[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: PAM perl module/XS

> Hello,
> Does anyone know of any PAM modules for Perl using XS?
> I am migrating a WWW-based password changer that initially used
> the Shadow Perl module.  Unfortunately, I haven't done XS yet,
> and now is not yet the time for me to learn :)  
> As a work-around I am writing a C program that will get the
> password from STDIN, pass it to the PAM system, and return
> success or failure in the exit code.
> Thanks,


	Last time I needed a web based change password system 
	I wrote it as a simple perl script with comm.pl (expect
	like library) and had my script to a telnet to localhost,
	login, issue a passwd command and feed it the old and 
	new passwords.

	(I prototyped it in expect -- but this customer wants
	everything in perl -- so the local SA staff can be focused
	on just one major scripting language).

	The benefits of this scheme:

		Nothing is SUID anything

		It works with any normal Unix regardless of
		shadow, pwdb, PAM, etc.

		It's scaleable to non-local host (using 
		stel or ssltelnet or ssh/slogin if you want
		to prevent LAN wire sniffing).

		It's trivial to use with SSL forms on any 
		SSL capable web daemon (i.e. Apache/Stronghold
		or Netscape Commerce Server).

	My version could handle most normal shell prompts and
	(especially) had a case for users who had /bin/passwd 
	as their login shell.

	Here what one of the betas looked like (I don't remember
	where I stashed a copy of the final working version):

#! /usr/bin/perl  

require "Comm.pl";
$Host = "localhost";
$User = <>;
$Password = <>;
$Newpass = <>;
$PS1 = '(\$|\%|#|:) $';	

$proc_handle = &open_proc( "telnet $Host" ) || die "open_proc failed";

( $match, $err, $before ) = &expect( $proc_handle, 3, 'login:' );
die "failed looking for login: err($err), before($before)" unless $match;
print $proc_handle "$User\n";
&expect( $proc_handle, 30, 'word:' ) || die "Didn't get a password prompt";
print $proc_handle "$Password\n";
&expect( $proc_handle, 20, $PS1 ) || die "no shell prompt";
print $proc_handle "\n/usr/bin/passwd\n";	
&expect( $proc_handle, 10, 'word:' ) || die "No current password prompt";
print $proc_handle "$Password\n";
&expect( $proc_handle, 10, ':' ) || die "No new password prompt";
print $proc_handle "$Newpass\n";
&expect( $proc_handle, 10, ':' ) || die "No repeat password prompt";
print $proc_handle "$Newpass\n";
&expect( $proc_handle, 10, $PS1 ) || die "no afterpasswd prompt";
print $proc_handle "exit\n";		# give us another shell prompt, please
&close_it( $proc_handle );

	You'll have to add a clause for the case where the target
	user's login shell is /bin/passwd.

	In my personal opinion this is more easily audited and 
	maintained than a C program for an end-user site.  

	At the same time I think it would be really neat if
	PAM's passwd program had an option that basically said --
	I want to change some users password only if "this" passwd
	(stdin) is valid -- where you could use a command like:

		echo -e $OLDPASSWD "\n" $NEWPASSWD \
			| passwd --batch --validatepw  $USER

	(where I've invented the --batch and --validatepw switches).
	Then I could use this for *any* case where I wanted to
	have a new protocol to change passwords (CGI, procmail/PGP
	smoke signal to digital interface, etc).

	For this to be useful it would have to be executable from 
	non-root accounts (so my program CGI, procmail recipe,
	or whatever is less vulnerable).  Naturally I'd have to 
	ensure that the passwd handling is immune to stack smashing
	buffer overflows and garbage input (but we already have to 
	do that).

	Doesn't anyone want to take this on?  (I don't like to touch
	SUID C programming -- and you shouldn't trust my "learning"
	experiences in the field).

	(And, yes, I'm aware that my echo ... | passwd command is
	a bad example since the $OLDPASSWD and $NEWPASSWD would be
	briefly exposed to 'ps' listings -- it was a sample for 

	Another neat feature would be if the --validatepw switch
	without the --batch would basically say: "return an
	error level if the password I pass to your stdin is not
	valid for the user specified"  

	This would be handy in CGI and similar remote job systems
	where you'd like to do do something like AUTHTYPE system -- 
	but your server doesn't support it.  (I know that Apache
	does have modules for supporting some flavors of
	AUTHTYPE system).

	The idea is for a "nobody" to be able to test if a 
	passwd if valid without getting a copy of the hashed
	password (which they could then export to a system 
	running crack).  Since this would be logged -- attempts
	to run a dictionary crack via this interface could be 
	detected and even (if you wanted) automatically prevented
	(maintain a small cache of tty's that have "recently" 
	issued these commands and use an exponential backoff delay).

Jim Dennis,                                info@mail.starshine.org
Proprietor,                          consulting@mail.starshine.org
Starshine Technical Services              http://www.starshine.org

        PGP  1024/2ABF03B1 Jim Dennis <jim@starshine.org>
        Key fingerprint =  2524E3FEF0922A84  A27BDEDB38EBB95A 

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index] []