在使用 mod_python 运行的脚本中使用 pam_python
我想开发一个 Web 界面,允许 Linux 系统的用户执行与其帐户相关的某些任务。我决定在 Apache 上使用 Python 和 mod_python 编写网站的后端。为了对用户进行身份验证,我想我可以使用 python_pam 来查询PAM 服务。我改编了与模块捆绑在一起的 example 并得到了这个:
# out is the output stream used to print debug
def auth(username, password, out):
def pam_conv(aut, query_list, user_data):
out.write("Query list: " + str(query_list) + "\n")
# List to store the responses to the different queries
resp = []
for item in query_list:
query, qtype = item
# If PAM asks for an input, give the password
if qtype == PAM.PAM_PROMPT_ECHO_ON or qtype == PAM.PAM_PROMPT_ECHO_OFF:
resp.append((str(password), 0))
elif qtype == PAM.PAM_PROMPT_ERROR_MSG or qtype == PAM.PAM_PROMPT_TEXT_INFO:
resp.append(('', 0))
out.write("Our response: " + str(resp) + "\n")
return resp
# If username of password is undefined, fail
if username is None or password is None:
return False
service = 'login'
pam_ = PAM.pam()
pam_.start(service)
# Set the username
pam_.set_item(PAM.PAM_USER, str(username))
# Set the conversation callback
pam_.set_item(PAM.PAM_CONV, pam_conv)
try:
pam_.authenticate()
pam_.acct_mgmt()
except PAM.error, resp:
out.write("Error: " + str(resp) + "\n")
return False
except:
return False
# If we get here, the authentication worked
return True
我的问题是这个函数无论我在简单脚本中还是通过 mod_python 使用它,其行为都不相同。为了说明这一点,我编写了这些简单的案例:
my_username = "markys"
my_good_password = "lalala"
my_bad_password = "lololo"
def handler(req):
req.content_type = "text/plain"
req.write("1- " + str(auth(my_username,my_good_password,req) + "\n"))
req.write("2- " + str(auth(my_username,my_bad_password,req) + "\n"))
return apache.OK
if __name__ == "__main__":
print "1- " + str(auth(my_username,my_good_password,sys.__stdout__))
print "2- " + str(auth(my_username,my_bad_password,sys.__stdout__))
脚本的结果是:
Query list: [('Password: ', 1)]
Our response: [('lalala', 0)]
1- True
Query list: [('Password: ', 1)]
Our response: [('lololo', 0)]
Error: ('Authentication failure', 7)
2- False
但 mod_python 的结果是:
Query list: [('Password: ', 1)]
Our response: [('lalala', 0)]
Error: ('Authentication failure', 7)
1- False
Query list: [('Password: ', 1)]
Our response: [('lololo', 0)]
Error: ('Authentication failure', 7)
2- False
我不明白为什么 auth 函数在给定相同输入的情况下不返回相同的值。知道我哪里错了吗? 这里是原始脚本,如果可以帮助您的话。
多谢 !
编辑:好吧,我发现了错误。我以 root 身份运行该脚本。 mod_python 作为网络服务器的用户运行脚本。只有root才有权读取shadow。我不确定如何规避这个问题,但至少现在我知道问题是什么!
I would like to develop a web interface to allow users of a Linux system to do certain tasks related to their account. I decided to write the backend of the site using Python and mod_python on Apache. To authenticate the users, I thought I could use python_pam to query the PAM service. I adapted the example bundled with the module and got this:
# out is the output stream used to print debug
def auth(username, password, out):
def pam_conv(aut, query_list, user_data):
out.write("Query list: " + str(query_list) + "\n")
# List to store the responses to the different queries
resp = []
for item in query_list:
query, qtype = item
# If PAM asks for an input, give the password
if qtype == PAM.PAM_PROMPT_ECHO_ON or qtype == PAM.PAM_PROMPT_ECHO_OFF:
resp.append((str(password), 0))
elif qtype == PAM.PAM_PROMPT_ERROR_MSG or qtype == PAM.PAM_PROMPT_TEXT_INFO:
resp.append(('', 0))
out.write("Our response: " + str(resp) + "\n")
return resp
# If username of password is undefined, fail
if username is None or password is None:
return False
service = 'login'
pam_ = PAM.pam()
pam_.start(service)
# Set the username
pam_.set_item(PAM.PAM_USER, str(username))
# Set the conversation callback
pam_.set_item(PAM.PAM_CONV, pam_conv)
try:
pam_.authenticate()
pam_.acct_mgmt()
except PAM.error, resp:
out.write("Error: " + str(resp) + "\n")
return False
except:
return False
# If we get here, the authentication worked
return True
My problem is that this function does not behave the same whether I use it in a simple script or through mod_python. To illustrate this, I wrote these simple cases:
my_username = "markys"
my_good_password = "lalala"
my_bad_password = "lololo"
def handler(req):
req.content_type = "text/plain"
req.write("1- " + str(auth(my_username,my_good_password,req) + "\n"))
req.write("2- " + str(auth(my_username,my_bad_password,req) + "\n"))
return apache.OK
if __name__ == "__main__":
print "1- " + str(auth(my_username,my_good_password,sys.__stdout__))
print "2- " + str(auth(my_username,my_bad_password,sys.__stdout__))
The result from the script is :
Query list: [('Password: ', 1)]
Our response: [('lalala', 0)]
1- True
Query list: [('Password: ', 1)]
Our response: [('lololo', 0)]
Error: ('Authentication failure', 7)
2- False
but the result from mod_python is :
Query list: [('Password: ', 1)]
Our response: [('lalala', 0)]
Error: ('Authentication failure', 7)
1- False
Query list: [('Password: ', 1)]
Our response: [('lololo', 0)]
Error: ('Authentication failure', 7)
2- False
I don't understand why the auth
function does not return the same value given the same inputs. Any idea where I got this wrong ? Here is the original script, if that could help you.
Thanks a lot !
EDIT: All right I found the error. I was running the script as root. mod_python was running the script as the webserver's user. Only root has the right to read shadow. I am not sure how I will circumvent this, but at least now I know what is the problem !
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看来您必须启用 Apache 才能使用 PAM 身份验证。看看这个网站: http://www.debianhelp.co.uk/apachepam.htm
您可能也想看看这个网站:http://inming.net/? p=86
It seems like you have to enable Apache to use PAM authentication. Take a look at this site: http://www.debianhelp.co.uk/apachepam.htm
You might want to take a look at this site too : http://inming.net/?p=86