SUMMARY: batch of passwords

From: Don H. Olive <don_at_andromeda.campbellsvil.edu>
Date: Fri, 17 Sep 1999 17:32:12 -0400 (EDT)

Thanks to everyone who responded. I got several ideas but by far, the
consensus is to use a program called expect. I found expect-5.30 at

                   http://expect.nist.gov

Expect uses TCL/TK and uses a syntax something expect, send, expect,
send...

I haven't used it yet but it looks trivially easy.

Other people sent in nice ideas and scripts too. I'll include them
below.


***************from Tom Payerle:
#!/bin/sh

USER=$1
NEWPASS=$2

                
expect -c "spawn \"passwd\" \"${USER}\"" \
        -c 'expect "word:"' -c "send \"${NEWPWD}\r\"" \
        -c 'expect "gain:"' -c "send \"${NEWPWD}\r\"" -c "interact"

****************from Alan Davis

You might also take a look at the zuausr from the U of Alaska :

ftp://raven.alaska.edu/pub/randy/zuausr/


**************from Alan Angulo

#!/usr/local/bin/perl
# By Alan Angulo
# May 13, 1997
B
# Get passwd
srand;
while($pline = <STDIN>) {
  ($username,$password)=split(/:/,$pline);
  chop ($password);
  if (length($password) < 6) {
    print "PASSWORD LESS THAN 6 CHARACTERS - TRY AGAIN.\n";
    $epasswd="PASSWORD WAS LESS THAN 6 CHARACTERS";
    next;
    }
  if (length($password) > 8) {
    $password = substr($password,0,8);
    }
  $salt = pack("CC",valid_salt_char(),valid_salt_char());
  $crypt_passwd = crypt($password,$salt);
  print "$username:$password:$crypt_passwd\n";
}
# SUBROUTINES
#Returns a random character from the set [./0-9A-Za-z]
#Used to generate salt chahacters
sub valid_salt_char
   {
   $s1=int(rand(76) +46);
   if ( (($s1 >= 58) && ($s1 <= 64)) || (($s1 >= 91) && ($s1 <= 96)) )
      {
         #Jump to a valid set instead of generating again
         return ($s1 += 8);
      }
   return $s1;
   }
#END-----------------------------------------------------------------

Save this code as makepasswd.
Create a text file all user/password information with the format:
              
             login:password

use it as: ./makepasswd < user_password.txt > encrypted_password.txt
encrypted_password.txt will contain login:password:encrypted_password.

Once you have the this info, the rest is just... you know... stuff.


*******************from Lars Bro

>From lbr_at_nettest.dk Thu Sep 16 05:18:09 1999

Hi,

Some commands are intended to be 'interactive'. Such commands read and wr=
ite
'/dev/tty' instead of standard input and standard output. One of the
benefits
is that these commands can make their own tty settings just like the pass=
wd
command that disables echo when the user types the password. If the comma=
nd
were
polite, it might have asked if stdin were a tty and then run interactivel=
y,
otherwise in batch....... but

for the sake of those programs where we cannot just redirect something in=
to
standard input, we have the 'pseudo ttys'. A pseudo tty is a terminal dev=
ice
in /dev. It is not connected to a terminal but to a process. Look at the =
C
example
below:

This program: (mypasswd.c)

#include <fcntl.h>
main()
{
        char buf[1024];
        int fd;
        int n;
        fd =3D open("/dev/tty", O_RDWR);

        for(;;) {
               n=3Dread(fd, buf, sizeof(buf));
               if (n <=3D0 )
                break;
               buf[n]=3D0;
               write(fd, buf, n);
        }
}

reads from /dev/tty and prints the same back to /dev/tty again. If you ru=
n
it, it will
work exactly as 'cat', it echoes everything back that you write. But no
matter how you
try to redirect or pipe input to it, it communicates with your terminal
only.

The next program makes a pseudo-tty (the terminal device I mentioned befo=
re)
and creates
a new process that runs the command "mypasswd".

main()
{
        char buf[1024];
        int n;

        int master;
        char name[64];
        int st;

        if (!forkpty(&master, name, (void*)0, (void*)0)) {
                execl("./mypasswd", "mypasswd", "user", 0);
                exit(1);
        } else {
                write(master, "Hello, World\n", 13);
                n=3Dread(master, buf, sizeof(buf));
                write(1,buf, n);
        }
        wait(&st);
}

This program calls forkpty() which - if returning 0 is the child process =
and
immediately
starts the program mypasswd above. The parent proces writes "Hello World"=
 to
the pseudo
terminal which is seen by "mypasswd" and returned. So, now we can make
programs that talk
to other programs by means of pseudo terminals.

The program below (run as root) successfully changed my password to "lars=
.."

main()
{
        char buf[1024];
        int n;

        int master;
        char name[64];
        int st;

        if (!forkpty(&master, name, (void*)0, (void*)0)) {
                execl("/usr/bin/passwd", "passwd", "lbr", 0);
                exit(1);
        } else {
                n=3Dread(master, buf, sizeof(buf));
                write(1,buf, n);
                write(master, "lars..\n", 7);
                n=3Dread(master, buf, sizeof(buf));
                write(1,buf, n);
                write(master, "lars..\n", 7);
                n=3Dread(master, buf, sizeof(buf));
                write(1,buf, n);
        }
        wait(&st);
}

This is fairly easy provided you can program C.

For those people that dont program C, there is something called "expect".=
 It
is a
program that does exactly the above, only its documentation is a 500+ pag=
es
book and it
needs its own mail group and news group. Basically, you write 'expect'
scripts
that contain information like this:

        run this program
        when it says ...
        you say ...
        and when it says
        you say ...

        and so on.

It is very popular and very commonly used (=3Dreliable). I bet you get a =
lot
of references
to it. But you can also do with 22 lines of C.

**************from Rich Lafferty rich_at_alcor.concordia.ca

You need to fool passwd into thinking it's not on a tty. Something
like this (which originally changed unix and AppleShare passwords;
I've cut out the appleshare part.)

/*
 * passwd.wrapper.c -- change Unix passwords, using passwd(1)
 * for the latter (to avoid bypassing PAM)
 *
 * 1999/08/25 Rich Lafferty
 * based on N. Dean Pentcheff's SMB-password changer
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the same terms as Perl (see http://www.perl.com).
 *
 * To work, must be installed SUID-root.
 * If called interactively (from a tty), is slightly verbose, and uses
 * the standard getpass() routine to query for and confirm a password.
 * If called noninteractively, expects the password (once) on stdin.
 */

#include <fcntl.h>
#include <sys/ioctl.h>
#include <pwd.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

/* Path to unix passwd(1) program */
#define PASSWD "/usr/bin/passwd.real"

#define PROMPT1 "New password: "
#define PROMPT2 "Retype new password: "

#define STRLEN 1024

int main (int argc, char *argv[]) {

  int fd;
  int status;
  struct passwd *pwentry;
  char new[STRLEN];
  char cmd[STRLEN];
  char *cp;
  FILE *cmdpipe;
  FILE *mystderr;
  uid_t origuid;

  /* get username and home directory */
  if (argc == 1) {
    if ((pwentry = getpwuid(getuid())) == NULL) {
      fprintf(stderr, "Failed getting pw entry for UID=%d, exiting...\n",
            getuid());
      exit(1);
    }
  } else {
    if ((pwentry = getpwnam(argv[1])) == NULL) {
      fprintf(stderr, "Failed getting pw entry for '%s', exiting...\n",
            argv[1]);
      exit(1);
    }
    /* Only root can change other people's passwords. */
    if (getuid() != 0) {
      fprintf(stderr, "Your magic is not strong enough to perform on other people's passwords.\n");
      exit(1);
    }
}

  fprintf(stderr, "Changing password for %s...\n", pwentry->pw_name);
  
  /* do we have the appropriate permissions? */
  if (geteuid() != 0) {
    fprintf(stderr, "This program cannot run unless it is SUID-root, "
            "exiting...\n");
    exit(1);
  }

  /* get a password and strip any trailing cr/lf stuff */
  if (isatty(0)) { /* interactive, so use a no-echo prompt twice */
    cp = getpass(PROMPT1);
    strncpy(new, cp, STRLEN);
    cp = getpass(PROMPT2);
    if (strcmp(new, cp)) {
      fprintf(stderr, "The two versions don't match, exiting...\n");
      exit(1);
    }
  } else { /* noninteractive, so just get it from stdin */
    if (read(0, new, STRLEN) <= 0) {
      fprintf(stderr, "Failed to read a new password, exiting...\n");
      exit(1);
    }
  }

  for (cp=new; *cp!='\n' && *cp!='\r' && cp-new<STRLEN-1; ++cp)
    ;

  *cp = '\0';
  if (strlen(new) <= 0) {
    fprintf(stderr, "No password entered, exiting...\n");
    exit(1);
  }


  /* get a private stderr, then close stderr/stdout to silence pwd programs */
  if ((fd = dup(2)) < 0) {
    fprintf(stderr, "Couldn't dup error-output fd, exiting...\n");
    exit(1);
  }
  if ((mystderr = fdopen(fd, "w")) == NULL) {
    fprintf(stderr, "Couldn't fdopen new stderr fd, exiting...\n");
    exit(1);
  }
  close(1);
  close(2);


  /* detach from controlling tty to convince passwd to read stdin for pw */
  if ((fd = open("/dev/tty", O_RDWR)) >= 0) {
    if (ioctl(fd, TIOCNOTTY) < 0) {
      fprintf(mystderr, "Failed to detach from /dev/tty: %s, exiting...\n",
              strerror(errno));
      exit(1);
    }
    close(fd);
  }

  /* shuffle UIDs for permissions - we expect to be running SUID-root */
  origuid = getuid();
  if (setuid(geteuid()) != 0) {
    fprintf(mystderr, "Failed to properly set UID, exiting...\n");
    exit(1);
  }

  /* open a pipe to and then feed the standard Unix passwd program, slowly */
  if (isatty(0)) {
    fprintf(mystderr, "Changing Unix password...");
    fflush(mystderr);
  }
  strcpy(cmd, PASSWD);
  strcat(cmd, " ");
  strcat(cmd, pwentry->pw_name);
  if ((cmdpipe = popen(cmd, "w")) == NULL) {
    fprintf(mystderr, "FAILED: Can't open pipe to '%s', exiting...\n", cmd);
    exit(1);
  }
  sleep(3);
  fprintf(cmdpipe, "%s\n", new); fflush(cmdpipe); sleep(2);
  fprintf(cmdpipe, "%s\n", new); fflush(cmdpipe); sleep(2);
  if ((status = pclose(cmdpipe)) != 0) {
    fprintf(mystderr, "FAILED: '%s' returned error code %d, exiting...\n",
            cmd, status);
    exit(1);
  }
  if (isatty(0))
    fprintf(mystderr, "Success.\n");
  }
  exit(0);
}

/* end of program */

********************from Leonardo Mosquera

#!/usr/local/bin/expect -f
spawn /bin/passwd [lindex $argv 0]
set password [lindex $argv 1]
puts $password
expect "password:"
send "$password\r"
expect "password:"
send "$password\r"
expect eof

This shell use expect, and is an easy one to run or call from your
script:

./putpass username password


**********************from Mark John Suter / <suter_at_its.uq.edu.au>

#!/bin/sh
# set_c2_passwd
# [CJT 22-July-1998]
# If given user does not have a C2 password field then set one.
# Value used for password field is "*", i.e. an impossible password.

edauth=/usr/tcb/bin/edauth

if [ $# != 1 ]
then
        echo "Usage: $0 username" 1>&2
        exit 2
fi

user=$1

$edauth -g $user || exit 3

if $edauth -g $user | grep -q ":u_pwd="
then
        echo "User $user already has a password" 1>&2
else
        echo "Setting password for user $user" 1>&2
        $edauth -g $user | sed -e 's/:chkent:/:u_pwd=*:chkent:/' | $edauth -s
fi


-- 
 Don H. Olive, Physics Department    don_at_campbellsvil.edu
 Campbellsville University           http://www2.campbellsvil.edu/~don
 UPO 1265, One University Drive      +1.270.789.5243 voice/+1.270.789.5042 fax
 Campbellsville KY, 42718 USA        PGP:  finger don_at_cygnus.campbellsvil.edu
Received on Fri Sep 17 1999 - 21:35:01 NZST

This archive was generated by hypermail 2.4.0 : Wed Nov 08 2023 - 11:53:39 NZDT