私のpythonプログラムがpamを介して認証を処理できるようにする方法を探しています。これにはhttp://code.google.com/p/web2py/source/browse/gluon/contrib/pam.pyを使用しています。これは、Python プログラムがルートとして実行されている限りうまく機能しますが、これは理想的ではありません。私の意見。
ルート権限を必要とせずに、ユーザー名/パスワードの検証に pam を利用するにはどうすればよいですか?
私のpythonプログラムがpamを介して認証を処理できるようにする方法を探しています。これにはhttp://code.google.com/p/web2py/source/browse/gluon/contrib/pam.pyを使用しています。これは、Python プログラムがルートとして実行されている限りうまく機能しますが、これは理想的ではありません。私の意見。
ルート権限を必要とせずに、ユーザー名/パスワードの検証に pam を利用するにはどうすればよいですか?
短い:適切な Python PAM 実装を使用し、PAM を適切にセットアップします。
long : 正常な PAM セットアップでは、root
特権は必要ありません。最終的に、これは PAM が提供するものの 1 つである特権の分離です。
pam_unix
パスワードを確認する方法があります。(contrib サブディレクトリにあることに注意してください...)の PAM 実装がweb2py
正しいことをしていないようです。PAM の設定が正しくない可能性があります。これは、詳細な情報がないとわかりません。これは、オペレーティング システムとフレーバー/ディストリビューションにも大きく依存します。
Python 用の PAM バインディングが複数あります (残念ながら、標準ライブラリにはありません)。代わりにこれらを使用してください。また、構成については、たくさんのチュートリアルがあり、システムに適したものを見つけてください。
古い/間違っている、これをしないでください: root である必要はありません/etc/shadow
。このファイルには通常shadow
、読み取り専用アクセスのグループがあります。PAM
したがって、チェックを実行しているユーザーをshadow
groupに追加するだけです。
groupadd <user> shadow
トリックを行う必要があります。
最後に、私はpexpectを使用して、su--usernameを試してみました。少し遅いですが、かなりうまく機能します。以下の例は洗練されていませんが、あなたはその考えを理解するでしょう。
乾杯、
ジェイ
#!/usr/bin/python
import pexpect
def pam(username, password):
'''Accepts username and password and tried to use PAM for authentication'''
try:
child = pexpect.spawn('/bin/su - %s'%(username))
child.expect('Password:')
child.sendline(password)
result=child.expect(['su: Authentication failure',username])
child.close()
except Exception as err:
child.close()
print ("Error authenticating. Reason: "%(err))
return False
if result == 0:
print ("Authentication failed for user %s."%(username))
return False
else:
print ("Authentication succeeded for user %s."%(username))
return True
if __name__ == '__main__':
print pam(username='default',password='chandgeme')
モジュールが最良の選択だと思いpam
ますが、プログラムに直接埋め込む必要はありません。localhost のポートにバインドする、または UNIX ドメイン ソケットをリッスンし、同じホスト上の他のプロセスに対する PAM 要求を満たす単純なサービスを作成できます。次に、web2py アプリケーションをそれに接続して、ユーザー/パスワードの検証を行います。
例えば:
import asyncore
import pam
import socket
class Client(asyncore.dispatcher_with_send):
def __init__(self, sock):
asyncore.dispatcher_with_send.__init__(self, sock)
self._buf = ''
def handle_read(self):
data = self._buf + self.recv(1024)
if not data:
self.close()
return
reqs, data = data.rsplit('\r\n', 1)
self._buf = data
for req in reqs.split('\r\n'):
try:
user, passwd = req.split()
except:
self.send('bad\r\n')
else:
if pam.authenticate(user, passwd):
self.send('ok\r\n')
else:
self.send('fail\r\n')
def handle_close(self):
self.close()
class Service(asyncore.dispatcher_with_send):
def __init__(self, addr):
asyncore.dispatcher_with_send.__init__(self)
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.set_reuse_addr()
self.bind(addr)
self.listen(1)
def handle_accept(self):
conn, _ = self.accept()
Client(conn)
def main():
addr = ('localhost', 8317)
Service(addr)
try:
asyncore.loop()
except KeyboardInterrupt:
pass
if __name__ == '__main__':
main()
使用法:
% telnet localhost 8317
bob abc123
ok
larry badpass
fail
incomplete
bad
通常のシステム (UNIX スタイル) のログイン資格情報を使用する場合は違います。ある時点で、PAM ライブラリは root のみが読み取ることができるシャドウ ファイルを読み取る必要があります。ただし、LDAP やデータベースなどの別の方法で認証する PAM プロファイルを使用する場合は、root を必要とせずに機能します。
これが、さまざまなユーザー資格情報で URL パス スペースのさまざまな部分を実行する独自のフレームワークを開発した理由の 1 つです。ログイン部分 (のみ) は root として実行して PAM (システム) で認証できます。他のパス サブツリー ハンドラーは別のユーザーとして実行されます。
これにはPyPAMモジュールを使用しています。