そろそろLDAPにしてみないか?

第18回OpenLDAPとSASL

最初に

前回までのFDS記事でSASLという言葉が出てきましたが、そういえばこれまでSASLについてあまり触れることがありませんでしたので、今回はOpenLDAPとSASLの関係についてお話ししておきます。

SASLとはSimple Authentication and Security Layerの略であり、簡単に言ってしまうと認証のためのフレームワークのようなものです。SASLを使用することにより、開発者は既存のライブラリや仕組みを再利用することができ、利用者にはチャレンジ・レスポンス認証などの安全な認証方式を提供することができます。

また、認証方式についてですが、SASLの中にはいくつかのメカニズムが用意されており、Kerberos、GSSAPI、DIGEST-MD5などいくつかの方式を利用することができるのですが、今回は検証環境の関係上、KerberosなどではなくDIGEST-MD5やCRAM-MD5を用いて安全な認証を実現します。

OpenLDAPとSASLの関係

たとえば、今まで通り-xオプションを使ったシンプル認証で

% ldapsearch -x -D “uid=nomo,ou=People,dc=example,dc=com" -w abc123 -b “dc=example,dc=com" "objectClass=*"

という検索を行う場合、クライアントからサーバに次のようなデータが送信されます。abc123という文字列が暗号化されていないことがわかるでしょうか図1⁠。

図1 Wiresharkでパケットをキャプチャした様子
図1 Wiresharkでパケットをキャプチャした様子

SASLを有効にすることで、前回の記事のAPOP同様、ネットワーク上に流れるパスワードを暗号化することができます。

それではさっそくSASLの設定です。/etc/openldap/slapd.confに以下を追記してslapdを再起動してください。

リスト1 slapd.confに追記する内容
sasl-regexp 
  uid=([^,]+),.*,cn=auth 
  uid=$1,ou=People,dc=example,dc=com 
password-hash {CLEARTEXT} 

クライアント側からSASL認証が要求されると、LDAPサーバは認証時に与えられたユーザ名を用いて、

uid=ユーザ名,cn=,cn=digest-md5,cn=auth 
(レルムが省略された場合はuid=ユーザ名,cn=digest-md5,cn=auth)

といったDNを生成します。ただし、実際にはこのようなエントリは存在しませんので、実際のDNにマッピングする設定が必要となります。そのための設定が

sasl-regexp 変換前DN 変換後DN

です。また、チャレンジ・レスポンス方式を使用する場合にはサーバ側に平文パスワード、または中間値が必要となりますので、エントリ中のuserPassword属性を常に平文で保存しておくため、

password-hash {CLEARTEXT} 

を設定しています。この設定を行うことで

% ldappasswd -U nomo -w abc123 -Y digest-md5 -s hoge

のようにパスワードを変更しても、それがデフォルトのSSHA形式でなく常に平文状態で格納されるようになります。

エントリの登録

今回は

sasl-regexp    uid=([^,]+),.*,cn=auth    uid=$1,ou=People,dc=example,dc=com 

という設定を行っているため、登録するエントリもuid=$1,ou=People,dc=example,dc=com に属している必要があります。

リスト2 サンプルエントリ
dn: dc=example,dc=c、om 
objectClass: dcObject 
objectClass: organization 
dc: example 
o: example 

dn: ou=People,dc=example,dc=com 
objectClass: organizationalUnit 
ou: People 

dn: uid=nomo,ou=People,dc=example,dc=com 
objectClass: inetOrgPerson 
sn: nomo 
cn: nomo 
uid: nomo 
userPassword: abc123 

エントリを登録できたら、後は次のように-Uオプションと-Yオプションを使用した検索が可能となります。

% ldapsearch -U proxy -Y digest-md5 -b "dc=example,dc=com" "objectclass=*" 

Wiresharkで確認してみても、平文パスワードは確認できず、サーバから発行されたチャレンジに基づきクライアントが毎回異なったレスポンスを返していることがわかります(図2⁠⁠。

図2 パケットをキャプチャした様子
図2 パケットをキャプチャした様子

Postfix SMTP AuthとSASL

OpenLDAP側でSASL設定を行っておくことにより、Cyrus-SASLのldapdbプラグインを利用することができるようになります。このプラグインは以前にも紹介したよう、FDSでは対応していないSASLプロキシ設定を行っておかなければなりません。

この概念としては、PostfixからロードされるSASLライブラリがプロキシアカウントであるproxyuserでLDAPサーバに接続し、そのproxyuserが代理で実際のユーザを検索しパスワードを照合する、といったイメージになります。そのため、次のようにプロキシ用のアカウントをLDAP上に登録しておきます。

今までとの違いは、saslAuthzTo属性です。この設定によって、proxyuserがuid=.*,ou=People,dc=example,dc=com以下から照合を行うことができるようになります。

リスト3 proxyuserアカウントの登録

dn: uid=proxyuser,ou=People,dc=example,dc=com 
objectClass: inetOrgPerson 
sn: proxyuser 
cn: proxyuser 
uid: proxyuser 
userPassword: proxy_passwd 
saslAuthzTo: dn.regex: uid=.*,ou=People,dc=example,dc=com 

また、saslAuthzTo属性を有効にするため、slapd.confには

sasl-authz-policy To 

を加えるとともに、proxyuserアカウントが実ユーザのパスワードを検索できるよう、

access to * 
  by self write 
  by dn="uid=proxyuser,ou=People,dc=example,dc=com" write 
  by * read 

といったACLを設定しておきます。あとはSMTP Auth用にsmtpd.confを作成します。

リスト4 /usr/lib/sasl2/smtpd.conf

pwcheck_method: auxprop 
auxprop_plugin: ldapdb 
ldapdb_uri: ldap://localhost 
ldapdb_id: proxyuser 
ldapdb_pw: proxy_passwd 
ldapdb_mech: DIGEST-MD5 
mech_list: LOGIN PLAIN CRAM-MD5 DIGEST-MD5 

駆け足になりましたが、これでsaslauthdを使わずLDAP認証が可能となりましたので、telnetコマンドなどで動作を確認してみてください。

最後に

OpenLDAPには以前紹介したSSLや今回紹介したようなSASLのように、さまざまな暗号化手法が用意されています。どのような手法を選択するかはユーザ次第となりますが、SSLを有効にした上でSASL認証を行ってもあまり意味が無さそうですし、LDAPのメリットである「高速な検索」が暗号化、復号化処理の負荷により失われてしまうかもしれません。

また、LDAPサーバ、クライアントはデータセンターなどの閉鎖的なネットワークに存在することも多く、このような場合にも通信経路を暗号化させる意味はそれほど無いでしょう。そのため、SSLやSASLを有効にする場合には、サーバとクライアントの経路、登録されているデータの機密性など考慮した上で適切な設定を行ってください。

たとえばインターネット越しにLDAP検索を行う場合でも、すでに経路がVPNなどで暗号化されていれば、通常SSLの必要もありません。ただし、検索速度を犠牲にしてでも二重、三重の暗号化を検討したいのであれば、それもまた自由です。

2008年最後の記事となってしまいましたが、来年もよろしくおつきあいください。

おすすめ記事

記事・ニュース一覧