私は現在、Webホスティングサービス用のマシンを準備しており、MySQLを使用してすべてのユーザーを保存することにしました(他のサービスはすでにそれを使用しているため)。そのために、私は libnss-mysql および pam-mysql を使用しています。ただし、ほとんどのセットアップは機能していますが、passwd
を使用してユーザーのパスワードを変更しようとすると問題が発生します。
現時点では、ユーザー(INSERT INTO
)を作成し、su
を使用してこのユーザーとしてログインすることができます。マシンはパスワードの入力を求めず、ユーザーのシェルへのアクセスが直接与えられます。ただし、このユーザーとしてログインすると、passwd
は:で終わります。
$ passwd myuser
passwd: Authentication token manipulation error
passwd: password unchanged
MySQLのログによると、passwd
が呼び出されたときにクエリが実行されるため、MySQLとの接続に問題はありません。また、存在しないユーザーでpasswd
を呼び出そうとすると、適切なpasswd: user 'doesnotexist' does not exist
が得られます。 passwd
はユーザーを見つけますが、その情報を変更することはできません。 auth.log
ログファイルには次のように記載されています:
pam_unix(passwd:chauthtok): user "myuser" does not exist in /etc/passwd
pam_mysql - option verbose is set to "1"
pam_mysql - pam_sm_chauthtok() called.
pam_mysql - pam_mysql_open_db() called.
pam_mysql - pam_mysql_open_db() returning 0.
pam_mysql - pam_sm_chauthtok() returning 0.
pam_mysql - pam_mysql_release_ctx() called.
pam_mysql - pam_mysql_destroy_ctx() called.
pam_mysql - pam_mysql_close_db() called.
passwd -Sa
を呼び出してすべてのアカウントのステータスを取得すると、myuser
アカウントが表示されます。さらに、getent passwd
とgetent shadow
はどちらもmyuser
の有効なエントリを返します。
$ passwd -Sa
...
messagebus L 06/28/2014 0 99999 7 -1
mysql L 06/28/2014 0 99999 7 -1
myuser P 01/01/1970 0 99999 7 -1
$ getent passwd myuser
myuser:x:5001:5000:First Last:/home/members/myuser:/bin/bash
$ getent shadow myuser
myuser:$6$...:0:0:99999:7:::0
ただし、myuser
に関するエージング情報を要求する場合:
$ chage -l myuser
chage: user 'myuser' does not exist in /etc/passwd
概して :
su
はユーザーを検出し、すべての場合にパスワードなしのログインを実行します(rootの場合、そうでない場合はパスワードの入力を求められ、トークンエラーが発生します)。chage
はユーザーを見つけることができません; DBの代わりに/etc/passwd
を検索しているようです。passwd
はユーザーを検出しますが、編集しようとするとトークンエラーを返します。ここにいくつかの構成サンプルがあります:
/ etc/pam.d/common-account
account sufficient pam_unix.so
account required pam_mysql.so config_file=/etc/pam-mysql.conf
/ etc/pam.d/common-auth
auth sufficient pam_unix.so nullok_secure
auth required pam_mysql.so config_file=/etc/pam-mysql.conf
/ etc/pam.d/common-session
session sufficient pam_unix.so
session required pwam_mysql.so config_file=/etc/pam-mysql.conf
/ etc/pam.d/common-passwd
password sufficient pam_unix.so obscure sha512
password required pam_mysql.so config_file=/etc/pam-mysql.conf
/ etc/libnss-mysql.cfg
getpwnam SELECT username,'x',(5000+id),5000,CONCAT(firstname, lastname),CONCAT('/home/members/', username),'/bin/bash' \
FROM users \
WHERE username='%1$s' \
LIMIT 1
getpwuid SELECT username,'x',(5000+id),5000,CONCAT(firstname, lastname),CONCAT('/home/members/', username),'/bin/bash' \
FROM users \
WHERE (5000+id)='%1$u' \
LIMIT 1
getspnam SELECT username,password,0,'0','99999','7','-1','-1','0' \
FROM users \
WHERE username='%1$s' \
LIMIT 1
getpwent SELECT username,'x',(5000+id),5000,CONCAT(firstname, lastname),CONCAT('/home/members/', username),'/bin/bash' \
FROM users
getspent SELECT username,password,0,'0','99999','7','-1','-1','0' \
FROM users
getgrnam SELECT '%1$s','members',5000
getgrgid SELECT name,password,'%1$u'
getgrent SELECT 'members','members',5000
memsbygid SELECT username \
FROM users
gidsbymem SELECT 5000
/bin/bash
みんなのために。myuser
の$HOME
ディレクトリは/home/members/myuser
です。members
グループに属しており、そのGIDは5000です。/ etc/pam-mysql.conf
users.Host = localhost
users.database = mydatabase
users.db_user = root
users.db_passwd = root_password
users.table = users
users.user_column = username
users.password_column = password
users.password_crypt = 1
/ etc/nsswitch.conf
passwd: compat mysql
group: compat
shadow: compat mysql
私が試したこと:
myuser
のDBにパスワード(SHA512ハッシュ、$6$...
)を設定します。passwd -d
):myuser
が/etc/passwd
に見つからないことを通知します。アカウントをロックしようとしたり、パスワードの有効期限を強制したりしようとすると、同じことが起こります。passwd
を呼び出しても、変更はありません。su
の代わりに):認証トークン操作エラーが発生し、ログインプロンプトに返送されます。 SSHで接続しようとしたときも同じです(さらに論理的なパスワードの有効期限の警告)。私には、ユーザー管理の部分(アカウント/セッション?)はMySQLに正しくリンクされているように見えますが、パスワード管理一部は/etc/passwd
に部分的に依存しているようです。構成で何かを見逃しましたか?
さて、私はその解決策を見つけました。最初に:これに参加する人は誰でも勉強することを強くお勧めします PAMモジュールの基本 。これ本当には全体を理解するのに役立ちます。それでは、私のcommon-*
ファイルを見てみましょう。それらはすべて同じ構造を持っています:
facility required pam_unix.so [...]
facility sufficient pam_mysql.so [...]
さて、PAMモジュールについてもっと読んだ後、これは私にはばかげているように見えます。 PAM制御フラグに関するいくつかのドキュメントは次のとおりです。
required:モジュールが成功すると、チェーンの残りの部分が実行され、他のモジュールが失敗しない限り、要求が許可されます。モジュールに障害が発生すると、チェーンの残りの部分も実行されますが、要求は最終的に拒否されます。
sufficient:モジュールが成功し、チェーン内の以前のモジュールが失敗しなかった場合、チェーンはすぐに終了し、要求が許可されます。モジュールに障害が発生した場合、モジュールは無視され、チェーンの残りの部分が実行されます。
基本的に、私の構成では、PAMは次のように動作します:/etc/passwd
および/etc/shadow
によるUNIX認証はすべての場合に成功する必要があります。 MySQLルックアップも実行されますが、UNIX認証が失敗した場合、その結果は考慮されません。
この設定では、MySQL認証メカニズムはすべての状況で役に立たなくなります。適切な構成は次のようになります。
facility sufficient pam_mysql.so [...]
facility required pam_unix.so [...]
これは次のことを示しています:MySQL認証メカニズムで十分です。成功した場合、それ以上のメカニズムはテストされません。ただし、失敗した場合は、UNIX認証が成功する必要があります。UNIXユーザーよりもMySQLユーザーの数が多いため、最初にMySQLに対して認証する方が論理的です。
PAMとNSSの役割の違いに注意することも重要です。私のセットアップでは、NSS構成が正しいため、認証は完全に機能していました。 NSSは基本的なUNIX認証を処理しますが、notアカウント/セッション管理、またはサービス固有(SSH/FTP/...)接続も処理しません。これらはすべてPAMによって処理されます。この分離が、root
がMySQLユーザーとして接続できた理由です。NSSはエントリを検出しました。また、root
は、ユーザーのIDを取得するために何かに対して認証する必要がないためです。 、PAMモジュールは呼び出されませんでした。