flacour has asked for the wisdom of the Perl Monks concerning the following question:

When i try to retrieve my users encrypted password with
(getpwnam($user))[1] it just returns an "x".

This is kind of right, since we are using "shadowed" passwords. But how do I retrieve this shadowed password?

Replies are listed 'Best First'.
RE: getpwnam() password
by eLore (Hermit) on Aug 03, 2000 at 01:10 UTC
    Have you tried CfgTie::TieShadow from CPAN?

    Search the CPAN modules for "shadow", and let me know how it works!

Re: getpwnam() password
by DrManhattan (Chaplain) on Aug 03, 2000 at 07:37 UTC

    getpwnam() only returns the crypted password if you execute it as root.

    [matt@resuna ~]$ perl -le 'print $passwd = (getpwnam("root"))[1]' * [matt@resuna ~]$ su Password: resuna# perl -le 'print $passwd = (getpwnam("root"))[1]' $2a$61$8DF//jVKvvTJ1zimSj82fdsFH/.z64H3vHlcp1FqhEOJ9HBBSiPq6
    (root password changed to protect the innocent)

    -Matt

      Well, that's obviously true on your system. But not necessarily everywhere: getpwnam() returns whatever the underlying library call returns, so man getpwnam is your reference there.

      -- Randal L. Schwartz, Perl hacker

        Actually, on systems where the underlying getpwnam() never returns the crypted password but Perl knows how to get the crypted password, Perl's getpwnam() will return the crypted password when you are root. Some like this, some hate it. But you are right in that it doesn't work on all systems.

Re: getpwnam() password
by neopol (Initiate) on Aug 03, 2000 at 02:18 UTC
    Well if you are trying to authenticate users this will work. This is the code I have used for a web front end. It is taken out of the documentation.

    sub check_pass {
      sub my_conv_func {
        my @res; while ( @_ ) {
        my $code = shift;
        my $msg = shift;
        my $ans = "";

        $ans = $userid if ($code == PAM_PROMPT_ECHO_ON() );
        $ans = $pass if ($code == PAM_PROMPT_ECHO_OFF() );

        push @res, PAM_SUCCESS();
        push @res, $ans;
        }
        push @res, PAM_SUCCESS();
        return @res;
       }

      ref($pamh = new Authen::PAM($service, $userid,\&my_conv_func)) || die "Error code $pamh during PAM init!";

      $ret=$pamh->pam_authenticate;

      if($ret ne 0) {
        print header, start_html("Password Change");
        print("Please enter your correct UserID Password");
        print end_html; die;
      }
Re: getpwnam() password
by Anonymous Monk on Aug 03, 2000 at 03:38 UTC
    Probably the easiest thing to do would be to open the shadow file, find the user and read the encrypted password.
    open(SHADOW, "< /etc/shadow") || die "Can't open for read: $!";
    while(<SHADOW>) {
        if($_ =~ /^$user:(\w+):.*/) {
                print "$user's encrypted password is $1\n";
        }
    }
    
      That's how I'd do it, but shouldn't line two be
      while(<SHADOW>) {
RE: getpwnam() password
by neopol (Initiate) on Aug 03, 2000 at 02:07 UTC
    Well if you are trying to authenticate users this will work. This is the code I have used for a web front end. It is taken out of the documentation. sub check_pass { sub my_conv_func { my @res; while ( @_ ) { my $code = shift; my $msg = shift; my $ans = ""; $ans = $userid if ($code == PAM_PROMPT_ECHO_ON() ); $ans = $pass if ($code == PAM_PROMPT_ECHO_OFF() ); push @res, PAM_SUCCESS(); push @res, $ans; } push @res, PAM_SUCCESS(); return @res; } ref($pamh = new Authen::PAM($service, $userid, \&my_conv_func)) || die "Error code $pamh during PAM init!"; $ret=$pamh->pam_authenticate; if($ret ne 0) { print header, start_html("Password Change"); print("Please enter your correct UserID Password"); print end_html; die; }