NOTE: This is a
SupplementalDocument topic which is
not included with the official TWiki distribution. Please help maintain high quality documentation by fixing any errors or incomplete content. Put questions and suggestions concerning the
documentation of this topic in the
comments section below! Use the
Support web for problems you are having using TWiki.
PAM Authentication without Apache
Here's what I had to do to enable PAM authentication in a TWiki running on Lighttpd/FreeBSD. You'll need
security/sudo
and
security/checkpassword-pam
ports installed. TWiki runs under user
www.
auth include system
- /root/bin/checkpassword-pam.sh
#!/bin/sh
exec /usr/local/bin/checkpassword-pam "$@" 3<&0
%www ALL = (root) NOPASSWD: /root/bin/checkpassword-pam.sh
- twiki/lib/TWiki/Users/PAM.pm
package TWiki::Users::PAM;
use Assert;
use strict;
use TWiki::Users::Password;
use Error qw( :try );
use base qw( TWiki::Users::Password );
sub checkPassword {
my( $this, $login, $passU ) = @_;
ASSERT( $login ) if DEBUG;
if($login =~ /([^']+)/){
$login = $1;
}else{
return 0;
}
if($passU =~ /([^']+)/){
$passU = $1;
}else{
return 0;
}
if(`id -u '$login'` == 0){
return 0;
}
my $res=`/usr/bin/printf '%s\\0%s\\0time\\0' '$login' '$passU'|/usr/local/bin/sudo /root/checkpassword-pam.sh -s twiki echo 'SUCCESS'`;
warn "$login - $res";
if($res =~ /SUCCESS/){
return 1;
}else{
return 0;
}
}
1;
$TWiki::cfg{PasswordManager} = 'TWiki::Users::PAM';
--
Contributor: AndrewPantyukhin - 11 Dec 2007
Comments & Questions about this Supplemental Document Topic
I am a little concerned that:
my $res=`/usr/bin/printf '%s\\0%s\\0time\\0' '$login' '$passU'...
exposes the password (in $passU) in the arguments to printf where it can
be seen by anybody running ps(1).
I am not quite sure what is in $passU, but that looks dangerous.
Better would be something along the lines of:
open(CHECKPASS, '|/usr/local/bin/sudo /root/checkpassword-pam.sh -s twiki /bin/sh -c "exit 0" ');
print CHECKPASS "$login\000$passU\000time\000";
$exitval = close(CHECKPASS);
if ( $exitval != 0 ) {
return 1;
} else {
return 0;
}
so that the magic string sent to checkpasswd-pam doesn't show up on a command line anywhere.
(Note you need to catch SIGPIPE in case the open fails and add some error checking (like the return
status of open for example)). Then use the exit status of the command to determine pass/fail. You
could use the original method with a call to one of the IPC::open functions to allow reading from and
writing to the checkpasswd-pam subprocess.
Also, what is /root/cpw.sh? Is it /root/bin/checkpassword-pam.sh
given above?
--
JohnRouillard - 12 Dec 2007
nice one!
Is there a reason not to use one of the CPAN Pam modules rather than shelling out? like
Authen::PAM
or
Authen::Simple::PAM
?
--
SvenDowideit - 12 Dec 2007
They still need to be run under root (through sudo or a simple setuid wrapper). So it's either you fork perl or shell with a tiny C program (or, of course, a persistent service, which is a bit more complicated to implement). Since authentication is rarely a performance concern (except under DoS), it's just a matter of taste.
--
AndrewPantyukhin - 27 Dec 2007