3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援→開発戻り浦島太郎状態の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。

(.Net,ADSI)ActiveDirectoryでMemberOf属性に Domain Users がない

.NetからADSIを用いてActiveDirectoryのユーザ情報を取ってきてるんですが、ユーザの所属するグループの値が入っている MemberOf 属性に Domain Users がいません。

逆に、Domain Users の member にはデフォルトは全ユーザがいないといけないのに、Not Set になってます。

下記は ADSI Edit で Domain Users のオブジェクトを見たときのSSです。

で、Active Directory ユーザーとコンピュータからユーザアカウント情報をよく見ると、Domain Users がプライマリグループになってました。(513がDomain Usersを表してるようです)

調べると、プライマリグループはMemberOfやmemberに含まれない仕様のようです。

[ADSI] プライマリグループを取得する - ComponentGeek Article下記サイトには、このように書いてました。

ユーザのディレクトリオブジェクトにバインドすると、プロパティprimaryGroupIdにプライマリグループのSIDの一部(相対識別ID)が格納されています。プライマリグループのSIDを取得するには、属性objectSidのバイト値の最後4バイトをprimaryGroup属性値で置き換えることで取得します。

厄介な仕様ですね。

参考先のコピペになりますが、下記のように書けばプライマリグループのSIDを取得できます。(C#)

public GetADSI(){

DirectoryEntry mDrctEntry = new DirectoryEntry(@"LDAP://domaincontroller/DC=domainname,DC=jp", "administrator", "password" );

// LDAP検索オブジェクトを作成

DirectorySearcher drSearch = new DirectorySearcher(mDrctEntry);

// アカウントフィルターを設定 Userオブジェクトだけ取得するように

drSearch.Filter = "(ObjectCategory=user)";

 

// 検索する

SearchResultCollection scn = drSearch.FindAll();

if (scn == null || scn.Count <= 0) {

//なかった時

Utility.DispMessageBox(Utility.StrType.NotFoundUser);

return null;

}

 

//Userオブジェクト新規生成(Userオブジェクトはユーザアカウント情報を格納するエンティティクラスです)

foreach (SearchResult sResult in scn) {

if (sResult.Properties["primaryGroupId"].Count > 0) {

byte[] sid = CreatePrimaryGroupSID((byte[])sResult.Properties["objectSID"][0], (int)sResult.Properties["primaryGroupId"][0]);

usr.PrimaryGroupSID = SidToString2(sid);

}

}

}

 

///

/// userのprimaryGroupId属性値はプライマリグループの相対識別値のみ

/// 含まれているので、userのobjectSidのバイト値の最後の4バイトをprimaryGroupId

/// のバイト値で置き換えることで取得する。

///

///

///

public byte[] CreatePrimaryGroupSID(byte[] sid ,int primaryGroup) {

//byte[] sid = user.Properties["objectSid"][0] as byte[];

//int primaryGroup = (int)user.Properties["primaryGroupId"][0];

byte[] primaryGroupBytes = BitConverter.GetBytes(primaryGroup);

for (int i = 0; i < primaryGroupBytes.Length; ++i)

{

sid.SetValue(primaryGroupBytes[i], sid.Length - (primaryGroupBytes.Length - i));

}

return sid;

}

 

///

/// SID配列を文字列に。

///

///

///

public string SidToString2(byte[] sids){

//ポインタ定義

IntPtr pStringSid = IntPtr.Zero;

//APIを使って変換 第二引数ポインタに結果が入ってる

int ret = ConvertSidToStringSid(sids, ref pStringSid);

//結果となる文字列変数定義

string strSid = string.Empty;

if (ret != 0)

{

//ポインタの先にある文字列をマネージStringに変換。

strSid = Marshal.PtrToStringAnsi(pStringSid);

//メモリ解放

Marshal.FreeCoTaskMem(pStringSid);

}

return strSid;

}