PHP script (or other webapp) to allow users to change their password

Tom Metro tmetro-blu-5a1Jt6qxUNc at public.gmane.org
Tue May 26 03:24:18 EDT 2009


Derek Atkins wrote:
> ...the sudo command was:
>  sudo (root) passwd $user
> 
> It's bad because:
> 
> 1) it didn't require knowledge of the existing user password
> 2) it could be used to reset ANY password for any user

I see your point.

This implementation still must have had to deal with some back-and-forth 
chat with the passwd program. How did it accomplish that, or did it just 
blindly pipe the password to passwd and hope for the best?


>> If the process is already running as $user, then su is a noop 
>> (effectively) and should be removed.
> 
> The process is running as user Apache.

Ah, so that's why the su is required, and the expect script must have 
incorporated a step to respond to the password prompt produced by su. I 
missed that.


>> a small wrapper program (C, Perl, PHP) that runs setUID to root and 
>> verifies that the supplied $user matches the real UID. That way a user 
>> can only change their own password. (Of course you'll want to validate 
>> the data you accept before passing it on to setpwent().)
> 
> Well, this is what I'm trying to accomplish via the PHP.

What I was describing was a separate program that you'd call from your 
PHP code. The purpose of it being separate is to 1. limit the scope of 
code that requires root, and 2. to provide an interface more friendly 
for automation than provided by passwd. You could, in fact, implement it 
by tweaking the source of passwd.

The underlying system call, setpwent(), requires root, so no matter how 
you slice it - using passwd or something else - you need some code to 
run as root. (passwd is setUID to root.)


>> Plan B might be to create an expect script that provides a more 
>> automation-friendly interface (like accepting the user and pass via 
>> STDIN, and returning a unique exit code for each failure case), while 
>> avoiding the use of temp files. Your PHP code could then call that.
> 
> Kinda hard to do that via PHP I think...

I don't follow. All the heavy lifting would be done in the expect 
script. The code you showed was an embedded expect script. I'm just 
saying that you could move that to an external file and make it a bit 
more sophisticated.

What I'm not sure about is how difficult it would be to make the expect 
script do what I described (plus adding the interaction with su). I tend 
to avoid specialty languages, like expect, as they inevitably have 
disappointing limitation compared to a general purpose language paired 
with a library. So if it was me, I'd use the Perl native expect library.

I took a look at what would be required to code this with the Perl 
Expect library, and it's doable, but a pain. The API isn't very clean 
(derived from the original expect and TCL), you don't get a good 
indication of whether the command executed successfully, error handling 
in general doesn't seem to be done well, you'd need to do a lot of 
testing to make sure you handled all the possible error messages from 
the two programs you are running, and any expect-like solution requires 
black magic with ptys under the hood. (I saw a few modules that were 
layered on top of the Expect module and provided marginally cleaner 
APIs, and IPC::Run that provides a far different API, but nothing that 
helps address the other problems above.)

It's a mess that I'd avoid, if you could. I'd take a look at modifying 
the source of passwd to accept its parameters from STDIN, and produce 
unique exit codes, or reimplement a minimalist passwd in Perl/C/PHP as a 
setUID root command with a similar interface, then call either from your 
PHP web UI.

What would be nice is to have some sort of simple remote procedure call 
library that could be layered over something like System V IPC for 
calling functions in a child process. Such a thing probably exists...

  -Tom

-- 
Tom Metro
Venture Logic, Newton, MA, USA
"Enterprise solutions through open source."
Professional Profile: http://tmetro.venturelogic.com/





More information about the Discuss mailing list