slappasswd の動作をソース読んでかじる

```slappasswd -c "$1$%.8s"``` を実行した際の動作を、ソースを読んでかじった。OpenLDAPのバージョンは2.4.40。

## 動作の概要

ざっくり言って以下の処理をする。

1. ```$1$%.8s``` の ```%.8s``` を、ランダムな8文字のソルトに置き換える
2. パスワードと1.で生成したソルトを、```crypt(*key, *salt)```に渡す
3. cryptの返り値の先頭に、```{CRYPT}```をつける

## もうちょっと詳しく

### slappasswd.c

[OpenLDAP Source Repository - openldap.git/blob - servers/slapd/slappasswd.c](http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=servers/slapd/slappasswd.c;h=7b698628347d1582a87ebdb22cce59bc94764415;hb=e648bdc22cd654d371a224a88973f986f67ba499)

まず、 [openldap.git] / servers / slapd / slappasswd.c の int slappasswd() が呼ばれる。

l.128 で -cオプションをパースする。l.130の```lutil_salt_format```で、static変数に、オプションで渡した文字列が保存される。

```slappasswd.c
 128                 case 'c':       /* crypt salt format */
 129                         scheme = "{CRYPT}";
 130                         lutil_salt_format( optarg );
 131                         break;
```

l.259で```lutil_passwd_hash```を呼び出す。```&passwd```の構造体に、求める暗号化されたパスワードが入る。

```slappasswd.c
 259         lutil_passwd_hash( &passwd, scheme, &hash, &text );
```

### passwd.c

[OpenLDAP Source Repository - openldap.git/blob - libraries/liblutil/passwd.c](http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=libraries/liblutil/passwd.c;h=383f32d8ffe9c5553f21dffa9362719ac24fe603;hb=e648bdc22cd654d371a224a88973f986f67ba499)

```lutil_passwd_hash```は[openldap.git] / libraries / liblutil / passwd.c で宣言されている。

```passwd.c
 376 int lutil_passwd_hash(
 ...
 382         const struct pw_scheme *sc = get_scheme( method );
 ...
 399         return (sc->hash_fn)( &sc->name, passwd, hash, text );
```

l.382で、{CRYPT}に対応したパスワード暗号化の構造体を取ってきて、l.399でパスワード暗号化関数を呼び出す。

```passwd.c
171         { BER_BVC("{CRYPT}"),           chk_crypt, hash_crypt },
```

```get_scheme``` から、l.171で宣言されている構造体を受け取るので、```hash_crypt```が呼ばれる。

```passwd.c
1184 static int hash_crypt(
...
1205         if( lutil_entropy( salt, sizeof( salt ) ) < 0 ) {
1206                 return LUTIL_PASSWD_ERR; 
1207         }
1208
1209         for( i=0; i< ( sizeof(salt) - 1 ); i++ ) {
1210                 salt[i] = crypt64[ salt[i] % (sizeof(crypt64)-1) ];
1211         }
1212         salt[sizeof( salt ) - 1 ] = '\0';
...
1222         rc = lutil_cryptptr( passwd->bv_val, (char *) salt, &hash->bv_val );
```
l.1205-l.1212でソルトを生成する。l.1205で乱数をつくり、1.1209-1210でBase64で解釈できる文字列に変換する。```lutil_entropy```はpassword.cと同一ディレクトリ内の[entropy.c](http://www.openldap.org/devel/gitweb.cgi?p=openldap.git;a=blob;f=libraries/liblutil/entropy.c;h=fddeea4ab9a0e46d9bcc0d1ecf0798cdca5addd7;hb=e648bdc22cd654d371a224a88973f986f67ba499)で宣言されている。

l.1222で```crypt```にパスワードとソルトを引き渡す関数を呼ぶ。

```passwd.c
  98 lutil_cryptfunc *lutil_cryptptr = lutil_crypt;
...
 899 static int lutil_crypt(
...
 904         char *cr = crypt( key, salt );
```
```lutil_crypt_ptr``` の実体は ```lutil_crypt```で、その内部で```crypt```を呼ぶ。



## 参考

* [userPassword はあえて {CRYPT} - JULYの日記](http://d.hatena.ne.jp/JULY/20130223)
* [Man page of CRYPT](http://linuxjm.sourceforge.jp/html/LDP_man-pages/man3/crypt.3.html)
* [OpenLDAP, Source Repository](http://www.openldap.org/software/repo.html)
* [OpenLDAP, Public License for 2.4.40](http://www.openldap.org/software/release/license.html)