SUMMARY: mass creating passwd and shadow files

From: Stuart Kendrick (sbk@fhcrc.org)
Date: Tue Feb 18 1997 - 16:47:13 CST


I want to write code which will take a plain text password and procduce a
shadow file format encrypted version. As many resondents pointed out,
this is a common task, and I ought to have consulted the archives at

http://www.LaTech.edu/sunman.html
or
http://www.nexial.nl/cgi-bin/sunmanagers

before posting. For future searchers, attached is a summary.

Thanks to:

Mark Bergman <bergman@phri.nyu.edu>
Ric Anderson <ric@rtd.com>
Jim Harmon <jim@telecnnct.com>
Michael F Gordon <Michael.Gordon@ee.ed.ac.uk
Francisco J. Donderis L. <fadal@sonitel.com>
Erick Cedeo <erickc@sonitel.com>
Igor Kolker <root@utopia.poly.edu>
Tom Hinze <hinze@ties.k12.mn.us>
Grinnell_Rick/goc_openmail@fpc.com

Ric Anderson <ric@rtd.com>
       char *seed = "X3";/* 2 chars of your choice. Low order 2 bytes
                          /* of clock is a good seed */
        char *pw; /* plain text password (8 char max) */
        char *encrypted_pw;
        extern char *crypt(); /* for old K&R c compilers */

        encrypted_pw = crypt(pw,seed);
The string returned by crypt is the entry for the password or
shadow file.

Jim Harmon <jim@telecnnct.com>
If you start with the passwd utility in the PERL Programming book, you
should have all the pieces you need to create the passwds, and to
install them in the shadow file with minimal alteration.

You can download it from the O'Reilly published docs ftp site at:

        ftp://ftp.ora.com/published/oreilly/nutshell/

Select the perl directory that covers the version of perl you're
using... assuming you are using perl. :)

The file is called "passwd" -I believe. See the Camel book, PG. 286-305
in the march/96 edition.

Michael F Gordon <Michael.Gordon@ee.ed.ac.uk
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

main(argc,argv)
int argc;
char **argv;
{
    char *extras="!@%*()-+={[}];<>?";
    char *exclusions="0Ol1I";
    char cleartext[9];
    char *encrypted;
    char *crypt();
    char saltc[2];
    int c,i,num;
    long salt;

    if (argc!=2) {
        fprintf(stderr,"usage: pwdgen num\n");
        exit(1);
    }

    num=atoi(argv[1]);
    cleartext[8]='\0';
    srand((int)time(NULL)+getpid());

    while (num--) {
        for (i=0;i<8;i++) {
            do {
                cleartext[i]=(rand() >> 24) & 0x7f;
            } while (cleartext[i]=='\0' ||
                     !(isalnum(cleartext[i]) ||
strchr(extras,cleartext[i])) ||
                     strchr(exclusions,cleartext[i]));
        }

       salt=time(NULL)+rand();

        /*
         * This is taken from passwd.c - it somehow makes sure that
         * the encrypted password consists of only a limited set of
         * characters.
         *
         */
        saltc[0]=salt & 077;
        saltc[1]=(salt>>6) & 077;
        for (i=0;i<2;i++) {
            c=saltc[i]+'.';
            if (c>'9')
                c+=7;
            if (c>'Z')
                c+=6;
            saltc[i]=c;
        }

        encrypted=crypt(cleartext,saltc);

        printf("%s\t%s\n",cleartext,encrypted);
    }

    return(0);
}

Francisco J. Donderis L. <fadal@sonitel.com>
you can write a program in c that uses the getpasswd() and encrypt()
function
and then insert into the shadow file

Erick Cedeo <erickc@sonitel.com>
There are multiple options to create encrypted passwords from a test
string, but it depends on your language.

There's a C function call crypt() defined on crypt.h, that you can use;
take a look at the crypt.3c man pages for usage.

If you prefer perl, there's also a perl function called crypt, used the
same way as the C one. The camel book has a good example on this function.

Igor Kolker <root@utopia.poly.edu>
try the following bit of Perl:
$salt = substr($userid,0,2);
$pass = crypt($uPass,$salt);

where $pass is the encrypted passwd, $userid is the login name, and $uPass
is the unencrypted passwd.

Tom Hinze <hinze@ties.k12.mn.us>
We often add 50 to a hundred users at a time to our NIS+ database so I
wrote a
PERL script to do it. Here is the part for creating passwds and
credentials:

#encrypt a passwd for the user.
    $passwd = crypt($password,$salt);

#add the user to the NISPLUS passwd table:

system("/bin/nistbladm -D owner=$login.`domainname`. -a name=$login
passwd=$passwd uid=\"$uid\" gid=\"$gid\" gcos=\"$gcos\"
home=\"/home/$login\"
shell=\"/usr/local/bin/$shell_type\" shadow=$day:0::::: passwd.org_dir");

#create local credentials for the user:
system("nisaddcred -p $uid -P $login.`domainname`. local > /dev/null");
#Create DES credentials for the user:
system("nisaddcred -p unix.$uid\@`domainname` -P $login.`domainname`. -l
\"$password\" des > /dev/null");

Your script may also need to create a home dir for the user as well as an
entry in the automount map - if your using the automounter.

Grinnell_Rick/goc_openmail@fpc.com
I dont know about the NIS part, but a normal shadow file can be
     manipulated using the salt, crypt, and putspwent commands.
     Actual syntax and usage are dependent on your choice of programming
     languages. Following are code snippets from work I've done in Perl
     and C. Obviuosly, you'll have to wrap your code around them to make
     them functional.
     --------------------------------------------------------------------
     C code snippet:
         /*
         | Create a 'salt' for the new password
         */
         memset (Salt, 0, 3);
         Time = time (NULL);
         srand (Time);
      Salt[0] = SaltRange [(rand() % SALT_RANGE_LEN)];
         Salt[1] = SaltRange [(rand() % SALT_RANGE_LEN)];

         /*
         | Encrypt the new password
         */
         pCryptPass = crypt (NewPassword, Salt);
         strcpy (CryptPass, pCryptPass);

         /*
         | Change the password in the passwd structure
         */

         if (SecPwdFile)
             {
             strcpy (pS_passwd->pw_passwd, CryptPass);
             rc = putspwent (pS_passwd, EtcPwdFile);
            }
         else
             {
             strcpy (pPasswd->pw_passwd, CryptPass);
             rc = putpwent (pPasswd, EtcPwdFile);
             }

     ---------------------------------------------------------

     Perl code snippet to validate a password:

     open SHADOW,"/etc/shadow") | die "Can't open the /etc/shadow file";
     while (<SHADOW>) {
             /^([^:]+)/;
             if ($1 eq $account) {
                     ($lanid,$passwd) = split(/:/);
                     $salt = substr($passwd,0,2);
                   last;
             }
     }
     close (SHADOW);
     if (crypt($pwd2tst,$salt) ne $passwd) {
     print "<html><head><title></title></head><body><center>"
     print "Invalid Password - Quit hacking!"
     print "</center></body></html>"
     exit;
     }

     # Oops - I dont have any perl books to look up the putspwent stuff
     # looks like your on your own here...

--sk

Stuart Kendrick
Network Services
FHCRC



This archive was generated by hypermail 2.1.2 : Fri Sep 28 2001 - 23:11:46 CDT