phpでldapのパスワード更新

もうすごい適当。

phpによるLDAPのパスワード更新の簡単なやつが見つからなかったのでとりあえず書いた。

* パスワードのencode部分は参考にしました。 
https://github.com/koppor/phpLdapPasswd/blob/master/functions.php 

* サーバ的には phpinfo でLDAPが有効なことが前提です。 
要はここのが動けばいいです。 
http://www.php.net/manual/ja/ref.ldap.php

```php:phpldap.php
<?php

// ldap バインドを使用する
$ldapdn  = 'dc=ldap-server, dc=sample.jp';     // ldap rdn あるいは dn
$ldaprdn  = 'cn=Manager, ' . $ldapdn;   // ldap rdn あるいは dn
$ldappass = 'managerpass';  // パスワード

$ldap_user = 'hoge';
$ldap_newpass = 'hogehoge';

// ここLDAP設定により変わるので適当ですが、ちゃんと設定しないと動きません
$ldap_fulldn = 'uid='.$ldap_user. ',ou=People,'. $ldapdn;

echo date("Y/m/d H:i:s ") . "Connecting ...". "<br />";

// ldap サーバーに接続する
$ldapconn = ldap_connect("ldap-server.sample.jp")
 or exit("Could not connect to LDAP server.");

if ($ldapconn) {
 
    echo date("Y/m/d H:i:s ") . "Binding ...". "<br />";

    // ldap サーバーにバインドする
    $ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);

    echo date("Y/m/d H:i:s ") . "Binding resuls is " . $ldapbind . "<br />";

    // バインド結果を検証する
    if ($ldapbind) {
        echo date("Y/m/d H:i:s ") . "LDAP bind successful...";
    } else {
        echo date("Y/m/d H:i:s ") . "LDAP bind failed...";
        exit;
    }

    echo date("Y/m/d H:i:s ") . " Searching ...";

    // ユーザを検索するワード（ここでは後方一致）
    $person = $ldap_user;
    $filter = "(uid=$person*)";
    //$colmun = array("givenname", "mail", "userpassword");  // 取得するカラムを絞る場合

    $serchID = ldap_search($ldapconn, $ldapdn, $filter);
    echo date("Y/m/d H:i:s ") . "Search result is " . $serchID . "<br />";
    echo date("Y/m/d H:i:s ") . "Number of entires returned is " . ldap_count_entries($ldapconn, $serchID) . "<br />";
    
    // 上記で見つかったID達を取得
    $entries = ldap_get_entries( $ldapconn, $serchID );

    //print_r($entries);   

    //全件表示
     for ($i=0; $i<$entries["count"]; $i++) {
        // to show the attribute displayName (note the case!)
        echo $entries[$i]["uid"][0].":".$entries[$i]["mail"][0] . ":" . $entries[$i]["userpassword"][0] . ":" . $entries[$i]["dn"] . "<br />";
        
        // compareのテスト。基本的に意味なし。
        $result = ldap_compare( $ldapconn, $entries[$i]["dn"] , "userpassword", $entries[$i]["userpassword"][0] );
        if ( $result === -1 ) {
            echo date("Y/m/d H:i:s ") . "Error: " . ldap_error($ldapconn) . "<br />";
        } elseif ($result === true) {
            echo date("Y/m/d H:i:s ") . "Password correct." . "<br />";;
        } elseif ($result === false) {
            echo date("Y/m/d H:i:s ") . "Wrong guess! Password incorrect." . "<br />";
        }   
    }

    // SSHAパスワード生成.
    $encodedpass = encode_password( $ldap_newpass, "ssha");
    echo "encodedpass=".$encodedpass . "<br>";

    //パスワード更新！
    if (!(@ldap_mod_replace($ldapconn, "uid=$ldap_user,ou=People,dc=ldap-server,dc=sample.jp", array('userpassword' => $encodedpass)))) {
        exit("Unable to change password.");
    }
    //上記で生成したSSHAパスワード保存されているか確認
    $iSerchID = ldap_search($ldapconn, $ldapdn, $filter);
    $entries = ldap_get_entries( $ldapconn, $iSerchID );
    for ($i=0; $i<$entries["count"]; $i++) {
        echo $entries[$i]["uid"][0].":".$entries[$i]["mail"][0] . ":" . $entries[$i]["userpassword"][0] . ":" . $entries[$i]["dn"] . "<br />";
    }

    // close
    echo date("Y/m/d H:i:s ") . " Closing connection";
    ldap_close($ldapconn);    
} else {
    echo date("Y/m/d H:i:s ") . " failed connection";    
}

/**
 * パスワード生成
 * @password
 * @encoding
 * @see https://github.com/koppor/phpLdapPasswd/blob/master/functions.php #encode_password
 **/
function encode_password ($password = "", $encoding = "clear") {
    if (strcasecmp($encoding, "clear") == 0) {
        $encodedpass = $password;
    } elseif (strcasecmp($encoding, "crypt") == 0) {
        $encodedpass = "{CRYPT}".crypt($password);
    } elseif (strcasecmp($encoding, "md5") == 0) {
        $encodedpass = "{MD5}".base64_encode(pack("H*",md5($password)));
    } elseif (strcasecmp($encoding, "ssha") == 0) {
        mt_srand((double)microtime()*1000000);
        $salt = mhash_keygen_s2k(MHASH_SHA1, $password, substr(pack('h*', md5(mt_rand())), 0, 8), 4);
        $encodedpass = "{SSHA}".base64_encode(mhash(MHASH_SHA1, $password.$salt).$salt);
    } else {
        exit("Invalid password encoding method configured: $encoding");
    }

    return($encodedpass);
}

?>
```