我编写了一个调用bash
命令的 Python CGI 脚本,它需要测试主机上是否成功登录。
我该如何为此编写测试?
例如,我可以创建一个bash
脚本来针对主机上的注册用户测试给定的用户名和密码组合吗?
答案1
使用 PAM 是最好的解决方案。您可以编写小型 C 代码,或者安装 python-pam 包并使用 python-pam 包附带的 python 脚本。看/usr/share/doc/python-pam/examples/pamtest.py
答案2
测试用户是否可以登录的正确方法是以该用户的身份实际登录。
所以我建议使用 CGI 脚本expect
要运行su
,请传递密码并运行必须执行的命令。这是一个执行此操作的期望脚本草稿(警告:绝对未经测试,并且我对期望并不熟练)。替换为用户名、密码和命令(我写的是bob
、swordfish
和somecommand
);请务必正确引用。
spawn "/bin/su" "bob"
expect "Password:"
send "swordfish\r"
expect "^\\$"
send "somecommand"
expect -re "^\\$"
send "exit\r"
expect eof
如果你确实不想通过一层执行命令su
(例如因为你所做的事情必须由CGI进程本身执行),那么使用expect来运行命令true
并检查返回状态是否为0。
另一种方法是使用聚丙烯酰胺直接在您的应用程序中,通过Python 的 PAM 绑定。
答案3
这里引用了一种“C”、“Python”PAM 解决方案,让我也放上 perl 的解决方案:-)
#!/usr/bin/perl
use Authen::PAM;
use POSIX qw(ttyname);
$service = "login";
$username = "foo";
$password = "bar";
$tty_name = ttyname(fileno(STDIN));
sub my_conv_func {
my @res;
while ( @_ ) {
my $code = shift;
my $msg = shift;
my $ans = "";
$ans = $username if ($code == PAM_PROMPT_ECHO_ON() );
$ans = $password if ($code == PAM_PROMPT_ECHO_OFF() );
push @res, (PAM_SUCCESS(),$ans);
}
push @res, PAM_SUCCESS();
return @res;
}
ref($pamh = new Authen::PAM($service, $username, \&my_conv_func)) ||
die "Error code $pamh during PAM init!";
$res = $pamh->pam_set_item(PAM_TTY(), $tty_name);
$res = $pamh->pam_authenticate;
print $pamh->pam_strerror($res),"\n" unless $res == PAM_SUCCESS();
答案4
如果您有 root 访问权限,并且使用 md5 密码,并且您只需要比较密码,那么您可以使用 perl地穴::密码MD5模块。从 /etc/shadow 中获取 MD5 哈希值,去掉 $1$,然后拆分剩余的 $。字段 1 = 盐,字段 2 = 加密文本。然后对输入到 CGI 中的文本进行哈希处理,将其与加密文本进行比较,然后 Bob 就是你的叔叔。
#!/usr/bin/env perl
use Crypt::PasswdMD5;
my $user = $ARGV[0];
my $plain = $ARGV[1];
my $check = qx{ grep $user /etc/shadow | cut -d: -f2 };
chomp($check);
my($salt,$md5txt) = $check =~ m/\$1\$([^\$].+)\$(.*)$/;
my $pass = unix_md5_crypt($plain, $salt);
if ( "$check" eq "$pass" ) {
print "OK","\n";
} else {
print "ERR","\n";
}