- 記事一覧 >
- ブログ記事
AD(Active Directory)のuserParameters属性をphpで解読に成功
はじめに
先日の記事「AD(Active Directory)の中身を覗いてみた - ldapsearch,php,PowerShell」で、userParameters 属性を php で解析すると、文字化けが発生することを書きました。その原因が分かり、正常に表示することができました。ついでに、だいぶ理解が進みましたので、どうやって解析しているかのロジック面も書きたいと思います。
他、PowerShell に一部誤りが有ったことにも気づきましたので、そちらも紹介していきます。
【検証環境】
Windows Server 2019 Datacenter Desktop
ドメインコントローラーに昇格したActive Directory
FreeBSD13(本ブログ別記事「FreeBSD-13.0-RELEASEにapache2,php,postgresql,openldapをインストール」まで実施したサーバーです。)
OpenLDAP: ldapsearch 2.4.59
PHP 7.4.23
現象
AD(Active Directory)の中身を表示する php プログラムを作成しました。userParameters
という属性があるのですが、バイナリ値が入っていて、うまく表示できませんでした。
こちら(stackoverflow)のclass TSProperty
とfunction userParameters($userParameters){
で抽出してみましたが、どちらも同じ結果で、一部読めるところがありますが、文字化けしました。
userParametersをphpで解析してprint_rした結果:
修正前後の diff
AD(Active Directory)の中身を表示 php プログラム全体は、https://gist.github.com/itc-lab/030844f88869eb3fbd3712363e766035に置きました。
こちら(stackoverflow)のfunction userParameters($userParameters){
を以下のように修正しました。
diff:
@@ -20,6 +20,10 @@ function userParameters($userParameters)
|
|
20
20
|
$NameLength = hexdec(substr($userParameters, 0, 2));
|
21
21
|
$userParameters = substr($userParameters, 2);
|
22
22
|
$ValueLength = hexdec(substr($userParameters, 0, 2)) * 3;
|
23
|
+
if ($ValueLength == 0xc2 * 3) {
|
24
|
+
$userParameters = substr($userParameters, 2);
|
25
|
+
$ValueLength = hexdec(substr($userParameters, 0, 2)) * 3;
|
26
|
+
}
|
23
27
|
$userParameters = substr($userParameters, 2);
|
24
28
|
$Type = substr($userParameters, 0, 2);
|
25
29
|
$userParameters = substr($userParameters, 2);
|
@@ -30,10 +34,14 @@ function userParameters($userParameters)
|
|
30
34
|
$userParameters = substr($userParameters, $ValueLength);
|
31
35
|
switch ($PropName) {
|
32
36
|
case 'CtxWFHomeDir':
|
37
|
+
case 'CtxWFHomeDirW':
|
33
38
|
case 'CtxWFHomeDirDrive':
|
34
39
|
case 'CtxInitialProgram':
|
40
|
+
case 'CtxInitialProgramW':
|
35
41
|
case 'CtxWFProfilePath':
|
42
|
+
case 'CtxWFProfilePathW':
|
36
43
|
case 'CtxWorkDirectory':
|
44
|
+
case 'CtxWorkDirectoryW':
|
37
45
|
case 'CtxCallbackNumber':
|
38
46
|
$parameters[$PropName] = decode_PropValue($PropValue, true);
|
39
47
|
break;
|
原因とロジック詳細
16進数表記の場合、0x を先頭に付けて表記します。
ある一定の長さの値があると、途中で0xc2
が挿入されていて、これを無視する必要がありました。※valueLength が 128 (0x80
) 以上で 0xc2
が挿入される気がします。
解析対象のバイナリデータ(userParameters 属性値)を bin2hex(バイナリデータ → 16進数文字列表記に変換)
↓
0x1a080143747843666750726573656e74e394b5e・・・
↓
先頭から1バイト(2文字)取り出して、属性名の長さを得る。(取り出した分は除去。以降同様。)
↓
先頭から1バイト(2文字)取り出して、属性値の長さを得る。
↓
次の先頭から1バイト(2文字)取り出して、Type を得る。
↓
属性名の長さ分取り出して、文字列にして、属性名を得る。
↓
属性値の長さ分取り出して、文字列にして、属性値を得る。
↓
先頭から1バイト(2文字)取り出して、属性名の長さを得る。
↓
・・・と繰り返していると、
「先頭から1バイト(2文字)取り出して、属性値の長さを得る。」のところで、0xc2
が現れます。これは、10進数にすると、194 なのですが、本来の属性値の長さではなく、0xc2
の次の値が本来の属性値の長さになります。
例えば、0xc2a0
となっている場合、0xa0
が属性値の長さです。0xa0
は、160 のため、全然違います。
結果、194 が値の長さ(実際には、3倍しています。)だと思って、属性値を取り出そうとするため、文字列化できません。
属性値の長さを得るところで、0xc2
が現れたときに、無視して、次の値が正しい属性値の長さとみなすと、うまくいきました。
該当箇所ソースコード(コメント付き):
$parameters = array();
$userParameters = bin2hex($userParameters);//バイナリ→16進数表記の文字列に変換
$userParameters = substr($userParameters, 96);//16進表記の文字列から96文字以降を取り出す
$Signature = chr(hexdec(substr($userParameters, 0, 2)));//先頭2文字取り出す→10進数に変換して、対応するアスキーコードの文字にする。
$userParameters = substr($userParameters, 2);//$Signatureを得るために使った先頭2文字は捨てる。
if ($Signature != 'P') {//シグニチャがPではない場合、エラー(false)
return false;
}
$TSPropertyCount = hexdec(substr($userParameters, 0, 2));//先頭2文字を10進数にして$TSPropertyCountに入れる。
$userParameters = substr($userParameters, 2);//$TSPropertyCountを得るために使った先頭2文字は捨てる。
for ($i = 0; $i < $TSPropertyCount; $i++) {//$TSPropertyCount=12なら、12回実行。$TSPropertyCountは、結果の連想配列のキー($PropName)の数になる。
$NameLength = hexdec(substr($userParameters, 0, 2));//先頭2文字を10進数にして$NameLengthに入れる。
$userParameters = substr($userParameters, 2);//$NameLengthを得るために使った先頭2文字は捨てる。
$ValueLength = hexdec(substr($userParameters, 0, 2)) * 3;//先頭2文字を10進数にして3倍にして$ValueLengthに入れる。
if ( $ValueLength == 0xc2 * 3 ) {//$ValueLengthが 0xc2×3(194×3)、つまり、この時点の$userParametersの先頭2文字がc2だったとき
$userParameters = substr($userParameters, 2);//先頭2文字は捨てる。
$ValueLength = hexdec(substr($userParameters, 0, 2)) * 3;//$ValueLengthを取り直す。先頭2文字を10進数にして3倍にして$ValueLengthに入れる。
}
$userParameters = substr($userParameters, 2);//$ValueLengthを得るために使った先頭2文字は捨てる。
$Type = substr($userParameters, 0, 2);//先頭2文字を$Typeに入れる。※$Typeは使っていない。
$userParameters = substr($userParameters, 2);//$Typeを得るために使った先頭2文字は捨てる。
$PropName = substr($userParameters, 0, $NameLength);//$NameLengthの長さ分、$PropNameに入れる。
$PropName = hex2str($PropName);//16進表記文字列を文字に変換。(hex2strは、引数の16進表記文字列を二文字ずつ取り出してアスキーコードに対応した文字列にしていく関数。)
$userParameters = substr($userParameters, $NameLength);//$PropNameを得るために使った先頭から$NameLengthの長さ分は捨てる。
$PropValue = substr($userParameters, 0, $ValueLength);//$ValueLengthの長さ分、$PropValueに入れる。
$userParameters = substr($userParameters, $ValueLength);//$PropValueを得るために使った先頭から$ValueLengthの長さ分は捨てる。
switch ($PropName) {//$PropValueは、文字列化の方法がおのおの異なるため、caseで分ける。
case 'CtxWFHomeDir':
case 'CtxWFHomeDirW'://ASCIIコード→文字列の対象にするため、追加。
case 'CtxWFHomeDirDrive':
case 'CtxInitialProgram':
case 'CtxInitialProgramW'://ASCIIコード→文字列の対象にするため、追加。
case 'CtxWFProfilePath':
case 'CtxWFProfilePathW'://ASCIIコード→文字列の対象にするため、追加。
case 'CtxWorkDirectory':
case 'CtxWorkDirectoryW'://ASCIIコード→文字列の対象にするため、追加。
case 'CtxCallbackNumber':
$parameters[$PropName] = decode_PropValue($PropValue, true);//2番目の引数のtrueは、ASCIIコード→文字列にするという意味。
break;
case 'CtxCfgFlags1':
$parameters[$PropName] = parse_CtxCfgFlags1(decode_PropValue($PropValue));//CtxCfgFlags1は、バイナリ値なので、フラグの判定結果を返す。
break;
case 'CtxShadow':
$parameters[$PropName] = parse_CtxShadow(decode_PropValue($PropValue));//0:Disable,1:EnableInputNotify,2:EnableInputNoNotify,3:EnableNoInputNotify,4:EnableNoInputNoNotify
break;
default:
$parameters[$PropName] = decode_PropValue($PropValue);//ASCIIコード→文字列は行わず、16進数文字列を返す。
}
}
return $parameters;
正常出力例
以下のように正常に出力されるようになりました。(userParameters
部分は、json_encode
しています。)
# php ADSearch.php
dn: CN=山田 太郎,CN=Users,DC=ad,DC=contoso,DC=com;
accountexpires: 132854364000000000;
admincount: 1;
badpasswordtime: 132773714847543562;
badpwdcount: 0;
c: JP;
cn: 山田 太郎;
co: 日本;
codepage: 0;
company: 株式会社丸丸;
countrycode: 392;
department: 経営企画部;
description: 山田 太郎の説明;
directreports: CN=佐藤 部下,CN=Users,DC=ad,DC=contoso,DC=com;
displayname: TaroY;
distinguishedname: CN=山田 太郎,CN=Users,DC=ad,DC=contoso,DC=com;
dscorepropagationdata: 20211001094324.0Z; 20211001084813.0Z; 20211001084555.0Z; 20211001084454.0Z; 16010101000000.0Z;
givenname: 太郎;
info: 電話
メモ;
initials: James;
instancetype: 4;
l: 豊田市○○町;
lastlogoff: 0;
lastlogon: 132773705270944929;
lastlogontimestamp: 132773705270944929;
lockouttime: 0;
logoncount: 1;
logonhours: ff1f80ff1f80ff1f80ff1f80ff1f80ff1f80ff1f80;
mail: yamada.taro@contoso.com;
managedobjects: CN=グループX,CN=Users,DC=ad,DC=contoso,DC=com;
manager: CN=田中 上司,CN=Users,DC=ad,DC=contoso,DC=com;
memberof: CN=グループX,CN=Users,DC=ad,DC=contoso,DC=com;
msds-phoneticcompanyname: カブシキガイシャマルマル;
msds-phoneticdepartment: ケイエイキカクブ;
msds-phoneticdisplayname: ヤマダ タロウ;
msds-phoneticfirstname: タロウ;
msds-phoneticlastname: ヤマダ;
msds-supportedencryptiontypes: 0;
msnpcallingstationid: 000-111-2222;
msnpsavedcallingstationid: 000-111-2222;
msradius-framedinterfaceid: ::10;
msradius-framedipv6prefix: fe8e::;
msradius-framedipv6route: 2001:1:2:3::/64 :: 1;
msradius-savedframedinterfaceid: ::10;
msradius-savedframedipv6prefix: fe8e::;
msradius-savedframedipv6route: 2001:1:2:3::/64 :: 1;
msradiuscallbacknumber: 000-222-1111;
msradiusframedipaddress: -1062728523;
msradiusframedroute: 192.168.0.0/24 0.0.0.0 1;
msradiusservicetype: 4;
msrassavedframedipaddress: -1062728523;
msrassavedframedroute: 192.168.0.0/24 0.0.0.0 1;
name: 山田 太郎;
objectcategory: CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=contoso,DC=com;
objectclass: top; person; organizationalPerson; user;
objectguid: 2226c0e2-03df-4696-a09c-8c8e051b2b66;
objectsid: S-1-5-21-312109860-4223824132-3422679046-1103;
otherfacsimiletelephonenumber: 000-000-0001;
otherhomephone: 000-0000-1111;
otheripphone: 000-000-00002;
othermobile: 090-0000-1111;
otherpager: 000-0000-2222;
physicaldeliveryofficename: 山田 太郎の事業所;
postalcode: 000-0000;
postofficebox: 私書箱X;
primarygroupid: 513;
profilepath: \\192.168.12.219\profile\yamada.taro;
pwdlastset: 132775514426599728;
samaccountname: taro2000;
samaccounttype: 805306368;
scriptpath: C:\Windows\SYSVOL\domain\scripts\test.bat;
sn: 山田;
st: 愛知県;
streetaddress: 1-1;
telephonenumber: 090-0000-0000;
title: 部長;
useraccountcontrol: 512;
userparameters: {"CtxCfgPresent":"b00b1e55","CtxCfgFlags1":["F1MSK_INHERITAUTOCLIENT","F1MSK_AUTOCLIENTDRIVES","F1MSK_AUTOCLIENTLPTS","F1MSK_FORCECLIENTLPTDEF","F1MSK_DISABLEENCRYPTION"],"CtxShadow":"EnableInputNotify","CtxMinEncryptionLevel":"01","CtxWorkDirectory":"C:\\Windows\\system32","CtxWorkDirectoryW":"C:\\Windows\\system32","CtxWFHomeDir":"C:\\RDSprofile\\yamadashome","CtxWFHomeDirW":"C:\\RDSprofile\\yamadashome","CtxWFProfilePath":"\\\\192.168.12.219\\RDSprofile\\yamada.taro","CtxWFProfilePathW":"\\\\192.168.12.219\\RDSprofile\\yamada.taro","CtxInitialProgram":"C:\\Windows\\system32\\notepad.exe","CtxInitialProgramW":"C:\\Windows\\system32\\notepad.exe"};
userprincipalname: yamada.taro@ad.contoso.com;
usnchanged: 49305;
usncreated: 16408;
whenchanged: 20211007081802.0Z;
whencreated: 20210923082520.0Z;
wwwhomepage: https://www.contoso.com/;
文字列のデコードについて
各属性値について、文字列かフラグ値が収まっているのですが、文字列について、文字コードがそのまま入っているわけではありません。なぜ、こうなったのか分かりませんが、不可解な仕様になっています。
http://daduke.org/linux/userparameters.html に ASCII コード → バイナリへのエンコードの場合の解説があるのですが、これの逆のことをして、デコードしています。
つまり、3バイトのバイナリ →ASCII コード(1文字)の変換になります。
・3バイトずつ見ていきます。
・先頭4ビットの header は無視されます。
・control x, control y が 011010
の場合、本来の xxxx, yyyy から 10進数で言うと -9 されているため、逆に +9 します。
・xxxxyyyy と4ビットずつ合わせて1バイトの ASCII コードを得ます。
・php の chr 関数で文字にします。※chr 関数は、10進数を引数に取り、該当する ASCII コードの文字を返す関数です。例:chr(hexdec("0x5a"))
→0x5a は、90 で Z です。
該当部分のソースコード:
function decode_PropValue($hex, $ascii=false)
{
$decode_PropValue = '';
$blobs = str_split($hex, 6);
foreach ($blobs as $blob) {
$bin = decbin(hexdec($blob));
$control_y = substr($bin, 4, 6);
$nibble_y = substr($bin, 10, 4);
$control_x = substr($bin, 14, 6);
$nibble_x = substr($bin, 20, 4);
$byte = nibble_control($nibble_x, $control_x).nibble_control($nibble_y, $control_y);
if ($ascii) {
$decode_PropValue .= chr(bindec($byte));
} else {
$decode_PropValue = str_pad(dechex(bindec($byte)), 2, '0', STR_PAD_LEFT).$decode_PropValue;
}
}
return $decode_PropValue;
}
function nibble_control($nibble, $control)
{
if ($control == '011010') {
$dec = bindec($nibble);
$dec += 9;
return str_pad(decbin($dec), 4, '0', STR_PAD_LEFT);
}
return $nibble;
}
ちなみに、
CtxInitialProgram C:\Windows\system32\notepad.exe
CtxInitialProgramW C:\Windows\system32\notepad.exe
のように W 有り無しの属性名が有りますが、
これの違いは、例えば、"exe"の文字列の場合、
W 無しの方は、普通に"exe"
W 有りの方は、"[NULL 文字]e[NULL 文字]x[NULL 文字]e" と[NULL 文字]が入っています。
$blob:e380b0
$byte:00000000
chr(bindec($byte)):NULL
↓
$blob:e394b6
$byte:01100101
chr(bindec($byte)):e
↓
$blob:e380b0
$byte:00000000
chr(bindec($byte)):NULL
↓
$blob:e3a0b7
$byte:01111000
chr(bindec($byte)):x
↓
$blob:e380b0
$byte:00000000
chr(bindec($byte)):NULL
↓
$blob:e394b6
$byte:01100101
chr(bindec($byte)):e
PowerShell 版について
userParameters 属性の値を解読できる PowerShell で書かれたこちら(gist.github.com)を見つけました。
以下の要領で、ConvertFrom-UserParameter.ps1
をパスが通るところに置いて実行すると、userParameters 属性値が何も問題無く取り出されます。
PS C:\Users\Administrator> . ConvertFrom-UserParameter.ps1
PS C:\Users\Administrator> (Get-ADUser yamada.taro -Properties "userParameters").userParameters | ConvertFrom-UserParameter -ShowAll
(結果表示は略)
こちらは、0xc2
の問題は発生しません。Get-ADUser
コマンドレットから返ったバイナリ値が ldapsearch の時と異なり、加工済みのためです。
PS C:\Users\Administrator> (Get-ADUser yamada.taro -Properties "userParameters").userParameters > userParameters.bin
として、取得した userParameters.bin をバイナリエディタで確認すると、以下のようになっています。(CtxInitialProgramW の部分だけを抜粋)
00000440: 24 00 80 00
00000450: 01 00 43 00 74 00 78 00 49 00 6E 00 69 00 74 00
00000460: 69 00 61 00 6C 00 50 00 72 00 6F 00 67 00 72 00
00000470: 61 00 6D 00 57 00 34 33 30 30 33 61 30 30 35 63
00000480: 30 30 35 37 30 30 36 39 30 30 36 65 30 30 36 34
00000490: 30 30 36 66 30 30 37 37 30 30 37 33 30 30 35 63
000004A0: 30 30 37 33 30 30 37 39 30 30 37 33 30 30 37 34
000004B0: 30 30 36 35 30 30 36 64 30 30 33 33 30 30 33 32
000004C0: 30 30 35 63 30 30 36 65 30 30 36 66 30 30 37 34
000004D0: 30 30 36 35 30 30 37 30 30 30 36 31 30 30 36 34
000004E0: 30 30 32 65 30 30 36 35 30 30 37 38 30 30 36 35
000004F0: 30 30 30 30 30 30 0D 00 0A 00
ldap のデータ 0x24c28001437478496e697469616c50726f6772616d57
が
ldap : Get-ADUser
24 : 24 00
c2 : なし
80 : 80 00
01 : 01 00
437478496e697469616c50726f6772616d57 : 43 00 74 00 78 00 ...
のように、バイナリデータは WORD、ASCII データは UNICODE に変換されています。
つまり、PowerShell のConvertFrom-UserParameter.ps1
は、0xc2
を心配する必要もなく、上述の文字列のデコードについてのような文字列抽出処理も要らないのです。
PowerShell 版の誤りについて
php でuserParameters
の値を取り出せるようになって、PowerShell 版(ConvertFrom-UserParameter.ps1
)に誤りが有ることに気付きました。CtxCfgFlags1
の値(フラグ名文字列の配列にしたもの)が php で抽出したものと異なります。
php:
"CtxCfgFlags1":["F1MSK_INHERITAUTOCLIENT","F1MSK_AUTOCLIENTDRIVES","F1MSK_AUTOCLIENTLPTS","F1MSK_FORCECLIENTLPTDEF","F1MSK_DISABLEENCRYPTION"]
PowerShell:
PS C:\Users\Administrator> ((Get-ADUser taro2000 -Properties "userParameters").userParameters | ConvertFrom-UserParameter -ShowAll).CtxCfgFlags1
INHERITMAXDISCONNECTIONTIME
DISABLECCM
INHERITAUTOCLIENT
INHERITMAXIDLETIME
INHERITSECURITY
FORCECLIENTLPTDEF
フラグの内容が異なり、例えば、GUI の Active Directory ユーザーとコンピューター「ログオン時、クライアントのドライブに接続する」のチェックボックスを OFF にすると、以下の変化があります。
php: F1MSK_AUTOCLIENTDRIVES
が無くなる。
PowerShell: INHERITMAXDISCONNECTIONTIME
が無くなる。
「ログオン時、クライアントのドライブに接続する」とINHERITMAXDISCONNECTIONTIME
は言葉の意味が無関係で、php の方は関係有りそうなことから、PowerShell の方に誤りがありそうなことが分かります。
ConvertFrom-UserParameter.ps1
を修正し、以下の diff のように、
フラグ判定対象のバイナリ値のバイト並びを逆向きにして判定すると、php で出力したフラグと一致しました。
「バイト並びを逆向き」の例(値は適当で、あくまでイメージです。)
0x12345678
→ 0x78563412
diff:
@@ -97,6 +97,7 @@ https://msdn.microsoft.com/en-us/library/ff635169.aspx
|
|
97
97
|
BEGIN {
|
98
98
|
# values from https://msdn.microsoft.com/en-us/library/ff635169.aspx
|
99
99
|
$CtxCfgFlagsBitValues = @{
|
100
|
+
'INHERITINITIALPROGRAM' = 0x10000000
|
100
101
|
'INHERITCALLBACK' = 0x08000000
|
101
102
|
'INHERITCALLBACKNUMBER' = 0x04000000
|
102
103
|
'INHERITSHADOW' = 0x02000000
|
@@ -158,20 +159,22 @@ https://msdn.microsoft.com/en-us/library/ff635169.aspx
|
|
158
159
|
$Type = $BinaryReader.ReadUInt16()
|
159
160
|
|
160
161
|
$AttributeName = [System.Text.Encoding]::UNICODE.GetString($BinaryReader.ReadBytes($NameLength))
|
161
|
-
$AttributeData = $BinaryReader.ReadBytes($ValueLength)
|
162
162
|
Write-Verbose "AttributeName: $AttributeName"
|
163
163
|
|
164
164
|
if ($AttributeName -match 'CtxCfgPresent|CtxCfgFlags1|CtxCallBack|CtxKeyboardLayout|CtxMinEncryptionLevel|CtxNWLogonServer|CtxMaxConnectionTime|CtxMaxDisconnectionTime|CtxMaxIdleTime|CtxShadow|CtxMinEncryptionLevel') {
|
165
|
-
|
165
|
+
$AttributeData = ""
|
166
|
+
For ($i = 0; $i -lt $ValueLength; $i += 2) {
|
167
|
+
$AttributeData = [System.Text.Encoding]::UTF8.GetString($BinaryReader.ReadBytes(2)) + $AttributeData
|
168
|
+
}
|
166
169
|
$AttributeValue = [Convert]::ToInt32($AttributeData, 16)
|
167
170
|
|
168
171
|
if ($AttributeName -match 'CtxShadow') {
|
169
172
|
$AttributeValue = Switch ($AttributeValue) {
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
173
|
+
0 { 'Disable' }
|
174
|
+
1 { 'EnableInputNotify' }
|
175
|
+
2 { 'EnableInputNoNotify' }
|
176
|
+
3 { 'EnableNoInputNotify' }
|
177
|
+
4 { 'EnableNoInputNoNotify' }
|
175
178
|
default { $AttributeValue }
|
176
179
|
}
|
177
180
|
}
|
@@ -188,6 +191,7 @@ https://msdn.microsoft.com/en-us/library/ff635169.aspx
|
|
188
191
|
$ResultValues.Add($AttributeName, $AttributeValue)
|
189
192
|
}
|
190
193
|
elseif ($AttributeName -match 'CtxWFHomeDirDrive|CtxWFHomeDir|CtxWFHomeDrive|CtxInitialProgram|CtxWFProfilePath|CtxWorkDirectory|CtxCallbackNumber') {
|
194
|
+
$AttributeData = $BinaryReader.ReadBytes($ValueLength)
|
191
195
|
$AttributeValue = ''
|
192
196
|
For ($i = 0; $i -lt $ValueLength; $i += 2) {
|
193
197
|
$ValueChar = [Char][Byte]([Convert]::ToInt16([Char][byte]$AttributeData[$i] + [char][byte]$AttributeData[$i+1], 16))
|
※
フラグの一つ
'INHERITINITIALPROGRAM' = 0x10000000
も抜けていましたので、足しました。
ソースコード全体は、本家のを fork して、修正し、https://gist.github.com/itc-lab/3749188ce58ad803a97ae3f1f924c435 に置きました。
PowerShell:
PS C:\Users\Administrator> ((Get-ADUser taro2000 -Properties "userParameters").userParameters | ConvertFrom-UserParameter -ShowAll).CtxCfgFlags1
INHERITAUTOCLIENT
AUTOCLIENTDRIVES
AUTOCLIENTLPTS
DISABLEENCRYPTION
FORCECLIENTLPTDEF
php の結果と一致するようになりました。
その他、宣伝、誹謗中傷等、当方が不適切と判断した書き込みは、理由の如何を問わず、投稿者に断りなく削除します。
書き込み内容について、一切の責任を負いません。
このコメント機能は、予告無く廃止する可能性があります。ご了承ください。
コメントの削除をご依頼の場合はTwitterのDM等でご連絡ください。