Front page | perl.perl5.porters |
Postings from March 2000
WHOA THERE! Somebody went and broke all the getpw functions!
Thread Next
From:
Tom Christiansen
Date:
March 18, 2000 06:47
Subject:
WHOA THERE! Somebody went and broke all the getpw functions!
Message ID:
23330.953390850@chthon
% grep '\$dir,\$shell' perl3.0/perl.man.?
perl.man.2: $quota,$comment,$gcos,$dir,$shell) = getpw.\|.\|.
% grep '\$dir,\$shell' perl4.036/man1/perl.1
$quota,$comment,$gcos,$dir,$shell) = getpw.\|.\|.
% grep '\$dir,\$shell' perl5.001m/pod/perlfunc.pod
$quota,$comment,$gcos,$dir,$shell) = getpw*
% grep '\$dir,\$shell' perl5.002/pod/perlfunc.pod
$quota,$comment,$gcos,$dir,$shell) = getpw*
% grep '\$dir,\$shell' perl5.003/pod/perlfunc.pod
$quota,$comment,$gcos,$dir,$shell) = getpw*
% grep '\$dir,\$shell' perl5.004/pod/perlfunc.pod
$quota,$comment,$gcos,$dir,$shell) = getpw*
% grep '\$dir,\$shell' perl5.005/pod/perlfunc.pod
$quota,$comment,$gcos,$dir,$shell,$expire) = getpw*
% grep '\$dir,\$shell' perl5.006/pod/perlfunc.pod
$quota,$comment,$gcos,$dir,$shell,$expire) = getpw*
*NOW* I know why my sysadmin scripts have been mysteriously crapping
out. You went and changed the last return value from getpw*()!
Hello? Hello? This code has worked for a *long* time:
@pwent = getpwnam($whoever);
$shell = pop(@pwent) || '/bin/sh';
So has this, although not for *quite* so long
$shell = (getpwnam($whoever))[-1] || '/bin/sh';
Well, now it doesn't; it reports that all users on my system now
have a shell of '/bin/sh'. Why? I have pw_expire but I don't use
it, so my "expires" field is 0.
That perl3/perl.man.2 file is dated October 29th, 1989. That's a
very, ver, very long long-standing behavior to just go breaking
like this. I can't understand how this isn't a bug. Yes, I
understand what you're trying to do, but I don't think you did the
right thing, because you broke old code. And you didn't even tell
us about it! It's not in the v5.4 perldelta page at all.
#ifndef INCOMPLETE_TAINTS
/* pw_gecos is tainted because user himself can diddle with it. */
SvTAINTED_on(sv);
#endif
PUSHs(sv = sv_mortalcopy(&PL_sv_no));
sv_setpv(sv, pwent->pw_dir);
PUSHs(sv = sv_mortalcopy(&PL_sv_no));
sv_setpv(sv, pwent->pw_shell);
#ifdef PWEXPIRE
PUSHs(sv = sv_mortalcopy(&PL_sv_no));
sv_setiv(sv, (IV)pwent->pw_expire);
#endif
}
Lovely. Just lovely. Now, *how* many values do getpw*() return
in list context? Answer: you don't know anymore! Sometimes it's
there, sometimes it's not. That means you cannot know (without
delightful probing %Config) what type of value the [-1] entry even
*contains*.
(Notice also how pw_expire isn't in User::pwent. Guess why?)
I don't have an excellent solution to this, but I do not one bit
like what's happened to a sysadmin-critical function used in mission
critical admin and security scripts run by the superuser. I even
less care for the fact that nobody deigned to document this gratuitous
breakage in the appripriate impacts document (read: the proper
release's perldelta page).
So, just what are we now supposed to do about this?
--tom
PS: And pw_shell should be tainted!
Thread Next
-
WHOA THERE! Somebody went and broke all the getpw functions!
by Tom Christiansen