web-dev-qa-db-ja.com

pam-mysqlを介してパスワードを変更しようとしたときのトークンエラー

私は現在、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 passwdgetent 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
  • 私のユーザーIDはDBでは1から始まりますが、システムでは5000から始める必要があります(5000 + id)。
  • /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に部分的に依存しているようです。構成で何かを見逃しましたか?

2
John WH Smith

さて、私はその解決策を見つけました。最初に:これに参加する人は誰でも勉強することを強くお勧めします 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モジュールは呼び出されませんでした。

2
John WH Smith