home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / compsrcs / misc / volume06 / chkpwd < prev    next >
Encoding:
Internet Message Format  |  1991-08-27  |  25.8 KB

  1. From decwrl!ucbvax!pasteur!ames!lll-winken!uunet!allbery Sun Apr 23 15:40:30 PDT 1989
  2. Article 860 of comp.sources.misc:
  3. Path: decwrl!ucbvax!pasteur!ames!lll-winken!uunet!allbery
  4. From: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5. Newsgroups: comp.sources.misc
  6. Subject: v06i091: Password checking routine(s)
  7. Keywords: password sanity checking code
  8. Message-ID: <53142@uunet.UU.NET>
  9. Date: 23 Apr 89 19:26:25 GMT
  10. Sender: allbery@uunet.UU.NET
  11. Reply-To: ut-emx!clyde@cs.utexas.edu (Head UNIX Hacquer)
  12. Organization: Moose & Squirrel Software
  13. Lines: 1197
  14. Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  15.  
  16. Posting-number: Volume 6, Issue 91
  17. Submitted-by: ut-emx!clyde@cs.utexas.edu (Head UNIX Hacquer)
  18. Archive-name: chkpwd
  19.  
  20. Enclosed is some code that I worked up to do some password checking.
  21. I hope it can be useful to others.
  22.  
  23. #    This is a shell archive.
  24. #    Remove everything above and including the cut line.
  25. #    Then run the rest of the file through sh.
  26. -----cut here-----cut here-----cut here-----cut here-----
  27. #!/bin/sh
  28. # shar:    Shell Archiver
  29. #    Run the following text with /bin/sh to create:
  30. #    README
  31. #    Makefile
  32. #    checkpasswd.h
  33. #    checkpasswd.c
  34. #    makedict.c
  35. #    viewdict.c
  36. #    wormwords
  37. # This archive created: Mon Jan  9 13:27:05 1989
  38. # By:    Head UNIX Hacquer (Moose & Squirrel Software)
  39. echo shar: extracting README '(1040 characters)'
  40. sed 's/^XX//' << \SHAR_EOF > README
  41. XX
  42. XXThis is a password checking program that I wrote after the infamous Internet
  43. XXworm.  I used the password cracking algorithim the worm used in order
  44. XXto check the obviousness of a password.
  45. XX
  46. XXThe routine checkpasswd.c does this.  Read the source for the routine
  47. XXfor details of how it works.  In this package are the following:
  48. XX
  49. XXREADME        This file
  50. XXMakefile    Q.E.D.
  51. XXcheckpasswd.c    Password check routine
  52. XXcheckpasswd.h    Include for checkpasswd calling
  53. XXdriver.c    Test program
  54. XXmakedict.c    Program to build dbm dictionary
  55. XXwormwords    The infamous worm password list
  56. XXviewdict.c    Program to view dbm dictionary
  57. XX
  58. XXI hope this can be a kernel of intelligent password checking for 4BSD systems.
  59. XX
  60. XXI am working on a replacement for the BSD passwd program, which should be
  61. XXavailable soon.
  62. XX
  63. XXContents copyright 1989 Clyde W. Hoover (Moose & Squirrel Software, NotInc.)
  64. XX
  65. XXDistribution unlimited provided copyright notice is retained.
  66. XXPlease spread this around as much as useful.
  67. XX
  68. XX    Clyde Hoover
  69. XX    Computation Center
  70. XX    The University of Texas at Austin
  71. XX    clyde@emx.utexas.edu
  72. SHAR_EOF
  73. if test 1040 -ne "`wc -c README`"
  74. then
  75. echo shar: error transmitting README '(should have been 1040 characters)'
  76. fi
  77. echo shar: extracting Makefile '(670 characters)'
  78. sed 's/^XX//' << \SHAR_EOF > Makefile
  79. XX#
  80. XX#    Make password checking routines and test program
  81. XX
  82. XX#
  83. XX#    The checkpasswd routine depends upon the existence of the ndbm
  84. XX#    routines in the 4.3BSD libc.  Changes will have to be made to
  85. XX#    checkpasswd.c if these are not available.
  86. XX#
  87. XXCFLAGS    = -g
  88. XX
  89. XXpwtest: driver.o checkpasswd.o
  90. XX    cc $(CFLAGS) -o pwtest driver.o checkpasswd.o
  91. XX
  92. XXcheckpasswd.o: checkpasswd.c checkpasswd.h
  93. XX    cc $(CFLAGS) -c checkpasswd.c
  94. XX
  95. XXmakedict: makedict.c
  96. XX    cc $(CFLAGS) -o makedict makedict.c
  97. XX
  98. XXviewdict: viewdict.c
  99. XX    cc $(CFLAGS) -o viewdict viewdict.c
  100. XX
  101. XXpwdict:    wormlist makedict
  102. XX    -rm -f pwdict
  103. XX    cat /usr/dict/words wormlist | makedict pwdict
  104. XX    @echo install pwdict to where PWDICT points to in checkpasswd.c
  105. SHAR_EOF
  106. if test 670 -ne "`wc -c Makefile`"
  107. then
  108. echo shar: error transmitting Makefile '(should have been 670 characters)'
  109. fi
  110. echo shar: extracting checkpasswd.h '(1399 characters)'
  111. sed 's/^XX//' << \SHAR_EOF > checkpasswd.h
  112. XX/*
  113. XX *    passwdcheck.h
  114. XX *
  115. XX *      Copyright 1989 Clyde W. Hoover (Moose & Squirrel Software, NotInc.)
  116. XX *
  117. XX */
  118. XX
  119. XX#define    EXPORT    /**/
  120. XX#define    IMPORT    extern
  121. XX
  122. XX#define    PWCK_FAIL    -1
  123. XX#define    PWCK_OK        0
  124. XX#define    PWCK_NULL    1
  125. XX#define    PWCK_OBVIOUS    2
  126. XX#define    PWCK_FINGER    3
  127. XX#define    PWCK_INDICT    4
  128. XX#define    PWCK_ILLCHAR    5
  129. XX#define    PWCK_SHORT    6
  130. XX
  131. XX/*
  132. XX *    Return codes for checkpassword() are:
  133. XX *
  134. XX *    PWCK_OK if <password> is ok to use
  135. XX *    PWCK_FAIL if something failed during the check process
  136. XX *    PWCK_NULL if <password> is the null string
  137. XX *    PWCK_OBVIOUS if <password> is too "obvious"
  138. XX *        (equals login name, host name, 'zzzz' )
  139. XX *    PWCK_FINGER if <password> is in the users' passwd/finger info
  140. XX *    PWCK_INDICT if <password> is in the dictionaries checked
  141. XX *    PWCK_ILLCHAR if <password> is lexically illegal
  142. XX *    PWCK_SHORT if <password> is too short
  143. XX */
  144. XX
  145. XX/*
  146. XX *    Password checking peference block
  147. XX */
  148. XXstruct pwck_preferences {
  149. XX    char    OneCaseOk,    /* Are single-case pwds acceptable */
  150. XX        CtrlOk,        /* Are control characters acceptable */
  151. XX        CharRunLen,    /* How long can run of characters be  */
  152. XX        MinPwLen;    /* Minimum password length */
  153. XX    char    *EgrepPath;    /* Path to the 'egrep' program */
  154. XX};
  155. XX
  156. XX/*
  157. XX *    Preference list
  158. XX */
  159. XXIMPORT struct pwck_preferences    pwck_preferences;
  160. XX
  161. XX/*
  162. XX *    List of control characters not allowed in passwords
  163. XX */
  164. XXIMPORT char        pwck_illegalcc[];
  165. XX
  166. XX/*
  167. XX *    List of dictionaries to check
  168. XX */
  169. XXIMPORT char        *pwck_dicitonaries[];
  170. XX
  171. SHAR_EOF
  172. if test 1399 -ne "`wc -c checkpasswd.h`"
  173. then
  174. echo shar: error transmitting checkpasswd.h '(should have been 1399 characters)'
  175. fi
  176. echo shar: extracting checkpasswd.c '(13550 characters)'
  177. sed 's/^XX//' << \SHAR_EOF > checkpasswd.c
  178. XX/*
  179. XX *    checkpasswd.c - Login password check routines.
  180. XX *
  181. XX *    Perform various sanity and security checks on a password candidate.
  182. XX *
  183. XX *    Written December, 1988
  184. XX *
  185. XX *    Copyright 1989 Clyde W. Hoover (Moose & Squirrel Software, NotInc.)
  186. XX *
  187. XX *        Clyde Hoover
  188. XX *        Computation Center
  189. XX *        The University of Texas at Austin
  190. XX *        Austin, Texas
  191. XX *        clyde@emx.utexas.edu
  192. XX */
  193. XX
  194. XX#ifndef lint
  195. XXstatic char sccsid[] = "%W% %G% (cc.utexas.edu) %P%";
  196. XX#endif
  197. XX
  198. XX#include <sys/types.h>
  199. XX#include <strings.h>
  200. XX#include <ctype.h>
  201. XX
  202. XX#define    LOCAL    static
  203. XX
  204. XX#include "checkpasswd.h"
  205. XX
  206. XX/*
  207. XX *    Special string compare defines.
  208. XX */
  209. XX#define    try(P,C,V)    { if (cistrcmp(P,C) == 0) return(V); }
  210. XX#define    mtry(P,C,V)    { int i; if ((i = StrAllCmp(P,C,V)) != PWCK_OK) return(i); }
  211. XX
  212. XX/*
  213. XX *    Table of operational parameter preferences.
  214. XX *    May be modified by the caller.
  215. XX */
  216. XXEXPORT
  217. XXstruct pwck_preferences    pwck_preferences = {
  218. XX    1,        /* single-case pwds ok */
  219. XX    1,        /* control chars ok */
  220. XX    3,        /* dup length = 3 */
  221. XX    4,        /* minimum length */
  222. XX    "PATH=/bin:/usr/bin:/usr/ucb; egrep"    /* How to find egrep */
  223. XX};
  224. XX
  225. XX/*
  226. XX *    Table of control chars best avoided -
  227. XX *    mostly commonly-used terminal special chars.
  228. XX *    May be modified by the caller.
  229. XX */
  230. XX#define    ctrl(d)    ('d' & 037)
  231. XX
  232. XXEXPORT
  233. XXchar    pwck_illegalcc[128] = {
  234. XX    ctrl(c), ctrl(d), ctrl(h), /* ctrl(i),*/  ctrl(j), ctrl(m),
  235. XX    ctrl(o), ctrl(r), ctrl(s), ctrl(q), ctrl(z), ctrl(\\),
  236. XX    ctrl([),    /* escape */
  237. XX    '\0177',    /* rubout */
  238. XX    0
  239. XX};
  240. XX
  241. XX#define    PWDICT        "/usr/dict/pwwords"
  242. XX/*
  243. XX *    List of forbidden password dictionaries to look in.
  244. XX *    May be modified by the caller.
  245. XX */
  246. XXstatic char    *pwck_dicitonaries[16] = {
  247. XX    PWDICT,            /* illegal passwords list */
  248. XX    0
  249. XX};
  250. XX
  251. XX/*
  252. XX *    The 'pwck_*' routines all use the PWCK_* return
  253. XX *    codes, which are then propigated up to the caller of checkpassword().
  254. XX *
  255. XX *    All pwck_* routines in the table below are called thusly:
  256. XX *        pwck_*(password, userid)
  257. XX *            password = plaintext password string to test.
  258. XX *            userid = the user id which wants to use <password>.
  259. XX *
  260. XX *    Table of check functions to be called by checkpassword()
  261. XX */
  262. XXint    pwck_lexical(), pwck_local(), pwck_passwd(), pwck_dictionary();
  263. XX
  264. XXtypedef    int    (*function)();
  265. XX
  266. XXLOCAL
  267. XXfunction pwck_vector[] = {
  268. XX    pwck_lexical,
  269. XX    pwck_local,
  270. XX    pwck_passwd,
  271. XX    pwck_dictionary,
  272. XX    0
  273. XX};
  274. XX
  275. XX/* ------------------------------------------------------------------- */
  276. XX
  277. XX/*
  278. XX *    checkpassword - Password candidate sanity checker.
  279. XX *
  280. XX *    Arguments;
  281. XX *        password = plain text password string to check.
  282. XX *        userid = the uid whom the password is for, -1 to disable.
  283. XX *
  284. XX *    Returns:
  285. XX *        PWCK_OK if <password> is ok to use.
  286. XX *        PWCK_FAIL if something failed during the check process.
  287. XX *        PWCK_NULL if <password> is the null string
  288. XX *        PWCK_OBVIOUS if <password> is too "obvious".
  289. XX *            (equals login name, host name, 'zzzz' ).
  290. XX *        PWCK_FINGER if <password> is in the users' passwd/finger info.
  291. XX *        PWCK_INDICT if <password> is in the dictionaries checked.
  292. XX *        PWCK_ILLCHAR if <password> is lexically illegal.
  293. XX *        PWCK_SHORT if <password> is too short.
  294. XX *
  295. XX */
  296. XXcheckpassword(password, userid)
  297. XXchar    *password;        /* Plaintext of password to check */
  298. XXint    userid;            /* The user this is for */
  299. XX{
  300. XX    int        rcode;        /* General purpose scratch */
  301. XX    function    *checkfunc;    /* Check function pointer */
  302. XX
  303. XX    if (password == 0 || *password == 0)
  304. XX        return(PWCK_NULL);        /* Null password */
  305. XX
  306. XX    for (checkfunc = pwck_vector; *checkfunc; checkfunc++) {
  307. XX        if ((rcode = (*checkfunc)(password, userid)) != PWCK_OK)
  308. XX            return(rcode);
  309. XX    }
  310. XX    return(PWCK_OK);
  311. XX}
  312. XX
  313. XX
  314. XX/* ------------------------------------------------------------------- */
  315. XX
  316. XX#define    P_U    0x1     /* Upper case in password */
  317. XX#define    P_L    0x2     /* Lower case in password */
  318. XX#define    P_C    0x4     /* Control chars in password */
  319. XX#define    P_D    0x8     /* Digits in password */
  320. XX#define    P_P    0x10     /* Punctutation chars in password */
  321. XX
  322. XX#define    hasone(P)    (what |= (P))
  323. XX#define    hasany(P)    ((what & (P)) == (P))
  324. XX
  325. XX#define    ccok    pwck_preferences.CtrlOk
  326. XX#define    mcok    pwck_preferences.OneCaseOk
  327. XX#define    runl    pwck_preferences.CharRunLen
  328. XX#define    minl    pwck_preferences.MinPwLen
  329. XX
  330. XX/*
  331. XX *    pwck_lexical - Perform lexical analysis of password candidate.
  332. XX *
  333. XX *    Things which are ok:
  334. XX *        Mixed case
  335. XX *        Digits
  336. XX *        Punctutation
  337. XX *        Control characters (except for those in the forbidden table)
  338. XX *            (controlled by the preferences)
  339. XX *
  340. XX *    Things which are NOT ok:
  341. XX *        Passwords less that 'minl' length
  342. XX *        Runs of more than <runl> of the same character (e.g. 'zzz')
  343. XX *        Single-case strings
  344. XX *            (controlled by the preferences)
  345. XX *
  346. XX *    Things not checked for:
  347. XX *        Cycles of character groups (e.g. 'aabbcc' or 'ababab')
  348. XX */
  349. XXstatic int
  350. XXpwck_lexical(password, userid)
  351. XXchar    *password;
  352. XXint    userid;        /* NOTUSED */
  353. XX{
  354. XX    int    rc;        /* Duplicate character run count */
  355. XX    char    *p = password;    /* Scratch */
  356. XX    char    what = 0,    /* Lexical analysis result flags */
  357. XX        last = 0;    /* Last character seen (for run checks) */
  358. XX
  359. XX    if (minl && strlen(password) < minl)
  360. XX        return(PWCK_SHORT);
  361. XX
  362. XX    for (p = password; *p; p++) {
  363. XX        if (*p != last) {
  364. XX            last = *p;
  365. XX            rc = 0;
  366. XX        }
  367. XX        else {        /* Run of same characters */
  368. XX            if (runl && ++rc >= runl)
  369. XX                return(PWCK_OBVIOUS);
  370. XX        }
  371. XX        if (*p < ' ') {        /* Control character */
  372. XX            if (!ccok)
  373. XX                return(PWCK_ILLCHAR);
  374. XX            if (index (pwck_illegalcc, *p))
  375. XX                return(PWCK_ILLCHAR);
  376. XX            hasone(P_C);
  377. XX        }
  378. XX        else if (isupper(*p))    hasone(P_U);
  379. XX        else if (islower(*p))    hasone(P_L);
  380. XX        else if (ispunct(*p))    hasone(P_P);
  381. XX        else if (isdigit(*p))    hasone(P_D);
  382. XX    }
  383. XX    if (hasany(P_U | P_L))    return(PWCK_OK);    /* UC+lc */
  384. XX    if (hasany(P_D))    return(PWCK_OK);    /* Numbers */
  385. XX    if (hasany(P_P))    return(PWCK_OK);    /* Punctutation chars */
  386. XX    if (hasany(P_C))    return(PWCK_OK);    /* Control chars */
  387. XX    /*
  388. XX     *    Check for mono-case passwords 
  389. XX     */
  390. XX    if (!hasany(P_U) && mcok)    /* All lower case alpha */
  391. XX        return(PWCK_OK);
  392. XX    if (!hasany(P_L) && mcok)    /* All upper case alpha */
  393. XX        return(PWCK_OK);
  394. XX
  395. XX    return(PWCK_ILLCHAR);
  396. XX}
  397. XX#undef    hasone
  398. XX#undef    hasany
  399. XX
  400. XX/*
  401. XX *    pwck_local - Perform 'local' password checks.
  402. XX *
  403. XX *    Returns:
  404. XX *        PWCK_OBVIOUS if <password> == hostname
  405. XX *        PWCK_OK if otherwise
  406. XX */
  407. XXLOCAL int
  408. XXpwck_local(password, userid)
  409. XXchar    *password;
  410. XXint    userid;        /* NOTUSED */
  411. XX{
  412. XX    char    myname[32];        /* Scratch */
  413. XX
  414. XX    (void) gethostname(myname, sizeof(myname));
  415. XX    try(password, myname, PWCK_OBVIOUS);
  416. XX    /*
  417. XX     * Want to try full canoncalized hostname here in case gethostname
  418. XX     * didn't get that for us.
  419. XX     *
  420. XX     * Then look in users' .rhosts and try those strings (maybe)
  421. XX     */
  422. XX    return(PWCK_OK);
  423. XX}
  424. XX
  425. XX/*
  426. XX *    pwck_dictionary - Look in the forbidden password dictionaries.
  427. XX *
  428. XX *    Returns:
  429. XX *        PWCK_INDICT if <password> was in any dictionary
  430. XX *        PWCK_OK if not
  431. XX */
  432. XXLOCAL int
  433. XXpwck_dictionary(password, userid)
  434. XXchar    *password;
  435. XXint    userid;        /* NOTUSED */
  436. XX{
  437. XX    int    i,        /* Counter */
  438. XX        rcode;        /* Return code temp */
  439. XX
  440. XX    for (i = 0; pwck_dicitonaries[i]; i++) {
  441. XX        if ((rcode =
  442. XX             IsInDictionary(pwck_dicitonaries[i], password)) != PWCK_OK)
  443. XX            return(rcode);
  444. XX    }
  445. XX    return(PWCK_OK);
  446. XX}
  447. XX
  448. XX/*
  449. XX *    IsInDictionary - look for <password> in <dictionary>
  450. XX *
  451. XX *    Use a DBM version of the dictionary if present, 
  452. XX *    use egrep to search the flat file if not.
  453. XX *
  454. XX *    Returns:
  455. XX *        PWCK_INDICT if <password> was found in <dictionary>
  456. XX *        PWCK_OK if not
  457. XX */
  458. XX#define    returnwith(code) { dbm_close(dbp); return(code); }
  459. XX#define    EGREP    pwck_preferences.EgrepPath
  460. XX
  461. XX#include <ndbm.h>
  462. XX
  463. XXLOCAL int
  464. XXIsInDictionary(dictionary, password)
  465. XXchar    *dictionary,        /* Pathname of dictionary */
  466. XX    *password;        /* Plaintext of password */
  467. XX{
  468. XX    DBM    *dbp;        /* DBM database pointer */
  469. XX    datum    k,        /* DBM lookup key */
  470. XX        d;        /* DBM lookup datum */
  471. XX    int    uc = isupper(password[0]);    /* Is first char UC? */
  472. XX    char    pwtemp[128];    /* Scratch buffer */
  473. XX
  474. XX    if ((dbp = dbm_open(dictionary, 0, 0)) == (DBM *)0) {
  475. XX        char    command[128];    /* Command build buffer */
  476. XX        int    rc;        /* System() return code */
  477. XX
  478. XX        if (access(dictionary, 0) < 0)
  479. XX            return(PWCK_OK);
  480. XX        /*
  481. XX         * If the first letter is capitalized, look for
  482. XX         * "[wW]ord" else look for "word"
  483. XX         */
  484. XX        if (uc) 
  485. XX            (void) sprintf(command,
  486. XX                "%s -s '^[%c%c]%s$' %s > /dev/null",
  487. XX                EGREP, password[0], password[0] & ~040,
  488. XX                &password[1], dictionary);
  489. XX        else
  490. XX            (void) sprintf(command, "%s -s '^%s$' %s > /dev/null",
  491. XX                EGREP, password, dictionary);
  492. XX        rc = system(command);
  493. XX        if (rc == 0)
  494. XX            return(PWCK_INDICT);
  495. XX        else
  496. XX            return(PWCK_OK);
  497. XX    } 
  498. XX    /*
  499. XX     * Look in the DBM version of the dictionary.
  500. XX     * Look for <password>, then if the first letter
  501. XX     * is capitalized, force to lower and look again.  I don't care
  502. XX     * if <password> is in the dictionary but has mixed case letters,
  503. XX     * but if the first letter has been capitalized, I care because
  504. XX     * that's not a sufficent permutation to be secure.
  505. XX     */
  506. XX    (void) strcpy(pwtemp, password);
  507. XX    k.dptr = pwtemp;
  508. XX    k.dsize = strlen(pwtemp);
  509. XX    d = dbm_fetch(dbp, k);
  510. XX    if (d.dptr)
  511. XX        returnwith(PWCK_INDICT);
  512. XX    if (uc) {
  513. XX        pwtemp[0] |= 040;
  514. XX        d = dbm_fetch(dbp, k);
  515. XX        if (d.dptr)
  516. XX            returnwith(PWCK_INDICT);
  517. XX    }
  518. XX    returnwith(PWCK_OK);
  519. XX}
  520. XX#undef    returnwith
  521. XX
  522. XX
  523. XX/*
  524. XX *    pwck_password - Check password candidate against the users' password
  525. XX *        file information, or any other information that is publicly
  526. XX *        available about this user that a bandit could use as
  527. XX *        password guesses.
  528. XX *
  529. XX *    Here is the place to search your 'finger' database.
  530. XX */
  531. XX#include    <pwd.h>
  532. XX
  533. XXstatic int
  534. XXpwck_passwd(password, userid)
  535. XXchar    *password;
  536. XXint    userid;
  537. XX{
  538. XX    char    temp[128];        /* Scratch */
  539. XX    struct passwd    *pwp;        /* Pointer to user information */
  540. XX
  541. XX    if (userid < 0)            /* Can't do user checks */
  542. XX        return(PWCK_OK);
  543. XX
  544. XX    pwp = getpwuid(userid);
  545. XX    if (pwp == 0)
  546. XX        return(PWCK_FAIL);
  547. XX
  548. XX    try(password, pwp->pw_name, PWCK_OBVIOUS); /* Checks 'name' and 'Name' */
  549. XX
  550. XX    (void) strcpy(temp, pwp->pw_name);
  551. XX    (void) strcat(temp, pwp->pw_name);
  552. XX    try(password, temp, PWCK_OBVIOUS);    /* Check 'namename' */
  553. XX
  554. XX    (void) strcpy(temp, pwp->pw_name);
  555. XX    MirrorString(temp);
  556. XX    try(password, temp, PWCK_OBVIOUS);    /* 'eman' */
  557. XX
  558. XX    /*
  559. XX     * Try every word in user's GECOS entry
  560. XX     */
  561. XX    mtry(password, pwp->pw_gecos, PWCK_FINGER);
  562. XX    return(PWCK_OK);
  563. XX}
  564. XX/* ------------------------------------------------------------------- */
  565. XX/*
  566. XX *    StrAllCmp - Compare all sub-strings (delineated by white space)
  567. XX *
  568. XX *    Returns:
  569. XX *        PWCK_OK if no match found
  570. XX *        rc if match found
  571. XX */
  572. XXLOCAL
  573. XXStrAllCmp(s1, s2, rc)
  574. XXchar    *s1,        /* String to look for */
  575. XX    *s2;        /* String to look for <s1> in */
  576. XXint    rc;        /* What to return on match */
  577. XX{
  578. XX    int    l;        /* Temp */
  579. XX
  580. XX    for (l = strlen(s1); *s2; s2++)
  581. XX        if (cistrncmp(s1, s2, l) == 0)
  582. XX            return (rc);
  583. XX    return(PWCK_OK);
  584. XX}
  585. XX
  586. XX/*
  587. XX *    MirrorString - reverse a string in place
  588. XX */
  589. XXLOCAL
  590. XXMirrorString(s)
  591. XXchar    *s;        /* String to reverse */
  592. XX{
  593. XX    char    *p;    /* Scratch */
  594. XX    char    t[128];    /* Scratch */
  595. XX    
  596. XX    (void) strcpy(t,s);
  597. XX    p = t;
  598. XX    while (*p) p++;        /* Find end of string */
  599. XX    --p;
  600. XX    for (; *s; )
  601. XX        *s++ = *p--;
  602. XX}
  603. XX
  604. XX/*
  605. XX *    Case indepedant string comparasion routines swiped from
  606. XX *    the source to MIT Hesiod.
  607. XX */
  608. XX/*
  609. XX * Copyright (c) 1986 Regents of the University of California.
  610. XX * All rights reserved.  The Berkeley software License Agreement
  611. XX * specifies the terms and conditions for redistribution.
  612. XX */
  613. XX
  614. XX/*
  615. XX * This array is designed for mapping upper and lower case letter
  616. XX * together for a case independent comparison.  The mappings are
  617. XX * based upon ascii character sequences.
  618. XX */
  619. XX
  620. XXLOCAL char charmap[] = {
  621. XX    '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
  622. XX    '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
  623. XX    '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
  624. XX    '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
  625. XX    '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
  626. XX    '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
  627. XX    '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
  628. XX    '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
  629. XX    '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  630. XX    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  631. XX    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  632. XX    '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137',
  633. XX    '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
  634. XX    '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
  635. XX    '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
  636. XX    '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
  637. XX    '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
  638. XX    '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
  639. XX    '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
  640. XX    '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
  641. XX    '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
  642. XX    '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
  643. XX    '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
  644. XX    '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
  645. XX    '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  646. XX    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  647. XX    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  648. XX    '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337',
  649. XX    '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
  650. XX    '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
  651. XX    '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
  652. XX    '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
  653. XX};
  654. XX
  655. XXLOCAL
  656. XXcistrcmp(s1, s2)
  657. XXregister char *s1, *s2;
  658. XX{
  659. XX    register char *cm = charmap;
  660. XX
  661. XX    while (cm[*s1] == cm[*s2++])
  662. XX        if (*s1++=='\0')
  663. XX            return(0);
  664. XX    return(cm[*s1] - cm[*--s2]);
  665. XX}
  666. XX
  667. XXLOCAL
  668. XXcistrncmp(s1, s2, n)
  669. XXregister char *s1, *s2;
  670. XXregister n;
  671. XX{
  672. XX    register char *cm = charmap;
  673. XX
  674. XX    while (--n >= 0 && cm[*s1] == cm[*s2++])
  675. XX        if (*s1++ == '\0')
  676. XX            return(0);
  677. XX    return(n<0 ? 0 : cm[*s1] - cm[*--s2]);
  678. XX}
  679. XX
  680. XX/* END */
  681. SHAR_EOF
  682. if test 13550 -ne "`wc -c checkpasswd.c`"
  683. then
  684. echo shar: error transmitting checkpasswd.c '(should have been 13550 characters)'
  685. fi
  686. echo shar: extracting makedict.c '(653 characters)'
  687. sed 's/^XX//' << \SHAR_EOF > makedict.c
  688. XX/*
  689. XX *    makedict - Make DBM version of password dictionary
  690. XX */
  691. XX
  692. XX#include <sys/file.h>
  693. XX#include <stdio.h>
  694. XX#include <ndbm.h>
  695. XX
  696. XXextern char    *index();
  697. XX
  698. XXchar    line[80];
  699. XX
  700. XXmain(argc, argv)
  701. XXchar    *argv[];
  702. XX{
  703. XX    DBM    *dp;
  704. XX    int    recs = 0;
  705. XX    datum    d,
  706. XX        k;
  707. XX
  708. XX    dp = dbm_open(argv[1], O_RDWR, 0);
  709. XX    if (dp == 0) {
  710. XX        if ((dp = dbm_open(argv[1], O_RDWR|O_CREAT, 0644)) == 0) {
  711. XX            perror("open dbm");
  712. XX            exit(1);
  713. XX        }
  714. XX    }
  715. XX    while (!feof(stdin)) {
  716. XX        char    *p;
  717. XX
  718. XX        fgets(line, 80, stdin);
  719. XX        p = index(line, '\n');
  720. XX        if (p) *p = 0;
  721. XX        d.dptr = line;
  722. XX        d.dsize = strlen(line);
  723. XX        dbm_store(dp, d, d, DBM_INSERT);
  724. XX        recs++;
  725. XX    }
  726. XX    dbm_close(dp);
  727. XX    printf("%s built, %d records\n", argv[1], recs);
  728. XX}
  729. SHAR_EOF
  730. if test 653 -ne "`wc -c makedict.c`"
  731. then
  732. echo shar: error transmitting makedict.c '(should have been 653 characters)'
  733. fi
  734. echo shar: extracting viewdict.c '(406 characters)'
  735. sed 's/^XX//' << \SHAR_EOF > viewdict.c
  736. XX/*
  737. XX *    viewdict - View DBM version of a password dictionary
  738. XX */
  739. XX
  740. XX#include <sys/file.h>
  741. XX#include <ndbm.h>
  742. XX
  743. XXmain(argc, argv)
  744. XXchar    *argv[];
  745. XX{
  746. XX    DBM    *dp;
  747. XX    datum    k;
  748. XX    char    t[128];
  749. XX
  750. XX    if ((dp = dbm_open(argv[1], O_RDONLY, 0)) == 0) {
  751. XX        perror(argv[1]);
  752. XX        exit(1);
  753. XX    }
  754. XX    for (k = dbm_firstkey(dp); k.dptr != 0; k = dbm_nextkey(dp)) {
  755. XX        strncpy(t, k.dptr, k.dsize);
  756. XX        t[k.dsize] = 0;
  757. XX        printf("%s\n", t);
  758. XX    }
  759. XX    exit(0);
  760. XX}
  761. SHAR_EOF
  762. if test 406 -ne "`wc -c viewdict.c`"
  763. then
  764. echo shar: error transmitting viewdict.c '(should have been 406 characters)'
  765. fi
  766. echo shar: extracting wormwords '(3278 characters)'
  767. sed 's/^XX//' << \SHAR_EOF > wormwords
  768. XXaaa
  769. XXacademia
  770. XXaerobics
  771. XXairplane
  772. XXalbany
  773. XXalbatross
  774. XXalbert
  775. XXalex
  776. XXalexander
  777. XXalgebra
  778. XXaliases
  779. XXalphabet
  780. XXama
  781. XXamorphous
  782. XXanalog
  783. XXanchor
  784. XXandromache
  785. XXanimals
  786. XXanswer
  787. XXanthropogenic
  788. XXanvils
  789. XXanything
  790. XXaria
  791. XXariadne
  792. XXarrow
  793. XXarthur
  794. XXathena
  795. XXatmosphere
  796. XXaztecs
  797. XXazure
  798. XXbacchus
  799. XXbailey
  800. XXbanana
  801. XXbananas
  802. XXbandit
  803. XXbanks
  804. XXbarber
  805. XXbaritone
  806. XXbass
  807. XXbassoon
  808. XXbatman
  809. XXbeater
  810. XXbeauty
  811. XXbeethoven
  812. XXbeloved
  813. XXbenz
  814. XXbeowulf
  815. XXberkeley
  816. XXberliner
  817. XXberyl
  818. XXbeverly
  819. XXbicameral
  820. XXbob
  821. XXbrenda
  822. XXbrian
  823. XXbridget
  824. XXbroadway
  825. XXbumbling
  826. XXburgess
  827. XXcampanile
  828. XXcantor
  829. XXcardinal
  830. XXcarmen
  831. XXcarolina
  832. XXcaroline
  833. XXcascades
  834. XXcastle
  835. XXcat
  836. XXcayuga
  837. XXceltics
  838. XXcerulean
  839. XXchange
  840. XXcharles
  841. XXcharming
  842. XXcharon
  843. XXchester
  844. XXcigar
  845. XXclassic
  846. XXclusters
  847. XXcoffee
  848. XXcoke
  849. XXcollins
  850. XXcommrades
  851. XXcomputer
  852. XXcondo
  853. XXcookie
  854. XXcooper
  855. XXcornelius
  856. XXcouscous
  857. XXcreation
  858. XXcreosote
  859. XXcretin
  860. XXdaemon
  861. XXdancer
  862. XXdaniel
  863. XXdanny
  864. XXdave
  865. XXdecember
  866. XXdefoe
  867. XXdeluge
  868. XXdesperate
  869. XXdevelop
  870. XXdieter
  871. XXdigital
  872. XXdiscovery
  873. XXdisney
  874. XXdog
  875. XXdrought
  876. XXduncan
  877. XXeager
  878. XXeasier
  879. XXedges
  880. XXedinburgh
  881. XXedwin
  882. XXedwina
  883. XXegghead
  884. XXeiderdown
  885. XXeileen
  886. XXeinstein
  887. XXelephant
  888. XXelizabeth
  889. XXellen
  890. XXemerald
  891. XXengine
  892. XXengineer
  893. XXenterprise
  894. XXenzyme
  895. XXersatz
  896. XXestablish
  897. XXestate
  898. XXeuclid
  899. XXevelyn
  900. XXextension
  901. XXfairway
  902. XXfelicia
  903. XXfender
  904. XXfermat
  905. XXfidelity
  906. XXfinite
  907. XXfishers
  908. XXflakes
  909. XXfloat
  910. XXflower
  911. XXflowers
  912. XXfoolproof
  913. XXfootball
  914. XXforesight
  915. XXformat
  916. XXforsythe
  917. XXfourier
  918. XXfred
  919. XXfriend
  920. XXfrighten
  921. XXfun
  922. XXfungible
  923. XXgabriel
  924. XXgardner
  925. XXgarfield
  926. XXgauss
  927. XXgeorge
  928. XXgertrude
  929. XXginger
  930. XXglacier
  931. XXgnu
  932. XXgolfer
  933. XXgorgeous
  934. XXgorges
  935. XXgosling
  936. XXgouge
  937. XXgraham
  938. XXgryphon
  939. XXguest
  940. XXguitar
  941. XXgumption
  942. XXguntis
  943. XXhacker
  944. XXhamlet
  945. XXhandily
  946. XXhappening
  947. XXharmony
  948. XXharold
  949. XXharvey
  950. XXhebrides
  951. XXheinlein
  952. XXhello
  953. XXhelp
  954. XXherbert
  955. XXhiawatha
  956. XXhibernia
  957. XXhoney
  958. XXhorse
  959. XXhorus
  960. XXhutchins
  961. XXimbroglio
  962. XXimperial
  963. XXinclude
  964. XXingres
  965. XXinna
  966. XXinnocuous
  967. XXirishman
  968. XXisis
  969. XXjapan
  970. XXjessica
  971. XXjester
  972. XXjixian
  973. XXjohnny
  974. XXjoseph
  975. XXjoshua
  976. XXjudith
  977. XXjuggle
  978. XXjulia
  979. XXkathleen
  980. XXkermit
  981. XXkernel
  982. XXkirkland
  983. XXknight
  984. XXladle
  985. XXlambda
  986. XXlamination
  987. XXlarkin
  988. XXlarry
  989. XXlazarus
  990. XXlebesgue
  991. XXlee
  992. XXleland
  993. XXleroy
  994. XXlewis
  995. XXlight
  996. XXlisa
  997. XXlouis
  998. XXlynne
  999. XXmacintosh
  1000. XXmack
  1001. XXmaggot
  1002. XXmagic
  1003. XXmalcolm
  1004. XXmark
  1005. XXmarkus
  1006. XXmarty
  1007. XXmarvin
  1008. XXmaster
  1009. XXmaurice
  1010. XXmellon
  1011. XXmerlin
  1012. XXmets
  1013. XXmichael
  1014. XXmichelle
  1015. XXmike
  1016. XXminimum
  1017. XXminsky
  1018. XXmoguls
  1019. XXmoose
  1020. XXmorley
  1021. XXmozart
  1022. XXnancy
  1023. XXnapoleon
  1024. XXnepenthe
  1025. XXness
  1026. XXnetwork
  1027. XXnewton
  1028. XXnext
  1029. XXnoxious
  1030. XXnutrition
  1031. XXnyquist
  1032. XXoceanography
  1033. XXocelot
  1034. XXolivetti
  1035. XXolivia
  1036. XXoracle
  1037. XXorca
  1038. XXorwell
  1039. XXosiris
  1040. XXoutlaw
  1041. XXoxford
  1042. XXpacific
  1043. XXpainless
  1044. XXpakistan
  1045. XXpam
  1046. XXpapers
  1047. XXpassword
  1048. XXpatricia
  1049. XXpenguin
  1050. XXpeoria
  1051. XXpercolate
  1052. XXpersimmon
  1053. XXpersona
  1054. XXpete
  1055. XXpeter
  1056. XXphilip
  1057. XXphoenix
  1058. XXpierre
  1059. XXpizza
  1060. XXplover
  1061. XXplymouth
  1062. XXpolynomial
  1063. XXpondering
  1064. XXpork
  1065. XXposter
  1066. XXpraise
  1067. XXprecious
  1068. XXprelude
  1069. XXprince
  1070. XXprinceton
  1071. XXprotect
  1072. XXprotozoa
  1073. XXpumpkin
  1074. XXpuneet
  1075. XXpuppet
  1076. XXrabbit
  1077. XXrachmaninoff
  1078. XXrainbow
  1079. XXraindrop
  1080. XXraleigh
  1081. XXrandom
  1082. XXrascal
  1083. XXreally
  1084. XXrebecca
  1085. XXremote
  1086. XXrick
  1087. XXripple
  1088. XXrobotics
  1089. XXrochester
  1090. XXrolex
  1091. XXromano
  1092. XXronald
  1093. XXrosebud
  1094. XXrosemary
  1095. XXroses
  1096. XXruben
  1097. XXrules
  1098. XXruth
  1099. XXsal
  1100. XXsaxon
  1101. XXscamper
  1102. XXscheme
  1103. XXscott
  1104. XXscotty
  1105. XXsecret
  1106. XXsensor
  1107. XXserenity
  1108. XXsharks
  1109. XXsharon
  1110. XXsheffield
  1111. XXsheldon
  1112. XXshiva
  1113. XXshivers
  1114. XXshuttle
  1115. XXsignature
  1116. XXsimon
  1117. XXsimple
  1118. XXsinger
  1119. XXsingle
  1120. XXsmile
  1121. XXsmiles
  1122. XXsmooch
  1123. XXsmother
  1124. XXsnatch
  1125. XXsnoopy
  1126. XXsoap
  1127. XXsocrates
  1128. XXsossina
  1129. XXsparrows
  1130. XXspit
  1131. XXspring
  1132. XXspringer
  1133. XXsquires
  1134. XXstrangle
  1135. XXstratford
  1136. XXstuttgart
  1137. XXsubway
  1138. XXsuccess
  1139. XXsummer
  1140. XXsuper
  1141. XXsuperstage
  1142. XXsupport
  1143. XXsupported
  1144. XXsurfer
  1145. XXsuzanne
  1146. XXswearer
  1147. XXsymmetry
  1148. XXtangerine
  1149. XXtape
  1150. XXtarget
  1151. XXtarragon
  1152. XXtaylor
  1153. XXtelephone
  1154. XXtemptation
  1155. XXthailand
  1156. XXtiger
  1157. XXtoggle
  1158. XXtomato
  1159. XXtopography
  1160. XXtortoise
  1161. XXtoyota
  1162. XXtrails
  1163. XXtrivial
  1164. XXtrombone
  1165. XXtubas
  1166. XXtuttle
  1167. XXumesh
  1168. XXunhappy
  1169. XXunicorn
  1170. XXunknown
  1171. XXurchin
  1172. XXutility
  1173. XXvasant
  1174. XXvertigo
  1175. XXvicky
  1176. XXvillage
  1177. XXvirginia
  1178. XXwarren
  1179. XXwater
  1180. XXweenie
  1181. XXwhatnot
  1182. XXwhiting
  1183. XXwhitney
  1184. XXwill
  1185. XXwilliam
  1186. XXwilliamsburg
  1187. XXwillie
  1188. XXwinston
  1189. XXwisconsin
  1190. XXwizard
  1191. XXwombat
  1192. XXwoodwind
  1193. XXwormwood
  1194. XXyacov
  1195. XXyang
  1196. XXyellowstone
  1197. XXyosemite
  1198. XXzap
  1199. XXzimmerman
  1200. SHAR_EOF
  1201. if test 3278 -ne "`wc -c wormwords`"
  1202. then
  1203. echo shar: error transmitting wormwords '(should have been 3278 characters)'
  1204. fi
  1205. #    End of shell archive
  1206. exit 0
  1207. -- 
  1208. Shouter-To-Dead-Parrots @ Univ. of Texas Computation Center; Austin, Texas  
  1209.     clyde@emx.utexas.edu; ...!cs.utexas.edu!ut-emx!clyde
  1210.  
  1211. "You really have to take a broad perspective when giving pat answers
  1212.  to other people's problems."  - Eyebeam
  1213.  
  1214.  
  1215.