没有root权限的python中的pam身份验证

我正在寻找一种让我的python程序通过pam处理身份验证的方法。 我正在使用http://code.google.com/p/web2py/source/browse/gluon/contrib/pam.py这个,只要我的python程序以root身份运行就不太理想了我的看法。 如何在不需要root权限的情况下使用pam进行用户名/密码验证?     
已邀请:
你不需要是root,你只需要能够读取
/etc/shadow
。该文件通常具有组
shadow
,具有只读访问权限。因此,您只需要在
shadow
组中添加运行
PAM
检查的用户。
groupadd <user> shadow
应该做的伎俩。     
我认为
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('rn', 1)
        self._buf = data
        for req in reqs.split('rn'):
            try:
                user, passwd = req.split()
            except:
                self.send('badrn')
            else:
                if pam.authenticate(user, passwd):
                    self.send('okrn')
                else:
                    self.send('failrn')

    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
    
最后,我最终使用pexpect并尝试su - 用户名。 它有点慢,但效果还不错。 下面的例子没有打磨,但你会得到这个想法。 干杯, 松鸦
#!/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')
    
如果您使用通常的系统(unix样式)登录凭据,则不会。在某些时候,PAM库必须读取只能由root读取的影子文件。但是,如果您使用通过备用方法(例如LDAP或数据库)进行身份验证的PAM配置文件,则它可以在不需要root的情况下工作。 这是我开发自己的框架的一个原因,该框架在不同的用户凭据下运行URL路径空间的不同部分。登录部分(仅)可以作为root运行以使用PAM(系统)进行身份验证,其他路径子树处理程序作为不同的用户运行。 我正在使用PyPAM模块。     
也许python-pam可以为你工作。     

要回复问题请先登录注册