[ADSI プログラミング] VBScript で SID(SDDL) を使用するには
ご無沙汰しております。 ILM 一家のパパ(お父さん)でございます。
暦上での秋は過ぎておりますが、猛暑の続く中、いかがお過ごしでしょうか。
とりあえず、ファミリーレストランでは秋メニューも始まっており、秋野菜の天ぷらなど食べては見たものの、なんか味気ないですね。本当の食欲の秋が、楽しみでなりません。
さて、久しぶりの投稿となりますが、今回は VBScript で ActiveDirectory の SID を扱う方法について、ご案内します。
Active Directory上では、user/group などのオブジェクトを SID(Security Identifier:セキュリティ識別子)で管理しています。SID は ドメイン内でユニークな値であり、user/group オブジェクトなどでは ObjectSID 属性として情報を保持していますが、格納値はバイナリ値であるため VBScript では直接扱う事が出来ません。
過去には、ADsSecurity.dll で機能提供されていた ADsSID オブジェクトにより、SID を VBScript を扱う事が可能でしたが、Active Directory サービス インターフェイス (ADSI) 2. 5 リソース キットの一部であった ADsSecurity.dll の提供も既に終了しており、この部分は VBScript のみで実装する必要がある状況となっています。
バイナリ値を扱う事が出来ない VBScript でどうするかというと、数値演算でバイナリ値を分割抽出し Hex関数で文字列化するという、少々強引な手段を用います。以下が関数例となります。
<SID(バイナリ) を数値演算で文字列(SDDL)に変換するスクリプト関数>
Function OctetString2String(byVal OctetStr)
dim result
dim j, loByte, hiByte
result = ""
for j = lbound(OctetStr) to ubound(OctetStr)
hiByte = ascb(midb(OctetStr,j+1,1))
loByte = hiByte mod 16
hiByte = hiByte \ 16
result = result & hex(hiByte) & hex(loByte)
next
OctetString2String = result
End Function
これを使ってどのような事ができるか、もう少し、具体的な例をご紹介しましょう。
信頼関係をもつ複数のドメイン間で、グループメンバーに信頼関係先ドメインのアカウントを追加したり、逆に信頼関係ドメインのアカウントを含むグループオブジェクトのメンバーを参照する場合、SID の直接操作が避けられません。これは、信頼関係先ドメインのアカウント(User/Group)については、SID の解決が行えないため対象アカウントの AdsPath 形式の情報のみでは
オブジェクトを識別する事ができないためです。
グループメンバーに信頼関係先ドメインのアカウントを追加するような操作では、以下のよう対象ユーザアカウントの SID を SDDL形式とすることで、直接 信頼関係ドメインのグループメンバーに追加する事が可能です。
グループ : jpdsilm1.extest.microsoft.com の testgroup1
ユーザー : jpdsilm2.extest.microsoft.com の testuser1
<スクリプト サンプル:グループメンバー追加>
Set objGroup = GetObject(LDAP://CN=testgroup1,OU=MyGroup,DC=jpdsilm1,DC=microsoft,DC=com)
Set objUser = GetObject(LDAP://CN=testuser1,CN=Users,DC=jpdsilm2,DC=extest,DC=microsoft,DC=com)
valSID = objUser.Get("objectSid")
strSID = OctetString2String(valSID)
Wscript.Echo "<Sid=" & strSID & ">"
objGroup.PutEx 3, "member", Array("<Sid=" & strSID & ">")
objGroup.SetInfo
Function OctetString2String(byVal OctetStr)
dim result
dim j, loByte, hiByte
result = ""
for j = lbound(OctetStr) to ubound(OctetStr)
hiByte = ascb(midb(OctetStr,j+1,1))
loByte = hiByte mod 16
hiByte = hiByte \ 16
result = result & hex(hiByte) & hex(loByte)
next
OctetString2String = result
End Function
<スクリプト サンプル:グループメンバー参照>
Set objADs = GetObject(LDAP://CN=testgroup1,OU=MyGroup,DC=jpdsilm1,DC=microsoft,DC=com)
For Each objMem In objADs.Members
If ( objMem.class = "foreignSecurityPrincipal" ) then
'該当オブジェクトドメインの SID 部分を取得
objVal = objMem.ObjectSid
strSID = OctetString2String(valSID)
Wscript.Echo "<Sid=" & strSID & ">"
Set objUser = GetObject("LDAP://jpdsilm2/<SID=" & strSID & ">")
Wscript.ECho objUser. sAMAccountName
End if
Next
Function OctetString2String(byVal OctetStr)
dim result
dim j, loByte, hiByte
result = ""
for j = lbound(OctetStr) to ubound(OctetStr)
hiByte = ascb(midb(OctetStr,j+1,1))
loByte = hiByte mod 16
hiByte = hiByte \ 16
result = result & hex(hiByte) & hex(loByte)
next
OctetString2String = result
End Function
いかがでしたでしょうか。
実はこの手法、以前に一家のお母さん(ういこさん)が投稿した、PrimaryGroup を参照する手法でも使っています。 他にも、ACL/ACE の操作でも流用できるかもしれませんね。
ご参考になれば、幸いです。
実娘が夏休みの宿題におわれている
~お父さん より~