[Techtalk] Perl Sockets Communication

Kai MacTane kmactane at GothPunk.com
Tue Nov 11 18:32:35 EST 2003


At 11/4/03 09:50 PM , januhe wrote:

>My name is Javier Nunez and I want to ask you a question. I was looking
>a script that you made to change passwords from a CGI script you opened
>a socket to a server running a daemon that change the password.

Was this the pwchanged script? Ah, I see from the link that it was. (Is. 
Whatever.)

>Well I create two scripts that run on a UNIX environment and one is
>running as a daemon, the other is connecting every month to the server
>to request the password change. My problem is that I do not know how to
>handle the passwd command.

What sort of handling does it need?

>How do I redirect the output of the passwd command  and how do I pass
>the command the string that I'm going to use as a password.

You could do this by opening a pipe to passwd, like so:

   open PASSWD, "| passwd $username";
   # Assume program is prompting for new password.
   print PASSWD "$newpass\n";
   # Now assume it's asking for confirmation, and not complaining
   # about the password being weak.
   print PASSWD "$newpass\n";
   # Could try doing it a third time, just in case...
   close PASSWD;

But, as you can see, that's kind of risky, given that it involves lots of 
assuming. A better way would be to use the IPC::Open2 module (documented in 
Chapter 7 of the Camel Book) to open the pipe bidirectionally, so that you 
can read each line of output from passwd and then deliver the appropriate 
input.

But the way I dealt with the situation in my finished script was to ignore 
the passwd utility altogether, and just write directly into /etc/shadow. It 
came out something like this (with tutorial comments added):

   $shadow = '/etc/shadow';
   $new_shadow = $shadow . '.pwchanged';
   # Open /etc/shadow, and create a new /etc/shadow.pwchanged.
   open SHADOW, "$shadow";
   $ret = open NEW, ">$new_shadow";
   unless ($ret) {
      # Give some sort of error message; couldn't open new file
   }

   # Read through shadow line-by-line, copying each line into
   # new shadow. On the one line we're interested in, make some
   # substitutions.
   while ($line = <SHADOW>) {
      if ($line =~ /^$username:/) {
         # You need to update the date-last-changed as well as
         # the actual password.
         $new_date = `date +%s`; # Seconds since epoch; GNU extension
         $new_date = int($new_date / 86400); # convert to days
         # Note that @line and $line are different variables!
         @line = split(/:/, $line);
         # Presume $hashed_pass has been set up before; it should
         # be the crypted or MD5ed version of the new password.
         $line[1] = $hashed_pass;
         $line[2] = $new_date;
         $line = join(':', @line);
      }
      print NEW "$line";
   }
   close SHADOW;
   $ret = close NEW;
   unless ($ret) {
      # Give some sort of error message; couldn't close new file
   }
   unless (rename $new_shadow, $shadow) {
      # Give error message that you couldn't mv temp file over /etc/shadow
   }
   unless (chmod 0400, $shadow) {
      # Give yet another error message
   }

This code was written without strict mode on, hence the lack of the word 
"my" on any variable declaration. Were I writing this stuff now, I'd do it 
with strict mode and taint checking on (and see a comment in that thread 
you referenced, about the dangers of allowing unsanitized user input to be 
used in a system command).

Heck, were I writing it now, I'd strongly consider using IPC:::Open2. But, 
if you like, I can post the scripts I actually did write. They've been in 
production use on the client's machine, and on my own server as well, for a 
couple of years now.

Hope that helps; let me know if you need other information.

                                                 --Kai MacTane
----------------------------------------------------------------------
"In another life I see you, as an angel flying high,
  And the hands of time will free you; you will cast your chains aside,
  And the dawn will come and kiss away
  Every tear that's ever fallen from your eyes...
                                                 --Concrete Blonde,
                                                  "Caroline"



More information about the Techtalk mailing list