Mac OSXにOpenLDAPを導入・設定する手順[P2]

##LDIFについて

以前に行ったの通りにLDAPのデータはLDIFという拡張子で定義されます。例として以下のように会社・グループ・ユーザーのデータを築いていきましょう。

```organization.ldif
dn: dc=localhost
objectclass: top
objectclass: domain
dc:localhost
description: Fictional example company
```

```backoffice_ou.ldif
dn: ou=backoffice, dc=localhost
objectclass: top
objectclass: organizationalUnit
ou: backoffice
description: Fictional example organizational unit
```

```bob.ldif
dn: uid=bob,ou=backoffice,dc=localhost
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: Mr Bob
sn: Mr
givenname: Bob
uid:Bob
ou:backoffice
description:BackOffice Manager
telephonenumber: 444-555-666
userpassword:{SSHA}Oc36F5PxDXTnJ30ni56FKIfHS9Kfo43c
```
bob.ldifを作成し先立ってbobのパスワードを以下のように生成してuserpasswordの値として記入する

```bash
$slappasswd -s ThisIsMyPassword
{SSHA}Oc36F5PxDXTnJ30ni56FKIfHS9Kfo43c
```

用意したファイルをldapaddでサーバーのデータベースに挿入されます：

```bash
#サーバー起動する
$sudo slapd -d3
#ファイルを挿入する
$ldapadd -x -D 'cn=Manager,dc=localhost' -w rootpwd -f organization.ldif
$ldapadd -x -D 'cn=Manager,dc=localhost' -w rootpwd -f backoffice.ldif
$ldapadd -x -D 'cn=Manager,dc=localhost' -w rootpwd -f bob.ldif
```

**挿入結果確認する**

```bash
$sudo slapcat

dn: dc=localhost
objectClass: top
objectClass: domain
dc: localhost
description: Fictional example company
structuralObjectClass: domain
entryUUID: 8a16e0aa-56a4-4c1b-b893-f47246c72680
creatorsName: cn=Manager,dc=localhost
createTimestamp: 20160928050917Z
entryCSN: 20160928050917.544333Z#000000#000#000000
modifiersName: cn=Manager,dc=localhost
modifyTimestamp: 20160928050917Z

dn: ou=backoffice,dc=localhost
objectClass: top
objectClass: organizationalUnit
ou: backoffice
description: Fictional example organizational unit
structuralObjectClass: organizationalUnit
entryUUID: 1b8fde10-e0c7-4482-95cd-49918ee55c62
creatorsName: cn=Manager,dc=localhost
createTimestamp: 20160928050919Z
entryCSN: 20160928050919.914712Z#000000#000#000000
modifiersName: cn=Manager,dc=localhost
modifyTimestamp: 20160928050919Z

dn: uid=bob,ou=backoffice,dc=localhost
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: Mr Bob
sn: Mr
givenName: Bob
uid: bob
ou: backoffice
description: BackOffice Manager
telephoneNumber: 444-555-666
userPassword:: e1NTSEF9T2MzNkY1UHhEWFRuSjMwbmk1NkZLSWZIUzlLZm80M2M=
structuralObjectClass: inetOrgPerson
entryUUID: aa7466f7-fc18-4d52-88ea-0e0fefd231da
creatorsName: cn=Manager,dc=localhost
createTimestamp: 20160928050926Z
entryCSN: 20160928050926.050189Z#000000#000#000000
modifiersName: cn=Manager,dc=localhost
modifyTimestamp: 20160928050926Z
```
**検索して確認する**

```bash
$ldapsearch -x '(uid=bob)'
```

**rootとして認証してみる**

```bash
$ldapwhoami -x -D 'cn=Manager,dc=localhost' -w rootpwd
dn:cn=Manager,dc=localhost
```

**bobアカウントで認証してみたら**

```bash
$ldapwhoami -x -D 'uid=bob,ou=backoffice,dc=localhost' -w ThisIsMyPassword
ldap_bind: Insufficient access (50)
```
なんで権限不足と言われたのかでびっくりしました。調査してみたらはっきりの回答は見つかりませんでしたがP1でslap.confを作成したときBDBというデーターベース種類を指定したのが覚え出しました。**BDB**のかわりに**LDIF**を指定してみたら以上の権限問題を解決できました。

```bash
$ldapwhoami -x -D 'uid=bob,ou=backoffice,dc=localhost' -w ThisIsMyPassword
'uid=bob,ou=backoffice,dc=localhost'
```

#PHPで認証モジュールを作成する

```php

class LDAPController extends Controller
{
    private static $me = null;

    private function __construct(){

    }

    public static function getInstance(){
        if(empty(self::$me)){
            self::$me = new LDAPController();
        }

        return self::$me;
    }

    public function checkLDAPLogin($user, $password){
    	
    	//$user     = $request->input('email');
    	
    	//$password = $request->input('password');
    	
        $ldap_host = Config::get("constants.LDAP.SERVER");
        $ldap_port = Config::get("constants.LDAP.PORT");
        $ldap_dn   = Config::get("constants.LDAP.ROOT_DN");

        $managerDN = Config::get("constants.LDAP.MANAGER_DN");
        
        $managerPassword = Config::get("constants.LDAP.MANAGER_PSW");

        Log::debug('$ldap_host='.$ldap_host);
        
        Log::debug('$ldap_port='.$ldap_port);
        
        Log::debug('$ldap_port='.$ldap_port);
        
        if(empty($ldap_port)){
            $ldap_port = 389;
        }

        $ldap = ldap_connect($ldap_host, intval($ldap_port));

        if(!$ldap){
            return json_encode(['success'=>false, 'message'=>"Could not connect to LDAP Server"]);
        }

        Log::debug("LDAP Connect Result:".print_r($ldap,true));

        if(Config::get("constants.LDAP.VERSION_3") == "1"){
            ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
        }
        ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);

        // verify user and password
        $bind = @ldap_bind($ldap, $managerDN, $managerPassword);

        Log::debug("LDAP Manager Bind:".print_r($bind,true));

        if($bind) {
            $userFilterStr = Config::get("constants.LDAP.USER_FILTER");
            
            $filter = str_replace("{}", $user, $userFilterStr);   //"(uid=" . $user . ")";
            
            Log::debug('LDAP Search $filter='.$filter);
            
            Log::debug('LDAP Search $ldap_dn='.$ldap_dn);
            
            
            $result = ldap_search($ldap, $ldap_dn, $filter);
            
            Log::debug("LDAP Search Result:".print_r($result,true));
            
            if(!$result){
                return json_encode(['success'=>false, message=> "Unable to search LDAP server"]);
            }
            
            Log::debug('$result'. print_r($result,true));
            
            $entries = ldap_get_entries($ldap, $result);
            
            Log::debug("LDAP Search Entries:".print_r($entries,true));

            if(empty($entries) || !isset($entries[0]) || !isset($entries[0]['dn'])){
                return json_encode(['success'=>false, 'message'=>"Invalid user"]);
            }

            Log::debug("LDAP Connect password:".$password);
            
            Log::debug("LDAP Connect entries:".$entries[0]['dn']);
            
            $bind = @ldap_bind($ldap,$entries[0]['dn'], $password);
            
            ldap_unbind($ldap);

            Log::debug($entries[0]);
            
            if($bind){
                return json_encode(['success'=>true , 'data'=> $entries[0]]);
            }else{            	
                return json_encode(['success'=>false, 'message'=>"Invalid user"]);
            }
        } else {
        	return json_encode(['success'=>false, 'message'=>"Invalid manager user"]);
        }
    }
}

```
:)