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