phpでのLDAPS接続方法(LDAP over SSL)

#初めに
PHPにてActive Directoryのユーザー作成時、パスワードも一緒に設定するには、通常のLDAP接続では行えず、LDAPS(LDAP over SSL)での接続を求められた為、今回記事にさせて頂きました。
正直何度も躓いてやっと出来たってレベルなので、意味として完全に理解している訳でもないので、この方法で絶対って訳ではないと思うので悪しからず。
ただググっている中で同様に躓いている方がかなりいるみたいだったので、方法の一つとして今回記事としてまとめさせて頂きます。

#開発環境
php5.6.15
Apache/2.4.6 (CentOS)
Microsoft Windows Server 2012 R2 Standard

opensslのインストールがまだの方は、インストールして下さい。

#Active Directory上での設定
①スタート⇒サーバーマネージャー⇒管理⇒役割と機能の追加⇒説明を読んで次へ
【インストールの種類】役割ベースまたは機能ベースのインストール
【サーバーの選択】サーバープールからサーバーを選択⇒LDAPS接続したいサーバーを選択して次へ
【サーバーの役割】Active Directory Certificateをチェックして次へ⇒管理ツールを含めるにチェックを入れたまま次へ
【機能】そのまま次へ
【AD CS】説明を読んで次へ
【役割サービス】そのまま次へ
【確認】インストール
【結果】インストールが完了したら閉じる

②サーバーマネージャー⇒！マークがついてるフラグマーク選択⇒対象サーバーにActive Directory証明書サービスを構築するを選択
【資格情報】任意の資格情報に変更して次へ
※デフォルトではログインユーザーになっている。今回エンタープライズCAをセットアップするので、資格情報はEnterprise Adminsグループに所属しているユーザーにする事。
※グループの確認「Active Directory ユーザーとコンピューター」⇒該当ユーザーをダブルクリックして、所属するグループ覧より確認。資格情報に選択したいユーザーが含まれていなかったら、追加から「Enterprise Admins」を追加する
【役割サービス】証明機関にチェックを入れて次へ⇒エンタープライズCAにチェックを入れて次へ
【CAの種類】ルートCAにチェックを入れて次へ
【秘密キー】新しい秘密キーを作成するにチェックを入れて次へ
【暗号化】SHA1を選択して次へ
【CA名】そのまま次へ
【有効期間】そのまま次へ
【証明書データベース】次へ
【確認】構成
【結果】構成に成功したら閉じる

③ADサーバ側にて、下記内容をテキストエディタに入力の上、保存。Subjectの部分はユニークなので、環境に変えて変更する。

```
;----------------- Request.inf ----------------- 
[Version] 
Signature=$Windows NT$ 

[NewRequest]
Subject = CN=sample.com ; 
PrivateKeyArchive=false
KeySpec = 1 
KeyUsage = 0xa0
Providertype = 12
RequestType = pkcs10
ProviderName = Microsoft RSA SChannel Cryptographic Provider
KeyLength = 2048
SMIME = TRUE
MachineKeySet = true
Exportable = TRUE

[EnhancedKeyUsageExtension] 
OID=1.3.6.1.5.5.7.3.1 ; this is for Server Authentication 

[RequestAttributes]
CertificateTemplate = WebServer
;-----------------------------------------------
```

④コマンドプロンプト(管理者にて実行)⇒Request.reqファイルを保存したいディレクトリまで移動して、下記コマンド実行
```cd 保存したいパス```
・base64でRequest.reqファイルにエンコード
```certreq -new Request.inf Request.req```
```certreq.exe```
・証明書を発行
```certreq -submit Request.req Request.cer```
※上記コマンドを実行すると、Request.rspというファイルも作成されますが、そちらは不要なので削除して頂いて問題ありません。
⑤certlm.mscを管理者にて実行
⑥証明書 -ローカルコンピューター-⇒個人⇒証明書⇒証明書名⇒すべてのタスク⇒エクスポート
⑦証明書のエクスポートウィザード画面にて、次へ⇒はい、秘密キーをエクスポートします⇒Personal Infomation Exchange - PKCS #12(.PFX)を選択⇒「証明のパスにある証明書を可能であればすべて含む」「すべての拡張をエクスポートする」にチェック(正しくエクスポートされたときは秘密キーを削除するはチェックしない)⇒パスワードにチェックを入れて、パスワードを入力して次へ⇒ファイル名を入力して、pfxファイルにて保存して完了
⑧mmc.exeを管理者にて実行⇒ファイルよりスナップインの追加と削除を選択⇒スナップイン側は証明書を選択して追加
㈯証明書スナップイン画面にて、サービスアカウント⇒別のコンピューターで接続したいホスト名を入力して次へ⇒Active Directory Domain Servicesを選択して完了
⑨コンソールルート(ホスト名)⇒ホスト名NTDS個人⇒すべてのタスク⇒インポート⇒次へ⇒先ほどエクスポートしたpfxファイルを選択して次へ⇒パスワードを入力⇒「このキーをエクスポート可能にする」「すべての拡張プロパティを含める」にチェックを入れて次へ⇒証明書をすべて次のストアに配置するにチェックして、参照は個人を選択して次へ⇒同様の手順で発行したRequest.cerファイルもmmc.exeを用いてインストール⇒完了
⑩これでldapsに接続する環境は整ったはずなので、ldp.exeを管理者にて実行し⇒接続を選択⇒サーバ部分にホスト名、ポートには636番、SSLにチェック(コネクションレスはチェック不要)を入れてOK⇒接続出来ればbindも試してみる。

接続もしくはbindに失敗した場合、どこかが間違えてる。もしくはこの記事が間違えてるので、別の記事を参考にした方がいいかも(´・ω・`)

#PHP
```
<?php
	$ldappass = 'TEStpaSS010';  // パスワード
	putenv('LDAPTLS_REQCERT=never') or die("couldn't setup reqcert-environment...");

	$ldapConn = ldap_connect('ldaps://HOSTNAME:636') or die("Could not connect to LDAP server");

	ldap_set_option($ldapConn, LDAP_OPT_PROTOCOL_VERSION, 3) or die("couldn't set protocol version...");
	ldap_set_option($ldapConn, LDAP_OPT_REFERRALS, 0) or die("couldn't set referrals...");

	$ldapbind = ldap_bind($ldapConn, 'CN=sample.admin,OU=test,DC=sample,DC=com', $ldappass);

	// バインド結果を検証する
	if (!$ldapbind) {
		echo LDAPS bind 失敗;
	} else {
		// ユーザー情報
		$strDn = "CN=test.sample,OU=test,DC=sample,DC=com;
		$info["cn"] = "test.sample";
		$info["sn"] = "テスト;
		$info["givenname"] = "サンプル";
		$info["displayname"] = "テスト サンプル";
		$info["msDS-PhoneticDisplayName"] = "てすと さんぷる";
		$info["msDS-PhoneticLastName"] = "てすと";
		$info["msDS-PhoneticFirstName"] = "さんぷる";
		$info["name"] = "test.sample";
		$info["UserPrincipalName"] = "test.sample@sample.com"
		$info["mail"] = "test.sample.com";
		$info["objectclass"][0]	= "top";
		$info["objectclass"][1]	= "person";
		$info["objectclass"][2]	= "organizationalPerson";
		$info["objectclass"][3]	= "user";
		$info["UserAccountControl"] = 512;
		$pwd = 'Pass0101';
		$newPassword = '"' . $pwdtxt . '"';
		$newPass = iconv( 'UTF-8', 'UTF-16LE', $newPassword ); 
		$info['unicodePwd'] = $newPass;

		$bool = ldap_add($ldapConn, $strDn, $info);

        echo '新規ユーザーを作成しました';
```
パスワードの変更を行うフィールドはunicodePwdになる。

#参考サイト
http://php.net/manual/ja/function.ldap-connect.php
http://lightmaterial.blogspot.jp/2008/04/phpldapactivedirectory-3.html
http://d.hatena.ne.jp/fezg00/20110118/1295279007
https://blog.putise.com/ca%E8%AA%8D%E8%A8%BC%E5%B1%80%E3%81%AE%E4%BD%9C%E6%88%90%E6%96%B9%E6%B3%95%E3%80%82windows-server%E3%81%A7ad%E9%80%A3%E6%90%BA%E3%81%97%E3%81%9F%E8%A8%BC%E6%98%8E%E6%9B%B8/
ありがとうございました！

#最後に
正直間違えている点も普通にあると思いますので、詳しい方がいましたらご指摘お願いしますm(_ _)m
なので本気でLDAPS接続出来なくて困っているという方はこの記事を鵜呑みにせず、あくまで参考程度に考えて下さい。