【IDM】パスワード同期機能の有効活用 その3 ~ unixUserPassword 属性から暗号化されたパスワードを取得する

本日、健康診断に行ってきました。健康診断...実は苦手でして...

いい歳して恥ずかしい話ですが....子供のころから、わきの下とわき腹が弱いのです。なので苦手なのは心電図...それに輪をかけてつらかったのは「腹部エコー検査」なるもの...。なんか、先のツルツルのヤツを使って、わきの下とかわき腹をしつこいくらいにグリグリされました。これは、もう、拷問としか言いようがありません。

ということで、「わきの下とわき腹が弱いですが 何か?」 コミュニティを作り、医療機器業界に「わき腹非接触検査機器の開発」を働きかけると同時に、わきの下とわき腹がくすぐったくならない禁断の呪文を開発したいなぁと思う、今日この頃です。同士募集です。

それはさておき、以下の続きとなる その3 です。

今回は、unixUserPassword 属性から、NIS用に暗号化されたパスワードを取り出します。msSFU30userPassword と違い、ちょっとコツがいります。

まずは、取り出しもとの unixUserPassword がいかなる特徴を持っているのか、見てみることにします。

ということで、スキーマツールを開きましょう。

Windows Server 2008 でのスキーマツールの開き方は従来通りです。以下のコマンドをコマンドプロンプトから入力後、mmc のツナップインに「Active Directory スキーマ」を追加してください。

c:>regsvr32 schmmgmt.dll

スキーマツールを起動したら、属性一覧の中から「 unixUserPassword 」 を探して、プロパティを開いてみてください。

注意していただきたいのは、上記の赤丸の部分です。

  • オクテット文字列である
  • 複数値である(戻り値がアレイ形式である)

オクテット文字列とは、文字列を1文字ごとに8ビットのバイナリ形式で保存する形式です...うーん、あたりまえですね。説明よりも、以下をご覧ください。unixUserPassword 属性に格納されている値を ADSI Edit で表示したものです。  一見、何が格納されているかわからないですね。

上のバイナリ値の最初の「 01001101 」を 10進数に変換すると 77 になります。77...何か心当たりありませんか? 子供の頃に食べたアイスクリームのような....そう、「M」のアスキーコードです。

では、次の 00110111 はどうでしょう?10進にすれば 55 。これは、「7」ですね。子供の頃から そういう教育をされてきた私にとっては朝飯前です。

といった感じで見ていくと、上記は「 M7hlyUsc6diZ. 」 となり、DES で暗号化されたパスワードだなぁということがわかります。

そんなわけで、スクリプトで取得するには以下のようになります。VBScript で書かれているので、拡張子を vbs として保存してください。

strDomain = "dc=example64,dc=jp"strUserName = "testuser001"

Set objConnection = CreateObject("ADODB.Connection")objConnection.Open "Provider=ADsDSOObject;"Set objCommand = CreateObject("ADODB.Command")objCommand.ActiveConnection = objConnectionobjCommand.CommandText = _        "<LDAP://" & strDomain & ">;" & _        "(&(objectCategory=person)(objectClass=user)" & _        "(sAMAccountName=" & strUserName & "));" & _        "sAMAccountName,unixUserPassword;" & _        "subtree"Set objRecordSet = objCommand.Execute

Do Until objRecordset.EOF

   arrUNIXUSERPASSWORD = objRecordset.Fields("unixUserPassword")  ' 取得したパスワードを arrUNIXUSERPASSWORD に格納

   For i = 1 To LenB(arrUNIXUSERPASSWORD(0))  ' arrUNIXUSERPASSWORDはアレイ値なので、(0) で1番目の値を取り出す

       strA = MidB(arrUNIXUSERPASSWORD(0), i, 1) ' MidB で1バイトずつ取り出し       strB = AscB(strA)   ' いったんアスキーコードにしてから       strUnixUserPassword = strUnixUserPassword & Chr(strB) ' 元の文字に戻してあげる

   Next

   objRecordset.movenext

Loop

wscript.echo strUnixUserPassword

 

上記のように、MidB、AscB、Chr(またはChrB)を使うというコツはいりますが、なれればオクテット値なんて怖くありません。

さて、こうして取り出した値をどうやって OpenLDAP に同期するのか...

ひとまずすぐに思いつくのは perl の Net::LDAP です。これは実績もあります。

まだ、ADSI を試してみたことは無いのですが、どなたか試された方いらっしゃいますか?

こんな方法が簡単!という案があれば是非ともご連絡ください。blog にてご紹介させていただきます。

ちなみに、KBには、以下のような情報が公開されています。次回は、以下について解説をつけたいと思います。

INFO: How to Use ADSI to Query a Third-Party LDAP Server
https://support.microsoft.com/kb/251195/en-us