home *** CD-ROM | disk | FTP | other *** search
- From decwrl!ucbvax!pasteur!ames!lll-winken!uunet!allbery Sun Apr 23 15:40:30 PDT 1989
- Article 860 of comp.sources.misc:
- Path: decwrl!ucbvax!pasteur!ames!lll-winken!uunet!allbery
- From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
- Newsgroups: comp.sources.misc
- Subject: v06i091: Password checking routine(s)
- Keywords: password sanity checking code
- Message-ID: <53142@uunet.UU.NET>
- Date: 23 Apr 89 19:26:25 GMT
- Sender: allbery@uunet.UU.NET
- Reply-To: ut-emx!clyde@cs.utexas.edu (Head UNIX Hacquer)
- Organization: Moose & Squirrel Software
- Lines: 1197
- Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 6, Issue 91
- Submitted-by: ut-emx!clyde@cs.utexas.edu (Head UNIX Hacquer)
- Archive-name: chkpwd
-
- Enclosed is some code that I worked up to do some password checking.
- I hope it can be useful to others.
-
- # This is a shell archive.
- # Remove everything above and including the cut line.
- # Then run the rest of the file through sh.
- -----cut here-----cut here-----cut here-----cut here-----
- #!/bin/sh
- # shar: Shell Archiver
- # Run the following text with /bin/sh to create:
- # README
- # Makefile
- # checkpasswd.h
- # checkpasswd.c
- # makedict.c
- # viewdict.c
- # wormwords
- # This archive created: Mon Jan 9 13:27:05 1989
- # By: Head UNIX Hacquer (Moose & Squirrel Software)
- echo shar: extracting README '(1040 characters)'
- sed 's/^XX//' << \SHAR_EOF > README
- XX
- XXThis is a password checking program that I wrote after the infamous Internet
- XXworm. I used the password cracking algorithim the worm used in order
- XXto check the obviousness of a password.
- XX
- XXThe routine checkpasswd.c does this. Read the source for the routine
- XXfor details of how it works. In this package are the following:
- XX
- XXREADME This file
- XXMakefile Q.E.D.
- XXcheckpasswd.c Password check routine
- XXcheckpasswd.h Include for checkpasswd calling
- XXdriver.c Test program
- XXmakedict.c Program to build dbm dictionary
- XXwormwords The infamous worm password list
- XXviewdict.c Program to view dbm dictionary
- XX
- XXI hope this can be a kernel of intelligent password checking for 4BSD systems.
- XX
- XXI am working on a replacement for the BSD passwd program, which should be
- XXavailable soon.
- XX
- XXContents copyright 1989 Clyde W. Hoover (Moose & Squirrel Software, NotInc.)
- XX
- XXDistribution unlimited provided copyright notice is retained.
- XXPlease spread this around as much as useful.
- XX
- XX Clyde Hoover
- XX Computation Center
- XX The University of Texas at Austin
- XX clyde@emx.utexas.edu
- SHAR_EOF
- if test 1040 -ne "`wc -c README`"
- then
- echo shar: error transmitting README '(should have been 1040 characters)'
- fi
- echo shar: extracting Makefile '(670 characters)'
- sed 's/^XX//' << \SHAR_EOF > Makefile
- XX#
- XX# Make password checking routines and test program
- XX
- XX#
- XX# The checkpasswd routine depends upon the existence of the ndbm
- XX# routines in the 4.3BSD libc. Changes will have to be made to
- XX# checkpasswd.c if these are not available.
- XX#
- XXCFLAGS = -g
- XX
- XXpwtest: driver.o checkpasswd.o
- XX cc $(CFLAGS) -o pwtest driver.o checkpasswd.o
- XX
- XXcheckpasswd.o: checkpasswd.c checkpasswd.h
- XX cc $(CFLAGS) -c checkpasswd.c
- XX
- XXmakedict: makedict.c
- XX cc $(CFLAGS) -o makedict makedict.c
- XX
- XXviewdict: viewdict.c
- XX cc $(CFLAGS) -o viewdict viewdict.c
- XX
- XXpwdict: wormlist makedict
- XX -rm -f pwdict
- XX cat /usr/dict/words wormlist | makedict pwdict
- XX @echo install pwdict to where PWDICT points to in checkpasswd.c
- SHAR_EOF
- if test 670 -ne "`wc -c Makefile`"
- then
- echo shar: error transmitting Makefile '(should have been 670 characters)'
- fi
- echo shar: extracting checkpasswd.h '(1399 characters)'
- sed 's/^XX//' << \SHAR_EOF > checkpasswd.h
- XX/*
- XX * passwdcheck.h
- XX *
- XX * Copyright 1989 Clyde W. Hoover (Moose & Squirrel Software, NotInc.)
- XX *
- XX */
- XX
- XX#define EXPORT /**/
- XX#define IMPORT extern
- XX
- XX#define PWCK_FAIL -1
- XX#define PWCK_OK 0
- XX#define PWCK_NULL 1
- XX#define PWCK_OBVIOUS 2
- XX#define PWCK_FINGER 3
- XX#define PWCK_INDICT 4
- XX#define PWCK_ILLCHAR 5
- XX#define PWCK_SHORT 6
- XX
- XX/*
- XX * Return codes for checkpassword() are:
- XX *
- XX * PWCK_OK if <password> is ok to use
- XX * PWCK_FAIL if something failed during the check process
- XX * PWCK_NULL if <password> is the null string
- XX * PWCK_OBVIOUS if <password> is too "obvious"
- XX * (equals login name, host name, 'zzzz' )
- XX * PWCK_FINGER if <password> is in the users' passwd/finger info
- XX * PWCK_INDICT if <password> is in the dictionaries checked
- XX * PWCK_ILLCHAR if <password> is lexically illegal
- XX * PWCK_SHORT if <password> is too short
- XX */
- XX
- XX/*
- XX * Password checking peference block
- XX */
- XXstruct pwck_preferences {
- XX char OneCaseOk, /* Are single-case pwds acceptable */
- XX CtrlOk, /* Are control characters acceptable */
- XX CharRunLen, /* How long can run of characters be */
- XX MinPwLen; /* Minimum password length */
- XX char *EgrepPath; /* Path to the 'egrep' program */
- XX};
- XX
- XX/*
- XX * Preference list
- XX */
- XXIMPORT struct pwck_preferences pwck_preferences;
- XX
- XX/*
- XX * List of control characters not allowed in passwords
- XX */
- XXIMPORT char pwck_illegalcc[];
- XX
- XX/*
- XX * List of dictionaries to check
- XX */
- XXIMPORT char *pwck_dicitonaries[];
- XX
- SHAR_EOF
- if test 1399 -ne "`wc -c checkpasswd.h`"
- then
- echo shar: error transmitting checkpasswd.h '(should have been 1399 characters)'
- fi
- echo shar: extracting checkpasswd.c '(13550 characters)'
- sed 's/^XX//' << \SHAR_EOF > checkpasswd.c
- XX/*
- XX * checkpasswd.c - Login password check routines.
- XX *
- XX * Perform various sanity and security checks on a password candidate.
- XX *
- XX * Written December, 1988
- XX *
- XX * Copyright 1989 Clyde W. Hoover (Moose & Squirrel Software, NotInc.)
- XX *
- XX * Clyde Hoover
- XX * Computation Center
- XX * The University of Texas at Austin
- XX * Austin, Texas
- XX * clyde@emx.utexas.edu
- XX */
- XX
- XX#ifndef lint
- XXstatic char sccsid[] = "%W% %G% (cc.utexas.edu) %P%";
- XX#endif
- XX
- XX#include <sys/types.h>
- XX#include <strings.h>
- XX#include <ctype.h>
- XX
- XX#define LOCAL static
- XX
- XX#include "checkpasswd.h"
- XX
- XX/*
- XX * Special string compare defines.
- XX */
- XX#define try(P,C,V) { if (cistrcmp(P,C) == 0) return(V); }
- XX#define mtry(P,C,V) { int i; if ((i = StrAllCmp(P,C,V)) != PWCK_OK) return(i); }
- XX
- XX/*
- XX * Table of operational parameter preferences.
- XX * May be modified by the caller.
- XX */
- XXEXPORT
- XXstruct pwck_preferences pwck_preferences = {
- XX 1, /* single-case pwds ok */
- XX 1, /* control chars ok */
- XX 3, /* dup length = 3 */
- XX 4, /* minimum length */
- XX "PATH=/bin:/usr/bin:/usr/ucb; egrep" /* How to find egrep */
- XX};
- XX
- XX/*
- XX * Table of control chars best avoided -
- XX * mostly commonly-used terminal special chars.
- XX * May be modified by the caller.
- XX */
- XX#define ctrl(d) ('d' & 037)
- XX
- XXEXPORT
- XXchar pwck_illegalcc[128] = {
- XX ctrl(c), ctrl(d), ctrl(h), /* ctrl(i),*/ ctrl(j), ctrl(m),
- XX ctrl(o), ctrl(r), ctrl(s), ctrl(q), ctrl(z), ctrl(\\),
- XX ctrl([), /* escape */
- XX '\0177', /* rubout */
- XX 0
- XX};
- XX
- XX#define PWDICT "/usr/dict/pwwords"
- XX/*
- XX * List of forbidden password dictionaries to look in.
- XX * May be modified by the caller.
- XX */
- XXstatic char *pwck_dicitonaries[16] = {
- XX PWDICT, /* illegal passwords list */
- XX 0
- XX};
- XX
- XX/*
- XX * The 'pwck_*' routines all use the PWCK_* return
- XX * codes, which are then propigated up to the caller of checkpassword().
- XX *
- XX * All pwck_* routines in the table below are called thusly:
- XX * pwck_*(password, userid)
- XX * password = plaintext password string to test.
- XX * userid = the user id which wants to use <password>.
- XX *
- XX * Table of check functions to be called by checkpassword()
- XX */
- XXint pwck_lexical(), pwck_local(), pwck_passwd(), pwck_dictionary();
- XX
- XXtypedef int (*function)();
- XX
- XXLOCAL
- XXfunction pwck_vector[] = {
- XX pwck_lexical,
- XX pwck_local,
- XX pwck_passwd,
- XX pwck_dictionary,
- XX 0
- XX};
- XX
- XX/* ------------------------------------------------------------------- */
- XX
- XX/*
- XX * checkpassword - Password candidate sanity checker.
- XX *
- XX * Arguments;
- XX * password = plain text password string to check.
- XX * userid = the uid whom the password is for, -1 to disable.
- XX *
- XX * Returns:
- XX * PWCK_OK if <password> is ok to use.
- XX * PWCK_FAIL if something failed during the check process.
- XX * PWCK_NULL if <password> is the null string
- XX * PWCK_OBVIOUS if <password> is too "obvious".
- XX * (equals login name, host name, 'zzzz' ).
- XX * PWCK_FINGER if <password> is in the users' passwd/finger info.
- XX * PWCK_INDICT if <password> is in the dictionaries checked.
- XX * PWCK_ILLCHAR if <password> is lexically illegal.
- XX * PWCK_SHORT if <password> is too short.
- XX *
- XX */
- XXcheckpassword(password, userid)
- XXchar *password; /* Plaintext of password to check */
- XXint userid; /* The user this is for */
- XX{
- XX int rcode; /* General purpose scratch */
- XX function *checkfunc; /* Check function pointer */
- XX
- XX if (password == 0 || *password == 0)
- XX return(PWCK_NULL); /* Null password */
- XX
- XX for (checkfunc = pwck_vector; *checkfunc; checkfunc++) {
- XX if ((rcode = (*checkfunc)(password, userid)) != PWCK_OK)
- XX return(rcode);
- XX }
- XX return(PWCK_OK);
- XX}
- XX
- XX
- XX/* ------------------------------------------------------------------- */
- XX
- XX#define P_U 0x1 /* Upper case in password */
- XX#define P_L 0x2 /* Lower case in password */
- XX#define P_C 0x4 /* Control chars in password */
- XX#define P_D 0x8 /* Digits in password */
- XX#define P_P 0x10 /* Punctutation chars in password */
- XX
- XX#define hasone(P) (what |= (P))
- XX#define hasany(P) ((what & (P)) == (P))
- XX
- XX#define ccok pwck_preferences.CtrlOk
- XX#define mcok pwck_preferences.OneCaseOk
- XX#define runl pwck_preferences.CharRunLen
- XX#define minl pwck_preferences.MinPwLen
- XX
- XX/*
- XX * pwck_lexical - Perform lexical analysis of password candidate.
- XX *
- XX * Things which are ok:
- XX * Mixed case
- XX * Digits
- XX * Punctutation
- XX * Control characters (except for those in the forbidden table)
- XX * (controlled by the preferences)
- XX *
- XX * Things which are NOT ok:
- XX * Passwords less that 'minl' length
- XX * Runs of more than <runl> of the same character (e.g. 'zzz')
- XX * Single-case strings
- XX * (controlled by the preferences)
- XX *
- XX * Things not checked for:
- XX * Cycles of character groups (e.g. 'aabbcc' or 'ababab')
- XX */
- XXstatic int
- XXpwck_lexical(password, userid)
- XXchar *password;
- XXint userid; /* NOTUSED */
- XX{
- XX int rc; /* Duplicate character run count */
- XX char *p = password; /* Scratch */
- XX char what = 0, /* Lexical analysis result flags */
- XX last = 0; /* Last character seen (for run checks) */
- XX
- XX if (minl && strlen(password) < minl)
- XX return(PWCK_SHORT);
- XX
- XX for (p = password; *p; p++) {
- XX if (*p != last) {
- XX last = *p;
- XX rc = 0;
- XX }
- XX else { /* Run of same characters */
- XX if (runl && ++rc >= runl)
- XX return(PWCK_OBVIOUS);
- XX }
- XX if (*p < ' ') { /* Control character */
- XX if (!ccok)
- XX return(PWCK_ILLCHAR);
- XX if (index (pwck_illegalcc, *p))
- XX return(PWCK_ILLCHAR);
- XX hasone(P_C);
- XX }
- XX else if (isupper(*p)) hasone(P_U);
- XX else if (islower(*p)) hasone(P_L);
- XX else if (ispunct(*p)) hasone(P_P);
- XX else if (isdigit(*p)) hasone(P_D);
- XX }
- XX if (hasany(P_U | P_L)) return(PWCK_OK); /* UC+lc */
- XX if (hasany(P_D)) return(PWCK_OK); /* Numbers */
- XX if (hasany(P_P)) return(PWCK_OK); /* Punctutation chars */
- XX if (hasany(P_C)) return(PWCK_OK); /* Control chars */
- XX /*
- XX * Check for mono-case passwords
- XX */
- XX if (!hasany(P_U) && mcok) /* All lower case alpha */
- XX return(PWCK_OK);
- XX if (!hasany(P_L) && mcok) /* All upper case alpha */
- XX return(PWCK_OK);
- XX
- XX return(PWCK_ILLCHAR);
- XX}
- XX#undef hasone
- XX#undef hasany
- XX
- XX/*
- XX * pwck_local - Perform 'local' password checks.
- XX *
- XX * Returns:
- XX * PWCK_OBVIOUS if <password> == hostname
- XX * PWCK_OK if otherwise
- XX */
- XXLOCAL int
- XXpwck_local(password, userid)
- XXchar *password;
- XXint userid; /* NOTUSED */
- XX{
- XX char myname[32]; /* Scratch */
- XX
- XX (void) gethostname(myname, sizeof(myname));
- XX try(password, myname, PWCK_OBVIOUS);
- XX /*
- XX * Want to try full canoncalized hostname here in case gethostname
- XX * didn't get that for us.
- XX *
- XX * Then look in users' .rhosts and try those strings (maybe)
- XX */
- XX return(PWCK_OK);
- XX}
- XX
- XX/*
- XX * pwck_dictionary - Look in the forbidden password dictionaries.
- XX *
- XX * Returns:
- XX * PWCK_INDICT if <password> was in any dictionary
- XX * PWCK_OK if not
- XX */
- XXLOCAL int
- XXpwck_dictionary(password, userid)
- XXchar *password;
- XXint userid; /* NOTUSED */
- XX{
- XX int i, /* Counter */
- XX rcode; /* Return code temp */
- XX
- XX for (i = 0; pwck_dicitonaries[i]; i++) {
- XX if ((rcode =
- XX IsInDictionary(pwck_dicitonaries[i], password)) != PWCK_OK)
- XX return(rcode);
- XX }
- XX return(PWCK_OK);
- XX}
- XX
- XX/*
- XX * IsInDictionary - look for <password> in <dictionary>
- XX *
- XX * Use a DBM version of the dictionary if present,
- XX * use egrep to search the flat file if not.
- XX *
- XX * Returns:
- XX * PWCK_INDICT if <password> was found in <dictionary>
- XX * PWCK_OK if not
- XX */
- XX#define returnwith(code) { dbm_close(dbp); return(code); }
- XX#define EGREP pwck_preferences.EgrepPath
- XX
- XX#include <ndbm.h>
- XX
- XXLOCAL int
- XXIsInDictionary(dictionary, password)
- XXchar *dictionary, /* Pathname of dictionary */
- XX *password; /* Plaintext of password */
- XX{
- XX DBM *dbp; /* DBM database pointer */
- XX datum k, /* DBM lookup key */
- XX d; /* DBM lookup datum */
- XX int uc = isupper(password[0]); /* Is first char UC? */
- XX char pwtemp[128]; /* Scratch buffer */
- XX
- XX if ((dbp = dbm_open(dictionary, 0, 0)) == (DBM *)0) {
- XX char command[128]; /* Command build buffer */
- XX int rc; /* System() return code */
- XX
- XX if (access(dictionary, 0) < 0)
- XX return(PWCK_OK);
- XX /*
- XX * If the first letter is capitalized, look for
- XX * "[wW]ord" else look for "word"
- XX */
- XX if (uc)
- XX (void) sprintf(command,
- XX "%s -s '^[%c%c]%s$' %s > /dev/null",
- XX EGREP, password[0], password[0] & ~040,
- XX &password[1], dictionary);
- XX else
- XX (void) sprintf(command, "%s -s '^%s$' %s > /dev/null",
- XX EGREP, password, dictionary);
- XX rc = system(command);
- XX if (rc == 0)
- XX return(PWCK_INDICT);
- XX else
- XX return(PWCK_OK);
- XX }
- XX /*
- XX * Look in the DBM version of the dictionary.
- XX * Look for <password>, then if the first letter
- XX * is capitalized, force to lower and look again. I don't care
- XX * if <password> is in the dictionary but has mixed case letters,
- XX * but if the first letter has been capitalized, I care because
- XX * that's not a sufficent permutation to be secure.
- XX */
- XX (void) strcpy(pwtemp, password);
- XX k.dptr = pwtemp;
- XX k.dsize = strlen(pwtemp);
- XX d = dbm_fetch(dbp, k);
- XX if (d.dptr)
- XX returnwith(PWCK_INDICT);
- XX if (uc) {
- XX pwtemp[0] |= 040;
- XX d = dbm_fetch(dbp, k);
- XX if (d.dptr)
- XX returnwith(PWCK_INDICT);
- XX }
- XX returnwith(PWCK_OK);
- XX}
- XX#undef returnwith
- XX
- XX
- XX/*
- XX * pwck_password - Check password candidate against the users' password
- XX * file information, or any other information that is publicly
- XX * available about this user that a bandit could use as
- XX * password guesses.
- XX *
- XX * Here is the place to search your 'finger' database.
- XX */
- XX#include <pwd.h>
- XX
- XXstatic int
- XXpwck_passwd(password, userid)
- XXchar *password;
- XXint userid;
- XX{
- XX char temp[128]; /* Scratch */
- XX struct passwd *pwp; /* Pointer to user information */
- XX
- XX if (userid < 0) /* Can't do user checks */
- XX return(PWCK_OK);
- XX
- XX pwp = getpwuid(userid);
- XX if (pwp == 0)
- XX return(PWCK_FAIL);
- XX
- XX try(password, pwp->pw_name, PWCK_OBVIOUS); /* Checks 'name' and 'Name' */
- XX
- XX (void) strcpy(temp, pwp->pw_name);
- XX (void) strcat(temp, pwp->pw_name);
- XX try(password, temp, PWCK_OBVIOUS); /* Check 'namename' */
- XX
- XX (void) strcpy(temp, pwp->pw_name);
- XX MirrorString(temp);
- XX try(password, temp, PWCK_OBVIOUS); /* 'eman' */
- XX
- XX /*
- XX * Try every word in user's GECOS entry
- XX */
- XX mtry(password, pwp->pw_gecos, PWCK_FINGER);
- XX return(PWCK_OK);
- XX}
- XX/* ------------------------------------------------------------------- */
- XX/*
- XX * StrAllCmp - Compare all sub-strings (delineated by white space)
- XX *
- XX * Returns:
- XX * PWCK_OK if no match found
- XX * rc if match found
- XX */
- XXLOCAL
- XXStrAllCmp(s1, s2, rc)
- XXchar *s1, /* String to look for */
- XX *s2; /* String to look for <s1> in */
- XXint rc; /* What to return on match */
- XX{
- XX int l; /* Temp */
- XX
- XX for (l = strlen(s1); *s2; s2++)
- XX if (cistrncmp(s1, s2, l) == 0)
- XX return (rc);
- XX return(PWCK_OK);
- XX}
- XX
- XX/*
- XX * MirrorString - reverse a string in place
- XX */
- XXLOCAL
- XXMirrorString(s)
- XXchar *s; /* String to reverse */
- XX{
- XX char *p; /* Scratch */
- XX char t[128]; /* Scratch */
- XX
- XX (void) strcpy(t,s);
- XX p = t;
- XX while (*p) p++; /* Find end of string */
- XX --p;
- XX for (; *s; )
- XX *s++ = *p--;
- XX}
- XX
- XX/*
- XX * Case indepedant string comparasion routines swiped from
- XX * the source to MIT Hesiod.
- XX */
- XX/*
- XX * Copyright (c) 1986 Regents of the University of California.
- XX * All rights reserved. The Berkeley software License Agreement
- XX * specifies the terms and conditions for redistribution.
- XX */
- XX
- XX/*
- XX * This array is designed for mapping upper and lower case letter
- XX * together for a case independent comparison. The mappings are
- XX * based upon ascii character sequences.
- XX */
- XX
- XXLOCAL char charmap[] = {
- XX '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
- XX '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
- XX '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
- XX '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
- XX '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
- XX '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
- XX '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
- XX '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
- XX '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- XX '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- XX '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- XX '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
- XX '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
- XX '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
- XX '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
- XX '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
- XX '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
- XX '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
- XX '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
- XX '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
- XX '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
- XX '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
- XX '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
- XX '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
- XX '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- XX '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- XX '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- XX '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
- XX '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
- XX '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
- XX '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
- XX '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
- XX};
- XX
- XXLOCAL
- XXcistrcmp(s1, s2)
- XXregister char *s1, *s2;
- XX{
- XX register char *cm = charmap;
- XX
- XX while (cm[*s1] == cm[*s2++])
- XX if (*s1++=='\0')
- XX return(0);
- XX return(cm[*s1] - cm[*--s2]);
- XX}
- XX
- XXLOCAL
- XXcistrncmp(s1, s2, n)
- XXregister char *s1, *s2;
- XXregister n;
- XX{
- XX register char *cm = charmap;
- XX
- XX while (--n >= 0 && cm[*s1] == cm[*s2++])
- XX if (*s1++ == '\0')
- XX return(0);
- XX return(n<0 ? 0 : cm[*s1] - cm[*--s2]);
- XX}
- XX
- XX/* END */
- SHAR_EOF
- if test 13550 -ne "`wc -c checkpasswd.c`"
- then
- echo shar: error transmitting checkpasswd.c '(should have been 13550 characters)'
- fi
- echo shar: extracting makedict.c '(653 characters)'
- sed 's/^XX//' << \SHAR_EOF > makedict.c
- XX/*
- XX * makedict - Make DBM version of password dictionary
- XX */
- XX
- XX#include <sys/file.h>
- XX#include <stdio.h>
- XX#include <ndbm.h>
- XX
- XXextern char *index();
- XX
- XXchar line[80];
- XX
- XXmain(argc, argv)
- XXchar *argv[];
- XX{
- XX DBM *dp;
- XX int recs = 0;
- XX datum d,
- XX k;
- XX
- XX dp = dbm_open(argv[1], O_RDWR, 0);
- XX if (dp == 0) {
- XX if ((dp = dbm_open(argv[1], O_RDWR|O_CREAT, 0644)) == 0) {
- XX perror("open dbm");
- XX exit(1);
- XX }
- XX }
- XX while (!feof(stdin)) {
- XX char *p;
- XX
- XX fgets(line, 80, stdin);
- XX p = index(line, '\n');
- XX if (p) *p = 0;
- XX d.dptr = line;
- XX d.dsize = strlen(line);
- XX dbm_store(dp, d, d, DBM_INSERT);
- XX recs++;
- XX }
- XX dbm_close(dp);
- XX printf("%s built, %d records\n", argv[1], recs);
- XX}
- SHAR_EOF
- if test 653 -ne "`wc -c makedict.c`"
- then
- echo shar: error transmitting makedict.c '(should have been 653 characters)'
- fi
- echo shar: extracting viewdict.c '(406 characters)'
- sed 's/^XX//' << \SHAR_EOF > viewdict.c
- XX/*
- XX * viewdict - View DBM version of a password dictionary
- XX */
- XX
- XX#include <sys/file.h>
- XX#include <ndbm.h>
- XX
- XXmain(argc, argv)
- XXchar *argv[];
- XX{
- XX DBM *dp;
- XX datum k;
- XX char t[128];
- XX
- XX if ((dp = dbm_open(argv[1], O_RDONLY, 0)) == 0) {
- XX perror(argv[1]);
- XX exit(1);
- XX }
- XX for (k = dbm_firstkey(dp); k.dptr != 0; k = dbm_nextkey(dp)) {
- XX strncpy(t, k.dptr, k.dsize);
- XX t[k.dsize] = 0;
- XX printf("%s\n", t);
- XX }
- XX exit(0);
- XX}
- SHAR_EOF
- if test 406 -ne "`wc -c viewdict.c`"
- then
- echo shar: error transmitting viewdict.c '(should have been 406 characters)'
- fi
- echo shar: extracting wormwords '(3278 characters)'
- sed 's/^XX//' << \SHAR_EOF > wormwords
- XXaaa
- XXacademia
- XXaerobics
- XXairplane
- XXalbany
- XXalbatross
- XXalbert
- XXalex
- XXalexander
- XXalgebra
- XXaliases
- XXalphabet
- XXama
- XXamorphous
- XXanalog
- XXanchor
- XXandromache
- XXanimals
- XXanswer
- XXanthropogenic
- XXanvils
- XXanything
- XXaria
- XXariadne
- XXarrow
- XXarthur
- XXathena
- XXatmosphere
- XXaztecs
- XXazure
- XXbacchus
- XXbailey
- XXbanana
- XXbananas
- XXbandit
- XXbanks
- XXbarber
- XXbaritone
- XXbass
- XXbassoon
- XXbatman
- XXbeater
- XXbeauty
- XXbeethoven
- XXbeloved
- XXbenz
- XXbeowulf
- XXberkeley
- XXberliner
- XXberyl
- XXbeverly
- XXbicameral
- XXbob
- XXbrenda
- XXbrian
- XXbridget
- XXbroadway
- XXbumbling
- XXburgess
- XXcampanile
- XXcantor
- XXcardinal
- XXcarmen
- XXcarolina
- XXcaroline
- XXcascades
- XXcastle
- XXcat
- XXcayuga
- XXceltics
- XXcerulean
- XXchange
- XXcharles
- XXcharming
- XXcharon
- XXchester
- XXcigar
- XXclassic
- XXclusters
- XXcoffee
- XXcoke
- XXcollins
- XXcommrades
- XXcomputer
- XXcondo
- XXcookie
- XXcooper
- XXcornelius
- XXcouscous
- XXcreation
- XXcreosote
- XXcretin
- XXdaemon
- XXdancer
- XXdaniel
- XXdanny
- XXdave
- XXdecember
- XXdefoe
- XXdeluge
- XXdesperate
- XXdevelop
- XXdieter
- XXdigital
- XXdiscovery
- XXdisney
- XXdog
- XXdrought
- XXduncan
- XXeager
- XXeasier
- XXedges
- XXedinburgh
- XXedwin
- XXedwina
- XXegghead
- XXeiderdown
- XXeileen
- XXeinstein
- XXelephant
- XXelizabeth
- XXellen
- XXemerald
- XXengine
- XXengineer
- XXenterprise
- XXenzyme
- XXersatz
- XXestablish
- XXestate
- XXeuclid
- XXevelyn
- XXextension
- XXfairway
- XXfelicia
- XXfender
- XXfermat
- XXfidelity
- XXfinite
- XXfishers
- XXflakes
- XXfloat
- XXflower
- XXflowers
- XXfoolproof
- XXfootball
- XXforesight
- XXformat
- XXforsythe
- XXfourier
- XXfred
- XXfriend
- XXfrighten
- XXfun
- XXfungible
- XXgabriel
- XXgardner
- XXgarfield
- XXgauss
- XXgeorge
- XXgertrude
- XXginger
- XXglacier
- XXgnu
- XXgolfer
- XXgorgeous
- XXgorges
- XXgosling
- XXgouge
- XXgraham
- XXgryphon
- XXguest
- XXguitar
- XXgumption
- XXguntis
- XXhacker
- XXhamlet
- XXhandily
- XXhappening
- XXharmony
- XXharold
- XXharvey
- XXhebrides
- XXheinlein
- XXhello
- XXhelp
- XXherbert
- XXhiawatha
- XXhibernia
- XXhoney
- XXhorse
- XXhorus
- XXhutchins
- XXimbroglio
- XXimperial
- XXinclude
- XXingres
- XXinna
- XXinnocuous
- XXirishman
- XXisis
- XXjapan
- XXjessica
- XXjester
- XXjixian
- XXjohnny
- XXjoseph
- XXjoshua
- XXjudith
- XXjuggle
- XXjulia
- XXkathleen
- XXkermit
- XXkernel
- XXkirkland
- XXknight
- XXladle
- XXlambda
- XXlamination
- XXlarkin
- XXlarry
- XXlazarus
- XXlebesgue
- XXlee
- XXleland
- XXleroy
- XXlewis
- XXlight
- XXlisa
- XXlouis
- XXlynne
- XXmacintosh
- XXmack
- XXmaggot
- XXmagic
- XXmalcolm
- XXmark
- XXmarkus
- XXmarty
- XXmarvin
- XXmaster
- XXmaurice
- XXmellon
- XXmerlin
- XXmets
- XXmichael
- XXmichelle
- XXmike
- XXminimum
- XXminsky
- XXmoguls
- XXmoose
- XXmorley
- XXmozart
- XXnancy
- XXnapoleon
- XXnepenthe
- XXness
- XXnetwork
- XXnewton
- XXnext
- XXnoxious
- XXnutrition
- XXnyquist
- XXoceanography
- XXocelot
- XXolivetti
- XXolivia
- XXoracle
- XXorca
- XXorwell
- XXosiris
- XXoutlaw
- XXoxford
- XXpacific
- XXpainless
- XXpakistan
- XXpam
- XXpapers
- XXpassword
- XXpatricia
- XXpenguin
- XXpeoria
- XXpercolate
- XXpersimmon
- XXpersona
- XXpete
- XXpeter
- XXphilip
- XXphoenix
- XXpierre
- XXpizza
- XXplover
- XXplymouth
- XXpolynomial
- XXpondering
- XXpork
- XXposter
- XXpraise
- XXprecious
- XXprelude
- XXprince
- XXprinceton
- XXprotect
- XXprotozoa
- XXpumpkin
- XXpuneet
- XXpuppet
- XXrabbit
- XXrachmaninoff
- XXrainbow
- XXraindrop
- XXraleigh
- XXrandom
- XXrascal
- XXreally
- XXrebecca
- XXremote
- XXrick
- XXripple
- XXrobotics
- XXrochester
- XXrolex
- XXromano
- XXronald
- XXrosebud
- XXrosemary
- XXroses
- XXruben
- XXrules
- XXruth
- XXsal
- XXsaxon
- XXscamper
- XXscheme
- XXscott
- XXscotty
- XXsecret
- XXsensor
- XXserenity
- XXsharks
- XXsharon
- XXsheffield
- XXsheldon
- XXshiva
- XXshivers
- XXshuttle
- XXsignature
- XXsimon
- XXsimple
- XXsinger
- XXsingle
- XXsmile
- XXsmiles
- XXsmooch
- XXsmother
- XXsnatch
- XXsnoopy
- XXsoap
- XXsocrates
- XXsossina
- XXsparrows
- XXspit
- XXspring
- XXspringer
- XXsquires
- XXstrangle
- XXstratford
- XXstuttgart
- XXsubway
- XXsuccess
- XXsummer
- XXsuper
- XXsuperstage
- XXsupport
- XXsupported
- XXsurfer
- XXsuzanne
- XXswearer
- XXsymmetry
- XXtangerine
- XXtape
- XXtarget
- XXtarragon
- XXtaylor
- XXtelephone
- XXtemptation
- XXthailand
- XXtiger
- XXtoggle
- XXtomato
- XXtopography
- XXtortoise
- XXtoyota
- XXtrails
- XXtrivial
- XXtrombone
- XXtubas
- XXtuttle
- XXumesh
- XXunhappy
- XXunicorn
- XXunknown
- XXurchin
- XXutility
- XXvasant
- XXvertigo
- XXvicky
- XXvillage
- XXvirginia
- XXwarren
- XXwater
- XXweenie
- XXwhatnot
- XXwhiting
- XXwhitney
- XXwill
- XXwilliam
- XXwilliamsburg
- XXwillie
- XXwinston
- XXwisconsin
- XXwizard
- XXwombat
- XXwoodwind
- XXwormwood
- XXyacov
- XXyang
- XXyellowstone
- XXyosemite
- XXzap
- XXzimmerman
- SHAR_EOF
- if test 3278 -ne "`wc -c wormwords`"
- then
- echo shar: error transmitting wormwords '(should have been 3278 characters)'
- fi
- # End of shell archive
- exit 0
- --
- Shouter-To-Dead-Parrots @ Univ. of Texas Computation Center; Austin, Texas
- clyde@emx.utexas.edu; ...!cs.utexas.edu!ut-emx!clyde
-
- "You really have to take a broad perspective when giving pat answers
- to other people's problems." - Eyebeam
-
-
-