home *** CD-ROM | disk | FTP | other *** search
- From: Alec.Muffett@UK.Sun.COM (Alec David Muffett)
- Newsgroups: comp.sources.misc
- Subject: v38i001: cracklib - CrackLib: A ProActive Password Security library, Part01/02
- Date: 18 Jun 1993 12:43:57 +0100
- Sender: aem@aber.ac.uk
- Approved: aem@aber.ac.uk
- Message-ID: <csm-v38i001=cracklib.124038@aber.ac.uk>
- X-Md4-Signature: 07e45cc9df2b4dfce237dbc5df60569e
-
- Submitted-by: Alec.Muffett@UK.Sun.COM (Alec David Muffett)
- Posting-number: Volume 38, Issue 1
- Archive-name: cracklib/part01
- Environment: C
-
-
-
- CrackLib is a library containing a C function (well, lots of functions
- really, but you only need to use one of them) which may be used in a
- "passwd"-like program.
-
- The idea is simple: try to prevent users from choosing passwords that
- could be guessed by "Crack" by filtering them out, at source.
-
- CrackLib is an offshoot of the the version 5 "Crack" software, and
- contains a considerable number of ideas nicked from the new software.
- At the time of writing, Crack 5 is incomplete (still awaiting purchase
- of my home box) - but I though I could share this with you.
-
- NOTE THIS WELL: CrackLib is NOT a replacement "passwd" program.
- CrackLib is a LIBRARY. CrackLib is what trendy marketdroid types would
- probably call an "enabler".
-
- The idea is that you wire it into your _own_ "passwd" program (if you
- have source); alternatively, you wire it into something like "shadow"
- from off of the net. You can use it almost _everywhere_.
-
- FOR YOUR INFORMATION:
-
- CrackLib has been tested mostly on Suns. If you can point me at ways
- round portability problems (eg: static linking, other libraries, etc)
- I'd be most grateful.
-
- A reference copy of CrackLib (+ large dictionary) can be found via
- anonymous FTP at:
-
- black.ox.ac.uk:~ftp/src/security/cracklib25.tar.Z
-
-
- - alec
- --
- #! /bin/sh
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: README MANIFEST LICENCE cracklib cracklib/fascist.c
- # cracklib/packlib.c cracklib/rules.c shadow shadow/README,CL util
- # Wrapped by alecm@uk-usenet on Fri Jun 18 12:37:27 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 1 (of 2)."'
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(9021 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- XCrackLib: A ProActive Password Sanity Library
- X
- XBy: Alec Muffett, 16th June, 1993
- X
- XAddress: alec.muffett@uk.sun.com
- X alec.muffett@sun.co.uk
- X alec_muffett@hicom.lut.ac.uk
- X
- X
- X- This software is not my fault in any way, nor indeed anybody's -
- X
- X
- X*** What is CrackLib ***
- X
- X
- XCrackLib is a library containing a C function (well, lots of functions
- Xreally, but you only need to use one of them) which may be used in a
- X"passwd"-like program.
- X
- XThe idea is simple: try to prevent users from choosing passwords that
- Xcould be guessed by "Crack" by filtering them out, at source.
- X
- XCrackLib is an offshoot of the the version 5 "Crack" software, and
- Xcontains a considerable number of ideas nicked from the new software.
- X
- XAt the time of writing, Crack 5 is incomplete (still awaiting purchase
- Xof my home box) - but I though I could share this with you.
- X
- X[ Incidentally, if Dell or anyone would like to "donate" a Linuxable
- X486DX2-66MHz box (EISA/16Mb RAM/640MB HD/AHA1740) as a development
- Xplatform for Crack, I'd be more than grateful to hear from you. 8-) ]
- X
- X
- XNOTE THIS WELL: CrackLib is NOT a replacement "passwd" program.
- XCrackLib is a LIBRARY. CrackLib is what trendy marketdroid types would
- Xprobably call an "enabler".
- X
- XThe idea is that you wire it into your _own_ "passwd" program (if you
- Xhave source); alternatively, you wire it into something like "shadow"
- Xfrom off of the net. You can use it in other things, too.
- X
- XYou can use it almost _everywhere_.
- X
- X
- X*** Advantages of CrackLib ***
- X
- X
- X1) it WORKS!
- X
- XI wrote something similar ("goodpass") a few years back, which went out
- Xwith Crack v3.x.
- X
- XGoodpass was slow and buggy and I think it was used (at least in part)
- Xin "npasswd". Hopefully, CrackLib will supplant "goodpass" entirely.
- X
- X
- X2) it's FAST!
- X
- XCrackLib finds potential passwords quickly, by using an index file to
- Xaccess dictionary words, and by keeping a table to assist binary
- Xsearching.
- X
- X
- X3) it's SMALL!
- X
- XCrackLib's dictionary is modified-DAWG compressed with a chunksize of 16
- Xwords (see Crack v5.0 docs (when it comes out) for details) - and then
- Xthe index file is built, with one entry per chunk.
- X
- XThe upshot of all this is that CrackLib can do indexed, binary searches
- Xin a 1.4 million word dictionary (raw size ~ 15Mb), but the CrackLib
- Xfiles (data+index+watermarks) occupy only ~ 7Mb. (45% original size)
- X
- XIt's even efficient over NFS !
- X
- X
- X4) it's MIND-NUMBINGLY THOROUGH!
- X
- X(is this beginning to read like a B-movie flyer, or what?)
- X
- XCrackLib makes literally hundreds of tests to determine whether you've
- Xchosen a bad password.
- X
- X* It tries to generate words from your username and gecos entry to tries
- Xto match them against what you've chosen.
- X
- X* It checks for simplistic patterns.
- X
- X* It then tries to reverse-engineer your password into a dictionary
- Xword, and searches for it in your dictionary.
- X
- X- after all that, it's PROBABLY a safe(-ish) password. 8-)
- X
- X
- X*** Instructions for building CrackLib...
- X
- X
- XSTEP 0) Engage your brain.
- X
- XI'm interested in improving the CrackLib software, doing bugfixes,
- X"guessing technique" improvements, and portability enhancements.
- X
- XI'm NOT interested in unhelpful comments like "well, _my_ operating
- Xsystem doesn't come with a dictionary". If it doesn't, either complain
- Xto your vendor, or GO AND GET a dictionary off the net.
- X
- XCrackLib is NOT a TOOL. It is not a complete package. It is not
- Xsomething you can utilise directly.
- X
- XIt is a resource, an aid, something to enhance the functionality of
- Xother software. You need to (either) write OR modify other software to
- Xuse it. If you can't do this, then you shouldn't be wasting your time
- Xwith it.
- X
- XRegarding bugs and portability problems: please try to work them out for
- Xyourself, and then (please) TELL me about them. This will help me
- Ximprove future versions.
- X
- X
- XSTEP 1) Edit the Makefile to set your preferred value of DICTPATH
- X
- XThis it the directory+filename-prefix that your version of CrackLib will
- Xgo hunting for, and it must be visible to all programs on all hosts that
- Xuse CrackLib
- X
- XHence, if you want to use a CrackLib binary on a distributed network,
- Xthese files are probably best placed on an NFS server.
- X
- XNote: You have to specify a FILENAME PREFIX too, eg:
- X
- X DICTPATH=/usr/local/lib/pw_dict
- X
- Xwhich will generate:
- X
- X /usr/local/lib/pw_dict.pwd
- X /usr/local/lib/pw_dict.pwi
- X /usr/local/lib/pw_dict.hwm
- X
- Xwhich are the files that CrackLib needs.
- X
- XThese files are NOT byte-order independent, in fact they are probably
- XARCHITECTURE SPECIFIC, mostly due to speed constraints. If this is a
- Xproblem, I suggest you use:
- X
- X DICTPATH=/usr/local/lib/pw_dict.sun4
- X DICTPATH=/usr/local/lib/pw_dict.i386
- X DICTPATH=/usr/local/lib/pw_dict.cray
- X
- X...etc, and build several sets of files, as appropriate.
- X
- X
- X(Hackers Note: Strictly, only *.pwi and *.hwm should be architecture
- Xdependent; however, if you build two dictionaries on two different
- Xplatforms, you MAY wind up with different *.pwd files too, due to
- Xincompatibilities in the std Unix utilities, or from using different
- XSOURCEDICTs.
- X
- XI may try to work this out in the next release. In the mean time, if
- Xyour *.pwd files are EXACTLY identical (use "cmp" to test), you can
- Xdelete the multiple copies and use softlinks instead.)
- X
- X
- XSTEP 2) Add to the SOURCEDICT variable, any files continaing extra words
- Xthat you wish CrackLib to use. CrackLib merges all of these files
- Xtogether, removes redundant characters, and compresses them. Generally,
- Xthe output file is 40..60% the size of all the input files, combined.
- X
- XNOTE: THE DEFAULT VALUE OF "SOURCEDICT" CONTAINS "/usr/dict/words" -
- Xthis is a file which can be found on many BSD-type Unix systems,
- Xcontaining a list of words, one per line, suitable for use with
- X"cracklib". If you do not have such a file, refer to STEP 0.
- X
- X
- XSTEP 3) do:
- X
- X % make all
- X
- Xthen do:
- X
- X % make install
- X
- Xwhich will build the CrackLib dictionary in $DICTPATH.
- X
- X
- X*** NOTE THIS WELL ***
- X
- XIf you supply massive amounts of text to CrackLib to use a a dictionary,
- Xyou must have enough free space available for use by the "sort" command,
- Xwhen the dictionary is built.
- X
- XSo: If you do not have (say) about 20Mb free in /usr/tmp (or whatever
- Xtemporary area your "sort" command uses), have a look at the
- X"util/mkdict" script.
- X
- XYou can usually tweak the "sort" command to use any large area of disk
- Xyou desire, by use of the "-T" option, and "mkdict" has a hook for this.
- X
- X
- XSTEP 4) Wire a call to "FascistCheck()" into your "passwd" program
- X
- X
- X- Left as an exercise for the reader.
- X
- X
- X*** Example of how to invoke CrackLib
- X
- XInsert a call to the routine FascistCheck, which is defined thusly:
- X
- XNAME
- X FascistCheck - check a potential password for guessability
- X
- X
- XSYNOPSIS
- X
- X char *FascistCheck(char *pw, char *dictpath);
- X
- X
- XDESCRIPTION
- X
- X FascistCheck() takes 2 arguments:
- X
- X pw - a string continaing the users chosen "potential password"
- X
- X dictpath - the full path name + filename prefix of the
- X CrackLib dictionary, specified in the installation Makefile.
- X (If you still haven't sussed, I'm talking about DICTPATH).
- X
- X
- XRETURN VALUE
- X
- X FascistCheck() returns the NULL pointer for a good password,
- X or a pointer to a diagnostic string if it is a bad password.
- X
- X
- XBUGS
- X - it can't catch everything. Just most things.
- X
- X - it calls getpwuid(getuid()) to look up the user,
- X this MAY affect poorly written programs
- X
- X - using more than one pw_dict file, eg:
- X
- X char *msg;
- X if (msg = FascistCheck(pw, "onepath") ||
- X msg = FascistCheck(pw, "anotherpath"))
- X {
- X printf("Bad Password: because %s\n", msg);
- X }
- X
- X ...works, but it's a kludge. AVOID IT IF POSSIBLE.
- X Using just the one dictionary is more efficient, anyway.
- X
- X - PWOpen() routines should cope with having more than 1
- X dictionary open at a time. I'll fix this RSN.
- X
- X
- XWORKED EXAMPLE
- X
- X---- modified extract from BSD distribution - "local_passwd.c" ----
- X
- X#ifndef CRACKLIB_DICTPATH /* if possible, get from the same Makefile as CrackLib */
- X#define CRACKLIB_DICTPATH "/usr/local/lib/pw_dict"
- X#endif /* see examples on how to import DICTPATH into CRACKLIB_DICTPATH */
- X...
- X...
- X...
- X for (buf[0] = '\0', tries = 0;;) {
- X p = getpass("New password:");
- X if (!*p) {
- X (void)printf("Password unchanged.\n");
- X pw_error(NULL, 0, 0);
- X }
- X
- X#ifndef CRACKLIB_DICTPATH
- X if (strlen(p) <= 5 && (uid != 0 || ++tries < 2)) {
- X (void)printf("Please enter a longer password.\n");
- X continue;
- X }
- X for (t = p; *t && islower(*t); ++t);
- X if (!*t && (uid != 0 || ++tries < 2)) {
- X (void)printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
- X continue;
- X }
- X#else
- X {
- X char *msg;
- X if (msg = (char *) FascistCheck(pwbuf, CRACKLIB_DICTPATH)) {
- X printf("Please use a different password.\n");
- X printf("The one you have chosen is unsuitable because %s.\n", msg);
- X continue; /* go round and round until they get it right */
- X }
- X }
- X#endif /* CRACKLIB_DICTPATH */
- X
- X (void)strcpy(buf, p);
- X if (!strcmp(buf, getpass("Retype new password:")))
- X break;
- X (void)printf("Mismatch; try again, EOF to quit.\n");
- X }
- X---- end of extract ----
- END_OF_FILE
- if test 9021 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(1338 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X----------------------------------------------------------
- XREADME 1 Boring docs
- XMANIFEST 1 This file
- XHISTORY 2 Version information
- XLICENCE 1 Licence documentation
- XMakefile 2 Makefile for std distribution
- XPOSTER 2 Cut down blurb for USENET
- Xcracklib 1 Library source code
- Xcracklib/Makefile 2
- Xcracklib/fascist.c 1 Pattern matching + API
- Xcracklib/genrules.pl 2
- Xcracklib/packer.h 2 Boring config file
- Xcracklib/packlib.c 1 DAWG-16 compression library from C5
- Xcracklib/rules.c 1 ...more stuff from Crack 5
- Xcracklib/stringlib.c 2 ...even more stuff from Crack 5
- Xshadow 1 Stubs for use with JFH's "shadow" suite
- Xshadow/README,CL 1
- Xshadow/obscure.c,CL 2 jfh's "obscure" routine with CrackLib
- Xutil 1 support utilities
- Xutil/Makefile 2
- Xutil/mkdict 2 dictionary preprocessor
- Xutil/packer.c 2 dictionary packer
- Xutil/testlib.c 2 password sanity testbed
- Xutil/testnum.c 2 numeric dict-lookup testbed
- Xutil/teststr.c 2 string dict-lookup testbed
- Xutil/unpacker.c 2 dictionary unpacker
- END_OF_FILE
- if test 1338 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'LICENCE' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'LICENCE'\"
- else
- echo shar: Extracting \"'LICENCE'\" \(4851 characters\)
- sed "s/^X//" >'LICENCE' <<'END_OF_FILE'
- X(*
- XThis document is freely plagiarised from the 'Artistic Licence',
- Xdistributed as part of the Perl v4.0 kit by Larry Wall, which is
- Xavailable from most major archive sites
- X*)
- X
- XThis documents purpose is to state the conditions under which these
- XPackages (See definition below) viz: "Crack", the Unix Password Cracker,
- Xand "CrackLib", the Unix Password Checking library, which are held in
- Xcopyright by Alec David Edward Muffett, may be copied, such that the
- Xcopyright holder maintains some semblance of artistic control over the
- Xdevelopment of the packages, while giving the users of the package the
- Xright to use and distribute the Package in a more-or-less customary
- Xfashion, plus the right to make reasonable modifications.
- X
- XSo there.
- X
- X***************************************************************************
- X
- XDefinitions:
- X
- X
- XA "Package" refers to the collection of files distributed by the
- XCopyright Holder, and derivatives of that collection of files created
- Xthrough textual modification, or segments thereof.
- X
- X"Standard Version" refers to such a Package if it has not been modified,
- Xor has been modified in accordance with the wishes of the Copyright
- XHolder.
- X
- X"Copyright Holder" is whoever is named in the copyright or copyrights
- Xfor the package.
- X
- X"You" is you, if you're thinking about copying or distributing this
- XPackage.
- X
- X"Reasonable copying fee" is whatever you can justify on the basis of
- Xmedia cost, duplication charges, time of people involved, and so on.
- X(You will not be required to justify it to the Copyright Holder, but
- Xonly to the computing community at large as a market that must bear the
- Xfee.)
- X
- X"Freely Available" means that no fee is charged for the item itself,
- Xthough there may be fees involved in handling the item. It also means
- Xthat recipients of the item may redistribute it under the same
- Xconditions they received it.
- X
- X
- X1. You may make and give away verbatim copies of the source form of the
- XStandard Version of this Package without restriction, provided that you
- Xduplicate all of the original copyright notices and associated
- Xdisclaimers.
- X
- X2. You may apply bug fixes, portability fixes and other modifications
- Xderived from the Public Domain or from the Copyright Holder. A Package
- Xmodified in such a way shall still be considered the Standard Version.
- X
- X3. You may otherwise modify your copy of this Package in any way,
- Xprovided that you insert a prominent notice in each changed file stating
- Xhow and when AND WHY you changed that file, and provided that you do at
- Xleast ONE of the following:
- X
- Xa) place your modifications in the Public Domain or otherwise make them
- XFreely Available, such as by posting said modifications to Usenet or an
- Xequivalent medium, or placing the modifications on a major archive site
- Xsuch as uunet.uu.net, or by allowing the Copyright Holder to include
- Xyour modifications in the Standard Version of the Package.
- X
- Xb) use the modified Package only within your corporation or organization.
- X
- Xc) rename any non-standard executables so the names do not conflict with
- Xstandard executables, which must also be provided, and provide separate
- Xdocumentation for each non-standard executable that clearly documents
- Xhow it differs from the Standard Version.
- X
- Xd) make other distribution arrangements with the Copyright Holder.
- X
- X4. You may distribute the programs of this Package in object code or
- Xexecutable form, provided that you do at least ONE of the following:
- X
- Xa) distribute a Standard Version of the executables and library files,
- Xtogether with instructions (in the manual page or equivalent) on where
- Xto get the Standard Version.
- X
- Xb) accompany the distribution with the machine-readable source of the
- XPackage with your modifications.
- X
- Xc) accompany any non-standard executables with their corresponding
- XStandard Version executables, giving the non-standard executables
- Xnon-standard names, and clearly documenting the differences in manual
- Xpages (or equivalent), together with instructions on where to get the
- XStandard Version.
- X
- Xd) make other distribution arrangements with the Copyright Holder.
- X
- X5. You may charge a reasonable copying fee for any distribution of this
- XPackage. You may charge any fee you choose for support of this Package.
- XYOU MAY NOT CHARGE A FEE FOR THIS PACKAGE ITSELF. However, you may
- Xdistribute this Package in aggregate with other (possibly commercial)
- Xprograms as part of a larger (possibly commercial) software distribution
- Xprovided that YOU DO NOT ADVERTISE this package as a product of your
- Xown.
- X
- X6. The name of the Copyright Holder may not be used to endorse or
- Xpromote products derived from this software without specific prior
- Xwritten permission.
- X
- X7. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
- XWARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- XMERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- X
- X The End
- END_OF_FILE
- if test 4851 -ne `wc -c <'LICENCE'`; then
- echo shar: \"'LICENCE'\" unpacked with wrong size!
- fi
- # end of 'LICENCE'
- fi
- if test ! -d 'cracklib' ; then
- echo shar: Creating directory \"'cracklib'\"
- mkdir 'cracklib'
- fi
- if test -f 'cracklib/fascist.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cracklib/fascist.c'\"
- else
- echo shar: Extracting \"'cracklib/fascist.c'\" \(8505 characters\)
- sed "s/^X//" >'cracklib/fascist.c' <<'END_OF_FILE'
- X/*
- X * This program is copyright Alec Muffett 1993. The author disclaims all
- X * responsibility or liability with respect to it's usage or its effect
- X * upon hardware or computer systems, and maintains copyright as set out
- X * in the "LICENCE" document which accompanies distributions of Crack v4.0
- X * and upwards.
- X */
- X
- Xstatic char vers_id[] = "fascist.c : v2.3p2 Alec Muffett 18 May 1993";
- X
- X#include "packer.h"
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include <pwd.h>
- X
- X#define ISSKIP(x) (isspace(x) || ispunct(x))
- X
- X#define MINDIFF 5
- X#define MINLEN 6
- X#define MAXSTEP 4
- X
- Xstatic char *r_destructors[] = {
- X ":", /* noop - must do this to test raw word. */
- X
- X "[", /* trimming leading/trailing junk */
- X "]",
- X "[[",
- X "]]",
- X "[[[",
- X "]]]",
- X
- X "/?p@?p", /* purging out punctuation/symbols/junk */
- X "/?s@?s",
- X "/?X@?X",
- X
- X "/$s$s", /* transmogrifying "$" back into "s", etc... */
- X "/4s4a",
- X "/2s2a",
- X "/3s3e",
- X "/0s0o",
- X "/1s1i",
- X "/4s4h",
- X "/1s1l",
- X "/$s$s/1s1l",
- X "/2s2a/3s3e",
- X "/0s0o/4s4h",
- X "/1s1l/4s4a",
- X "/2s2a/4s4h",
- X "/$s$s/3s3e",
- X "/$s$s/0s0o",
- X "/1s1i/4s4a",
- X "/$s$s/2s2a",
- X "/$s$s/4s4a",
- X "/0s0o/1s1l",
- X "/3s3e/4s4h",
- X "/1s1l/4s4h",
- X "/$s$s/4s4h",
- X "/1s1i/4s4h",
- X "/2s2a/4s4a",
- X "/$s$s/1s1i",
- X "/0s0o/1s1i",
- X "/1s1i/2s2a",
- X "/1s1i/3s3e",
- X "/0s0o/4s4a",
- X "/1s1l/3s3e",
- X "/3s3e/4s4a",
- X "/0s0o/2s2a",
- X "/0s0o/3s3e",
- X "/1s1l/2s2a",
- X "/0s0o/1s1l/2s2a",
- X "/0s0o/1s1i/4s4h",
- X "/1s1l/2s2a/4s4a",
- X "/2s2a/3s3e/4s4a",
- X "/0s0o/1s1i/2s2a",
- X "/1s1i/2s2a/3s3e",
- X "/0s0o/1s1l/4s4a",
- X "/1s1l/2s2a/4s4h",
- X "/$s$s/0s0o/1s1l",
- X "/$s$s/0s0o/2s2a",
- X "/0s0o/1s1i/3s3e",
- X "/$s$s/0s0o/3s3e",
- X "/1s1i/2s2a/4s4a",
- X "/$s$s/0s0o/4s4a",
- X "/$s$s/0s0o/4s4h",
- X "/0s0o/1s1l/4s4h",
- X "/1s1i/2s2a/4s4h",
- X "/0s0o/1s1l/3s3e",
- X "/$s$s/0s0o/1s1i",
- X "/0s0o/1s1i/4s4a",
- X "/2s2a/3s3e/4s4h",
- X "/1s1l/2s2a/3s3e",
- X "/$s$s/0s0o/1s1l/3s3e",
- X "/0s0o/1s1l/2s2a/4s4a",
- X "/0s0o/1s1i/2s2a/3s3e",
- X "/$s$s/0s0o/1s1i/4s4a",
- X "/$s$s/0s0o/1s1i/3s3e",
- X "/$s$s/0s0o/1s1l/4s4a",
- X "/0s0o/1s1l/2s2a/3s3e",
- X "/$s$s/0s0o/1s1i/2s2a",
- X "/1s1l/2s2a/3s3e/4s4a",
- X "/$s$s/0s0o/1s1l/2s2a",
- X "/$s$s/0s0o/1s1i/4s4h",
- X "/1s1i/2s2a/3s3e/4s4a",
- X "/0s0o/1s1i/2s2a/4s4a",
- X "/0s0o/1s1l/2s2a/4s4h",
- X "/1s1i/2s2a/3s3e/4s4h",
- X "/1s1l/2s2a/3s3e/4s4h",
- X "/0s0o/1s1i/2s2a/4s4h",
- X "/$s$s/0s0o/1s1l/4s4h",
- X "/$s$s/0s0o/1s1i/2s2a/4s4a",
- X "/$s$s/0s0o/1s1l/2s2a/4s4h",
- X "/$s$s/0s0o/1s1i/2s2a/4s4h",
- X "/0s0o/1s1l/2s2a/3s3e/4s4a",
- X "/$s$s/0s0o/1s1l/2s2a/4s4a",
- X "/0s0o/1s1i/2s2a/3s3e/4s4a",
- X "/0s0o/1s1i/2s2a/3s3e/4s4h",
- X "/$s$s/0s0o/1s1l/2s2a/3s3e",
- X "/0s0o/1s1l/2s2a/3s3e/4s4h",
- X "/$s$s/0s0o/1s1i/2s2a/3s3e",
- X "/$s$s/0s0o/1s1l/2s2a/3s3e/4s4h",
- X "/$s$s/0s0o/1s1l/2s2a/3s3e/4s4a",
- X "/$s$s/0s0o/1s1i/2s2a/3s3e/4s4a",
- X "/$s$s/0s0o/1s1i/2s2a/3s3e/4s4h",
- X (char *) 0
- X};
- X
- Xstatic char *r_constructors[] = {
- X ":",
- X "r",
- X "d",
- X "f",
- X "dr",
- X "fr",
- X "rf",
- X (char *) 0
- X};
- X
- Xint
- XGTry(rawtext, password)
- X register char *rawtext;
- X register char *password;
- X{
- X register int i;
- X register char *mp;
- X int len;
- X
- X /* use destructors to turn password into rawtext */
- X /* note use of Reverse() to save duplicating all rules */
- X
- X len = strlen(password);
- X
- X for (i = 0; r_destructors[i]; i++)
- X {
- X if (!(mp = Mangle(password, r_destructors[i])))
- X {
- X continue;
- X }
- X
- X#ifdef DEBUG
- X printf("d1->\t%s vs %s\n", mp, rawtext);
- X#endif
- X if (!strncmp(mp, rawtext, len))
- X {
- X return (1);
- X }
- X#ifdef DEBUG
- X printf("d2->\tr(%s) vs %s\n", mp, rawtext);
- X#endif
- X if (!strncmp(Reverse(mp), rawtext, len))
- X {
- X return (1);
- X }
- X }
- X
- X /* use constructors to turn rawtext into password */
- X
- X for (i = 0; r_constructors[i]; i++)
- X {
- X if (!(mp = Mangle(rawtext, r_constructors[i])))
- X {
- X continue;
- X }
- X#ifdef DEBUG
- X printf("c->\t%s vs %s\n", mp, password);
- X#endif
- X if (!strncmp(mp, password, len))
- X {
- X return (1);
- X }
- X }
- X
- X return (0);
- X}
- X
- Xchar *
- XFascistGecos(password, uid)
- X char *password;
- X int uid;
- X{
- X int i;
- X int j;
- X int wc;
- X struct passwd *pwp;
- X char gbuffer[STRINGSIZE];
- X char *uwords[STRINGSIZE];
- X char buffer[STRINGSIZE];
- X register char *ptr =
- X "\101\154\145\143\127\141\163\110\145\162\145";
- X
- X if (!(pwp = getpwuid(uid)))
- X {
- X return ("you are not registered in the password file");
- X }
- X
- X if (GTry(pwp->pw_name, password))
- X {
- X return ("it is based on your username");
- X }
- X
- X strcpy(gbuffer, Lowercase(pwp->pw_gecos));
- X
- X wc = 0;
- X ptr = gbuffer;
- X
- X while (*ptr)
- X {
- X while (*ptr && ISSKIP(*ptr))
- X {
- X ptr++;
- X }
- X
- X if (ptr != gbuffer)
- X {
- X ptr[-1] = '\0';
- X }
- X
- X uwords[wc++] = ptr;
- X
- X if (wc == STRINGSIZE)
- X {
- X uwords[--wc] = (char *) 0; /* to hell with it */
- X break;
- X } else
- X {
- X uwords[wc] = (char *) 0;
- X }
- X
- X while (*ptr && !ISSKIP(*ptr))
- X {
- X ptr++;
- X }
- X
- X if (*ptr)
- X {
- X *(ptr++) = '\0';
- X }
- X }
- X#ifdef DEBUG
- X for (i = 0; uwords[i]; i++)
- X {
- X printf("u:\t%s\n", uwords[i]);
- X }
- X#endif
- X for (i = 0; uwords[i]; i++)
- X {
- X if (GTry(uwords[i], password))
- X {
- X return ("it is based upon your password entry");
- X }
- X }
- X
- X for (j = 1; uwords[j]; j++)
- X {
- X for (i = 0; i < j; i++)
- X {
- X strcpy(buffer, uwords[i]);
- X strcat(buffer, uwords[j]);
- X if (GTry(buffer, password))
- X {
- X return ("it is derived from your password entry");
- X }
- X
- X strcpy(buffer, uwords[j]);
- X strcat(buffer, uwords[i]);
- X if (GTry(buffer, password))
- X {
- X return ("it's derived from your password entry");
- X }
- X
- X buffer[0] = uwords[i][0];
- X buffer[1] = '\0';
- X strcat(buffer, uwords[j]);
- X if (GTry(buffer, password))
- X {
- X return ("it is derivable from your password entry");
- X }
- X
- X buffer[0] = uwords[j][0];
- X buffer[1] = '\0';
- X strcat(buffer, uwords[i]);
- X if (GTry(buffer, password))
- X {
- X return ("it's derivable from your password entry");
- X }
- X }
- X }
- X
- X return ((char *) 0);
- X}
- X
- Xchar *
- XFascistLook(pwp, instring)
- X PWDICT *pwp;
- X char *instring;
- X{
- X register int i;
- X register char *ptr;
- X char junk[STRINGSIZE];
- X register char *jptr;
- X char rpassword[STRINGSIZE];
- X register char *password;
- X int32 notfound;
- X
- X notfound = PW_WORDS(pwp);
- X password = rpassword;
- X
- X strncpy(password, instring, STRINGSIZE);
- X
- X password[STRINGSIZE - 1] = '\0';
- X
- X if (strlen(password) < 4)
- X {
- X return ("it's WAY too short");
- X }
- X
- X if (strlen(password) < MINLEN)
- X {
- X return ("it is too short");
- X }
- X
- X jptr = junk;
- X *jptr = '\0';
- X
- X for (i = 0; i < STRINGSIZE && password[i]; i++)
- X {
- X if (!strchr(junk, password[i]))
- X {
- X *(jptr++) = password[i];
- X *jptr = '\0';
- X }
- X }
- X
- X if (strlen(junk) < MINDIFF)
- X {
- X return ("it does not contain enough DIFFERENT characters");
- X }
- X
- X strcpy(password, Lowercase(password));
- X
- X Trim(password);
- X
- X while (*password && isspace(*password))
- X {
- X password++;
- X }
- X
- X if (!*password)
- X {
- X return ("it is all whitespace");
- X }
- X
- X i = 0;
- X ptr = password;
- X while (ptr[0] && ptr[1])
- X {
- X if ((ptr[1] == (ptr[0] + 1)) || (ptr[1] == (ptr[0] - 1)))
- X {
- X i++;
- X }
- X ptr++;
- X }
- X
- X if (i > MAXSTEP)
- X {
- X return ("it is too simplistic/systematic");
- X }
- X
- X if (PMatch("aadddddda", password)) /* smirk */
- X {
- X return ("it looks like a National Insurance number.");
- X }
- X
- X if (ptr = FascistGecos(password, getuid()))
- X {
- X return (ptr);
- X }
- X
- X for (i = 0; r_destructors[i]; i++)
- X {
- X char *a;
- X if (!(a = Mangle(password, r_destructors[i])))
- X {
- X continue;
- X }
- X if (FindPW(pwp, a) != notfound)
- X {
- X return ("it is based on a dictionary word");
- X }
- X }
- X
- X strcpy(password, Reverse(password));
- X
- X for (i = 0; r_destructors[i]; i++)
- X {
- X char *a;
- X
- X if (!(a = Mangle(password, r_destructors[i])))
- X {
- X continue;
- X }
- X
- X if (FindPW(pwp, a) != notfound)
- X {
- X return ("it is based on a (reversed) dictionary word");
- X }
- X }
- X
- X return ((char *) 0);
- X}
- X
- Xchar *
- XFascistCheck(password, path)
- X char *password;
- X char *path;
- X{
- X static PWDICT *pwp;
- X static char lastpath[STRINGSIZE];
- X
- X if (pwp && strncmp(lastpath, path, STRINGSIZE))
- X {
- X PWClose(pwp);
- X pwp = (PWDICT *)0;
- X }
- X
- X if (!pwp)
- X {
- X if (!(pwp = PWOpen(path, "r")))
- X {
- X perror("PWOpen");
- X exit(-1);
- X }
- X strncpy(lastpath, path, STRINGSIZE);
- X }
- X
- X return (FascistLook(pwp, password));
- X}
- END_OF_FILE
- if test 8505 -ne `wc -c <'cracklib/fascist.c'`; then
- echo shar: \"'cracklib/fascist.c'\" unpacked with wrong size!
- fi
- # end of 'cracklib/fascist.c'
- fi
- if test -f 'cracklib/packlib.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cracklib/packlib.c'\"
- else
- echo shar: Extracting \"'cracklib/packlib.c'\" \(6603 characters\)
- sed "s/^X//" >'cracklib/packlib.c' <<'END_OF_FILE'
- X/*
- X * This program is copyright Alec Muffett 1993. The author disclaims all
- X * responsibility or liability with respect to it's usage or its effect
- X * upon hardware or computer systems, and maintains copyright as set out
- X * in the "LICENCE" document which accompanies distributions of Crack v4.0
- X * and upwards.
- X */
- X
- X#include "packer.h"
- X
- Xstatic char vers_id[] = "packlib.c : v2.3p2 Alec Muffett 18 May 1993";
- X
- XPWDICT *
- XPWOpen(prefix, mode)
- X char *prefix;
- X char *mode;
- X{
- X int32 i;
- X static PWDICT pdesc;
- X char iname[STRINGSIZE];
- X char dname[STRINGSIZE];
- X char wname[STRINGSIZE];
- X char buffer[STRINGSIZE];
- X FILE *dfp;
- X FILE *ifp;
- X FILE *wfp;
- X
- X if (pdesc.header.pih_magic == PIH_MAGIC)
- X {
- X fprintf(stderr, "%s: another dictionary already open\n", prefix);
- X return ((PWDICT *) 0);
- X }
- X
- X memset(&pdesc, '\0', sizeof(pdesc));
- X
- X sprintf(iname, "%s.pwi", prefix);
- X sprintf(dname, "%s.pwd", prefix);
- X sprintf(wname, "%s.hwm", prefix);
- X
- X if (!(pdesc.dfp = fopen(dname, mode)))
- X {
- X perror(dname);
- X return ((PWDICT *) 0);
- X }
- X
- X if (!(pdesc.ifp = fopen(iname, mode)))
- X {
- X fclose(pdesc.dfp);
- X perror(iname);
- X return ((PWDICT *) 0);
- X }
- X
- X if (pdesc.wfp = fopen(wname, mode))
- X {
- X pdesc.flags |= PFOR_USEHWMS;
- X }
- X
- X ifp = pdesc.ifp;
- X dfp = pdesc.dfp;
- X wfp = pdesc.wfp;
- X
- X if (mode[0] == 'w')
- X {
- X pdesc.flags |= PFOR_WRITE;
- X pdesc.header.pih_magic = PIH_MAGIC;
- X pdesc.header.pih_blocklen = NUMWORDS;
- X pdesc.header.pih_numwords = 0;
- X
- X fwrite((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp);
- X } else
- X {
- X pdesc.flags &= ~PFOR_WRITE;
- X
- X if (!fread((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp))
- X {
- X fprintf(stderr, "%s: error reading header\n", prefix);
- X
- X pdesc.header.pih_magic = 0;
- X fclose(ifp);
- X fclose(dfp);
- X return ((PWDICT *) 0);
- X }
- X
- X if (pdesc.header.pih_magic != PIH_MAGIC)
- X {
- X fprintf(stderr, "%s: magic mismatch\n", prefix);
- X
- X pdesc.header.pih_magic = 0;
- X fclose(ifp);
- X fclose(dfp);
- X return ((PWDICT *) 0);
- X }
- X
- X if (pdesc.header.pih_blocklen != NUMWORDS)
- X {
- X fprintf(stderr, "%s: size mismatch\n", prefix);
- X
- X pdesc.header.pih_magic = 0;
- X fclose(ifp);
- X fclose(dfp);
- X return ((PWDICT *) 0);
- X }
- X
- X if (pdesc.flags & PFOR_USEHWMS)
- X {
- X if (fread(pdesc.hwms, 1, sizeof(pdesc.hwms), wfp) != sizeof(pdesc.hwms))
- X {
- X pdesc.flags &= ~PFOR_USEHWMS;
- X }
- X }
- X }
- X
- X return (&pdesc);
- X}
- X
- Xint
- XPWClose(pwp)
- X PWDICT *pwp;
- X{
- X if (pwp->header.pih_magic != PIH_MAGIC)
- X {
- X fprintf(stderr, "PWClose: close magic mismatch\n");
- X return (-1);
- X }
- X
- X if (pwp->flags & PFOR_WRITE)
- X {
- X pwp->flags |= PFOR_FLUSH;
- X PutPW(pwp, (char *) 0); /* flush last index if necess */
- X
- X if (fseek(pwp->ifp, 0L, 0))
- X {
- X fprintf(stderr, "index magic fseek failed\n");
- X return (-1);
- X }
- X
- X if (!fwrite((char *) &pwp->header, sizeof(pwp->header), 1, pwp->ifp))
- X {
- X fprintf(stderr, "index magic fwrite failed\n");
- X return (-1);
- X }
- X
- X if (pwp->flags & PFOR_USEHWMS)
- X {
- X int i;
- X for (i=1; i<=0xff; i++)
- X {
- X if (!pwp->hwms[i])
- X {
- X pwp->hwms[i] = pwp->hwms[i-1];
- X }
- X#ifdef DEBUG
- X printf("hwm[%02x] = %d\n", i, pwp->hwms[i]);
- X#endif
- X }
- X fwrite(pwp->hwms, 1, sizeof(pwp->hwms), pwp->wfp);
- X }
- X }
- X
- X fclose(pwp->ifp);
- X fclose(pwp->dfp);
- X
- X pwp->header.pih_magic = 0;
- X
- X return (0);
- X}
- X
- Xint
- XPutPW(pwp, string)
- X PWDICT *pwp;
- X char *string;
- X{
- X if (!(pwp->flags & PFOR_WRITE))
- X {
- X return (-1);
- X }
- X
- X if (string)
- X {
- X strncpy(pwp->data[pwp->count], string, MAXWORDLEN);
- X pwp->data[pwp->count][MAXWORDLEN - 1] = '\0';
- X
- X pwp->hwms[string[0] & 0xff]= pwp->header.pih_numwords;
- X
- X ++(pwp->count);
- X ++(pwp->header.pih_numwords);
- X
- X } else if (!(pwp->flags & PFOR_FLUSH))
- X {
- X return (-1);
- X }
- X
- X if ((pwp->flags & PFOR_FLUSH) || !(pwp->count % NUMWORDS))
- X {
- X int i;
- X int32 datum;
- X register char *ostr;
- X
- X datum = (int32) ftell(pwp->dfp);
- X
- X fwrite((char *) &datum, sizeof(datum), 1, pwp->ifp);
- X
- X fputs(pwp->data[0], pwp->dfp);
- X putc(0, pwp->dfp);
- X
- X ostr = pwp->data[0];
- X
- X for (i = 1; i < NUMWORDS; i++)
- X {
- X register int j;
- X register char *nstr;
- X nstr = pwp->data[i];
- X
- X if (nstr[0])
- X {
- X for (j = 0; ostr[j] && nstr[j] && (ostr[j] == nstr[j]); j++);
- X putc(j & 0xff, pwp->dfp);
- X fputs(nstr + j, pwp->dfp);
- X }
- X putc(0, pwp->dfp);
- X
- X ostr = nstr;
- X }
- X
- X memset(pwp->data, '\0', sizeof(pwp->data));
- X pwp->count = 0;
- X }
- X return (0);
- X}
- X
- Xchar *
- XGetPW(pwp, number)
- X PWDICT *pwp;
- X int32 number;
- X{
- X int32 datum;
- X register int i;
- X register char *ostr;
- X register char *nstr;
- X register char *bptr;
- X char buffer[NUMWORDS * MAXWORDLEN];
- X static char data[NUMWORDS][MAXWORDLEN];
- X static int32 prevblock = 0xffffffff;
- X int32 thisblock;
- X
- X thisblock = number / NUMWORDS;
- X
- X if (prevblock == thisblock)
- X {
- X return (data[number % NUMWORDS]);
- X }
- X
- X if (fseek(pwp->ifp, sizeof(struct pi_header) + (thisblock * sizeof(int32)), 0))
- X {
- X perror("(index fseek failed)");
- X return ((char *) 0);
- X }
- X
- X if (!fread((char *) &datum, sizeof(datum), 1, pwp->ifp))
- X {
- X perror("(index fread failed)");
- X return ((char *) 0);
- X }
- X
- X if (fseek(pwp->dfp, datum, 0))
- X {
- X perror("(data fseek failed)");
- X return ((char *) 0);
- X }
- X
- X if (!fread(buffer, 1, sizeof(buffer), pwp->dfp))
- X {
- X perror("(data fread failed)");
- X return ((char *) 0);
- X }
- X
- X prevblock = thisblock;
- X
- X bptr = buffer;
- X
- X for (ostr = data[0]; *(ostr++) = *(bptr++); /* nothing */ );
- X
- X ostr = data[0];
- X
- X for (i = 1; i < NUMWORDS; i++)
- X {
- X nstr = data[i];
- X strcpy(nstr, ostr);
- X
- X ostr = nstr + *(bptr++);
- X while (*(ostr++) = *(bptr++));
- X
- X ostr = nstr;
- X }
- X
- X return (data[number % NUMWORDS]);
- X}
- X
- Xint32
- XFindPW(pwp, string)
- X PWDICT *pwp;
- X char *string;
- X{
- X register int32 lwm;
- X register int32 hwm;
- X register int32 middle;
- X register char *this;
- X int idx;
- X
- X if (pwp->flags & PFOR_USEHWMS)
- X {
- X idx = string[0] & 0xff;
- X lwm = idx ? pwp->hwms[idx - 1] : 0;
- X hwm = pwp->hwms[idx];
- X } else
- X {
- X lwm = 0;
- X hwm = PW_WORDS(pwp) - 1;
- X }
- X
- X#ifdef DEBUG
- X printf("---- %lu, %lu ----\n", lwm, hwm);
- X#endif
- X
- X for (;;)
- X {
- X int cmp;
- X
- X#ifdef DEBUG
- X printf("%lu, %lu\n", lwm, hwm);
- X#endif
- X
- X middle = lwm + ((hwm - lwm + 1) / 2);
- X
- X if (middle == hwm)
- X {
- X break;
- X }
- X
- X this = GetPW(pwp, middle);
- X cmp = strcmp(string, this); /* INLINE ? */
- X
- X if (cmp < 0)
- X {
- X hwm = middle;
- X } else if (cmp > 0)
- X {
- X lwm = middle;
- X } else
- X {
- X return (middle);
- X }
- X }
- X
- X return (PW_WORDS(pwp));
- X}
- END_OF_FILE
- if test 6603 -ne `wc -c <'cracklib/packlib.c'`; then
- echo shar: \"'cracklib/packlib.c'\" unpacked with wrong size!
- fi
- # end of 'cracklib/packlib.c'
- fi
- if test -f 'cracklib/rules.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'cracklib/rules.c'\"
- else
- echo shar: Extracting \"'cracklib/rules.c'\" \(15448 characters\)
- sed "s/^X//" >'cracklib/rules.c' <<'END_OF_FILE'
- X/*
- X * This program is copyright Alec Muffett 1993. The author disclaims all
- X * responsibility or liability with respect to it's usage or its effect
- X * upon hardware or computer systems, and maintains copyright as set out
- X * in the "LICENCE" document which accompanies distributions of Crack v4.0
- X * and upwards.
- X */
- X
- Xstatic char vers_id[] = "rules.c : v5.0p3 Alec Muffett 20 May 1993";
- X
- X#ifndef IN_CRACKLIB
- X
- X#include "crack.h"
- X
- X#else
- X
- X#include "packer.h"
- X
- Xstatic void
- XDebug(val, a, b, c, d, e, f, g)
- X int val;
- X char *a, *b, *c, *d, *e, *f, *g;
- X{
- X fprintf(stderr, a, b, c, d, e, f);
- X}
- X
- X#endif
- X
- X#define RULE_NOOP ':'
- X#define RULE_PREPEND '^'
- X#define RULE_APPEND '$'
- X#define RULE_REVERSE 'r'
- X#define RULE_UPPERCASE 'u'
- X#define RULE_LOWERCASE 'l'
- X#define RULE_PLURALISE 'p'
- X#define RULE_CAPITALISE 'c'
- X#define RULE_DUPLICATE 'd'
- X#define RULE_REFLECT 'f'
- X#define RULE_SUBSTITUTE 's'
- X#define RULE_MATCH '/'
- X#define RULE_NOT '!'
- X#define RULE_LT '<'
- X#define RULE_GT '>'
- X#define RULE_EXTRACT 'x'
- X#define RULE_OVERSTRIKE 'o'
- X#define RULE_INSERT 'i'
- X#define RULE_EQUALS '='
- X#define RULE_PURGE '@'
- X#define RULE_CLASS '?' /* class rule? socialist ethic in cracker? */
- X
- X#define RULE_DFIRST '['
- X#define RULE_DLAST ']'
- X#define RULE_MFIRST '('
- X#define RULE_MLAST ')'
- X
- Xint
- XSuffix(myword, suffix)
- X char *myword;
- X char *suffix;
- X{
- X register int i;
- X register int j;
- X i = strlen(myword);
- X j = strlen(suffix);
- X
- X if (i > j)
- X {
- X return (STRCMP((myword + i - j), suffix));
- X } else
- X {
- X return (-1);
- X }
- X}
- X
- Xchar *
- XReverse(str) /* return a pointer to a reversal */
- X register char *str;
- X{
- X register int i;
- X register int j;
- X static char area[STRINGSIZE];
- X j = i = strlen(str);
- X while (*str)
- X {
- X area[--i] = *str++;
- X }
- X area[j] = '\0';
- X return (area);
- X}
- X
- Xchar *
- XUppercase(str) /* return a pointer to an uppercase */
- X register char *str;
- X{
- X register char *ptr;
- X static char area[STRINGSIZE];
- X ptr = area;
- X while (*str)
- X {
- X *(ptr++) = CRACK_TOUPPER(*str);
- X str++;
- X }
- X *ptr = '\0';
- X
- X return (area);
- X}
- X
- Xchar *
- XLowercase(str) /* return a pointer to an lowercase */
- X register char *str;
- X{
- X register char *ptr;
- X static char area[STRINGSIZE];
- X ptr = area;
- X while (*str)
- X {
- X *(ptr++) = CRACK_TOLOWER(*str);
- X str++;
- X }
- X *ptr = '\0';
- X
- X return (area);
- X}
- X
- Xchar *
- XCapitalise(str) /* return a pointer to an capitalised */
- X register char *str;
- X{
- X register char *ptr;
- X static char area[STRINGSIZE];
- X ptr = area;
- X
- X while (*str)
- X {
- X *(ptr++) = CRACK_TOLOWER(*str);
- X str++;
- X }
- X
- X *ptr = '\0';
- X area[0] = CRACK_TOUPPER(area[0]);
- X return (area);
- X}
- X
- Xchar *
- XPluralise(string) /* returns a pointer to a plural */
- X register char *string;
- X{
- X register int length;
- X static char area[STRINGSIZE];
- X length = strlen(string);
- X strcpy(area, string);
- X
- X if (!Suffix(string, "ch") ||
- X !Suffix(string, "ex") ||
- X !Suffix(string, "ix") ||
- X !Suffix(string, "sh") ||
- X !Suffix(string, "ss"))
- X {
- X /* bench -> benches */
- X strcat(area, "es");
- X } else if (length > 2 && string[length - 1] == 'y')
- X {
- X if (strchr("aeiou", string[length - 2]))
- X {
- X /* alloy -> alloys */
- X strcat(area, "s");
- X } else
- X {
- X /* gully -> gullies */
- X strcpy(area + length - 1, "ies");
- X }
- X } else if (string[length - 1] == 's')
- X {
- X /* bias -> biases */
- X strcat(area, "es");
- X } else
- X {
- X /* catchall */
- X strcat(area, "s");
- X }
- X
- X return (area);
- X}
- X
- Xchar *
- XSubstitute(string, old, new) /* returns pointer to a swapped about copy */
- X register char *string;
- X register char old;
- X register char new;
- X{
- X register char *ptr;
- X static char area[STRINGSIZE];
- X ptr = area;
- X while (*string)
- X {
- X *(ptr++) = (*string == old ? new : *string);
- X string++;
- X }
- X *ptr = '\0';
- X return (area);
- X}
- X
- Xchar *
- XPurge(string, target) /* returns pointer to a purged copy */
- X register char *string;
- X register char target;
- X{
- X register char *ptr;
- X static char area[STRINGSIZE];
- X ptr = area;
- X while (*string)
- X {
- X if (*string != target)
- X {
- X *(ptr++) = *string;
- X }
- X string++;
- X }
- X *ptr = '\0';
- X return (area);
- X}
- X/* -------- CHARACTER CLASSES START HERE -------- */
- X
- X/*
- X * this function takes two inputs, a class identifier and a character, and
- X * returns non-null if the given character is a member of the class, based
- X * upon restrictions set out below
- X */
- X
- Xint
- XMatchClass(class, input)
- X register char class;
- X register char input;
- X{
- X register char c;
- X register int retval;
- X retval = 0;
- X
- X switch (class)
- X {
- X /* ESCAPE */
- X
- X case '?': /* ?? -> ? */
- X if (input == '?')
- X {
- X retval = 1;
- X }
- X break;
- X
- X /* ILLOGICAL GROUPINGS (ie: not in ctype.h) */
- X
- X case 'V':
- X case 'v': /* vowels */
- X c = CRACK_TOLOWER(input);
- X if (strchr("aeiou", c))
- X {
- X retval = 1;
- X }
- X break;
- X
- X case 'C':
- X case 'c': /* consonants */
- X c = CRACK_TOLOWER(input);
- X if (strchr("bcdfghjklmnpqrstvwxyz", c))
- X {
- X retval = 1;
- X }
- X break;
- X
- X case 'W':
- X case 'w': /* whitespace */
- X if (strchr("\t ", input))
- X {
- X retval = 1;
- X }
- X break;
- X
- X case 'P':
- X case 'p': /* punctuation */
- X if (strchr(".`,:;'!?\"", input))
- X {
- X retval = 1;
- X }
- X break;
- X
- X case 'S':
- X case 's': /* symbols */
- X if (strchr("$%%^&*()-_+=|\\[]{}#@/~", input))
- X {
- X retval = 1;
- X }
- X break;
- X
- X /* LOGICAL GROUPINGS */
- X
- X case 'L':
- X case 'l': /* lowercase */
- X if (islower(input))
- X {
- X retval = 1;
- X }
- X break;
- X
- X case 'U':
- X case 'u': /* uppercase */
- X if (isupper(input))
- X {
- X retval = 1;
- X }
- X break;
- X
- X case 'A':
- X case 'a': /* alphabetic */
- X if (isalpha(input))
- X {
- X retval = 1;
- X }
- X break;
- X
- X case 'X':
- X case 'x': /* alphanumeric */
- X if (isalnum(input))
- X {
- X retval = 1;
- X }
- X break;
- X
- X case 'D':
- X case 'd': /* digits */
- X if (isdigit(input))
- X {
- X retval = 1;
- X }
- X break;
- X
- X default:
- X Debug(1, "MatchClass: unknown class %c\n", class);
- X return (0);
- X break;
- X }
- X
- X if (isupper(class))
- X {
- X return (!retval);
- X }
- X return (retval);
- X}
- X
- Xchar *
- XPolyStrchr(string, class)
- X register char *string;
- X register char class;
- X{
- X while (*string)
- X {
- X if (MatchClass(class, *string))
- X {
- X return (string);
- X }
- X string++;
- X }
- X return ((char *) 0);
- X}
- X
- Xchar *
- XPolySubst(string, class, new) /* returns pointer to a swapped about copy */
- X register char *string;
- X register char class;
- X register char new;
- X{
- X register char *ptr;
- X static char area[STRINGSIZE];
- X ptr = area;
- X while (*string)
- X {
- X *(ptr++) = (MatchClass(class, *string) ? new : *string);
- X string++;
- X }
- X *ptr = '\0';
- X return (area);
- X}
- X
- Xchar *
- XPolyPurge(string, class) /* returns pointer to a purged copy */
- X register char *string;
- X register char class;
- X{
- X register char *ptr;
- X static char area[STRINGSIZE];
- X ptr = area;
- X while (*string)
- X {
- X if (!MatchClass(class, *string))
- X {
- X *(ptr++) = *string;
- X }
- X string++;
- X }
- X *ptr = '\0';
- X return (area);
- X}
- X/* -------- BACK TO NORMALITY -------- */
- X
- Xint
- XChar2Int(character)
- X char character;
- X{
- X if (isdigit(character))
- X {
- X return (character - '0');
- X } else if (islower(character))
- X {
- X return (character - 'a' + 10);
- X } else if (isupper(character))
- X {
- X return (character - 'A' + 10);
- X }
- X return (-1);
- X}
- X
- Xchar *
- XMangle(input, control) /* returns a pointer to a controlled Mangle */
- X char *input;
- X char *control;
- X{
- X int limit;
- X register char *ptr;
- X static char area[STRINGSIZE];
- X char area2[STRINGSIZE];
- X area[0] = '\0';
- X strcpy(area, input);
- X
- X for (ptr = control; *ptr; ptr++)
- X {
- X switch (*ptr)
- X {
- X case RULE_NOOP:
- X break;
- X case RULE_REVERSE:
- X strcpy(area, Reverse(area));
- X break;
- X case RULE_UPPERCASE:
- X strcpy(area, Uppercase(area));
- X break;
- X case RULE_LOWERCASE:
- X strcpy(area, Lowercase(area));
- X break;
- X case RULE_CAPITALISE:
- X strcpy(area, Capitalise(area));
- X break;
- X case RULE_PLURALISE:
- X strcpy(area, Pluralise(area));
- X break;
- X case RULE_REFLECT:
- X strcat(area, Reverse(area));
- X break;
- X case RULE_DUPLICATE:
- X strcpy(area2, area);
- X strcat(area, area2);
- X break;
- X case RULE_GT:
- X if (!ptr[1])
- X {
- X Debug(1, "Mangle: '>' missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X limit = Char2Int(*(++ptr));
- X if (limit < 0)
- X {
- X Debug(1, "Mangle: '>' weird argument in '%s'\n", control);
- X return ((char *) 0);
- X }
- X if (strlen(area) <= limit)
- X {
- X return ((char *) 0);
- X }
- X }
- X break;
- X case RULE_LT:
- X if (!ptr[1])
- X {
- X Debug(1, "Mangle: '<' missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X limit = Char2Int(*(++ptr));
- X if (limit < 0)
- X {
- X Debug(1, "Mangle: '<' weird argument in '%s'\n", control);
- X return ((char *) 0);
- X }
- X if (strlen(area) >= limit)
- X {
- X return ((char *) 0);
- X }
- X }
- X break;
- X case RULE_PREPEND:
- X if (!ptr[1])
- X {
- X Debug(1, "Mangle: prepend missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X area2[0] = *(++ptr);
- X strcpy(area2 + 1, area);
- X strcpy(area, area2);
- X }
- X break;
- X case RULE_APPEND:
- X if (!ptr[1])
- X {
- X Debug(1, "Mangle: append missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X register char *string;
- X string = area;
- X while (*(string++));
- X string[-1] = *(++ptr);
- X *string = '\0';
- X }
- X break;
- X case RULE_EXTRACT:
- X if (!ptr[1] || !ptr[2])
- X {
- X Debug(1, "Mangle: extract missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X register int i;
- X int start;
- X int length;
- X start = Char2Int(*(++ptr));
- X length = Char2Int(*(++ptr));
- X if (start < 0 || length < 0)
- X {
- X Debug(1, "Mangle: extract: weird argument in '%s'\n", control);
- X return ((char *) 0);
- X }
- X strcpy(area2, area);
- X for (i = 0; length-- && area2[start + i]; i++)
- X {
- X area[i] = area2[start + i];
- X }
- X /* cant use strncpy() - no trailing NUL */
- X area[i] = '\0';
- X }
- X break;
- X case RULE_OVERSTRIKE:
- X if (!ptr[1] || !ptr[2])
- X {
- X Debug(1, "Mangle: overstrike missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X register int i;
- X i = Char2Int(*(++ptr));
- X if (i < 0)
- X {
- X Debug(1, "Mangle: overstrike weird argument in '%s'\n",
- X control);
- X return ((char *) 0);
- X } else
- X {
- X ++ptr;
- X if (area[i])
- X {
- X area[i] = *ptr;
- X }
- X }
- X }
- X break;
- X case RULE_INSERT:
- X if (!ptr[1] || !ptr[2])
- X {
- X Debug(1, "Mangle: insert missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X register int i;
- X register char *p1;
- X register char *p2;
- X i = Char2Int(*(++ptr));
- X if (i < 0)
- X {
- X Debug(1, "Mangle: insert weird argument in '%s'\n",
- X control);
- X return ((char *) 0);
- X }
- X p1 = area;
- X p2 = area2;
- X while (i && *p1)
- X {
- X i--;
- X *(p2++) = *(p1++);
- X }
- X *(p2++) = *(++ptr);
- X strcpy(p2, p1);
- X strcpy(area, area2);
- X }
- X break;
- X /* THE FOLLOWING RULES REQUIRE CLASS MATCHING */
- X
- X case RULE_PURGE: /* @x or @?c */
- X if (!ptr[1] || (ptr[1] == RULE_CLASS && !ptr[2]))
- X {
- X Debug(1, "Mangle: delete missing arguments in '%s'\n", control);
- X return ((char *) 0);
- X } else if (ptr[1] != RULE_CLASS)
- X {
- X strcpy(area, Purge(area, *(++ptr)));
- X } else
- X {
- X strcpy(area, PolyPurge(area, ptr[2]));
- X ptr += 2;
- X }
- X break;
- X case RULE_SUBSTITUTE: /* sxy || s?cy */
- X if (!ptr[1] || !ptr[2] || (ptr[1] == RULE_CLASS && !ptr[3]))
- X {
- X Debug(1, "Mangle: subst missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else if (ptr[1] != RULE_CLASS)
- X {
- X strcpy(area, Substitute(area, ptr[1], ptr[2]));
- X ptr += 2;
- X } else
- X {
- X strcpy(area, PolySubst(area, ptr[2], ptr[3]));
- X ptr += 3;
- X }
- X break;
- X case RULE_MATCH: /* /x || /?c */
- X if (!ptr[1] || (ptr[1] == RULE_CLASS && !ptr[2]))
- X {
- X Debug(1, "Mangle: '/' missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else if (ptr[1] != RULE_CLASS)
- X {
- X if (!strchr(area, *(++ptr)))
- X {
- X return ((char *) 0);
- X }
- X } else
- X {
- X if (!PolyStrchr(area, ptr[2]))
- X {
- X return ((char *) 0);
- X }
- X ptr += 2;
- X }
- X break;
- X case RULE_NOT: /* !x || !?c */
- X if (!ptr[1] || (ptr[1] == RULE_CLASS && !ptr[2]))
- X {
- X Debug(1, "Mangle: '!' missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else if (ptr[1] != RULE_CLASS)
- X {
- X if (strchr(area, *(++ptr)))
- X {
- X return ((char *) 0);
- X }
- X } else
- X {
- X if (PolyStrchr(area, ptr[2]))
- X {
- X return ((char *) 0);
- X }
- X ptr += 2;
- X }
- X break;
- X /*
- X * alternative use for a boomerang, number 1: a standard throwing
- X * boomerang is an ideal thing to use to tuck the sheets under
- X * the mattress when making your bed. The streamlined shape of
- X * the boomerang allows it to slip easily 'twixt mattress and
- X * bedframe, and it's curve makes it very easy to hook sheets
- X * into the gap.
- X */
- X
- X case RULE_EQUALS: /* =nx || =n?c */
- X if (!ptr[1] || !ptr[2] || (ptr[2] == RULE_CLASS && !ptr[3]))
- X {
- X Debug(1, "Mangle: '=' missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X register int i;
- X if ((i = Char2Int(ptr[1])) < 0)
- X {
- X Debug(1, "Mangle: '=' weird argument in '%s'\n", control);
- X return ((char *) 0);
- X }
- X if (ptr[2] != RULE_CLASS)
- X {
- X ptr += 2;
- X if (area[i] != *ptr)
- X {
- X return ((char *) 0);
- X }
- X } else
- X {
- X ptr += 3;
- X if (!MatchClass(*ptr, area[i]))
- X {
- X return ((char *) 0);
- X }
- X }
- X }
- X break;
- X
- X case RULE_DFIRST:
- X if (area[0])
- X {
- X register int i;
- X for (i = 1; area[i]; i++)
- X {
- X area[i - 1] = area[i];
- X }
- X area[i - 1] = '\0';
- X }
- X break;
- X
- X case RULE_DLAST:
- X if (area[0])
- X {
- X register int i;
- X for (i = 1; area[i]; i++);
- X area[i - 1] = '\0';
- X }
- X break;
- X
- X case RULE_MFIRST:
- X if (!ptr[1] || (ptr[1] == RULE_CLASS && !ptr[2]))
- X {
- X Debug(1, "Mangle: '(' missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X if (ptr[1] != RULE_CLASS)
- X {
- X ptr++;
- X if (area[0] != *ptr)
- X {
- X return ((char *) 0);
- X }
- X } else
- X {
- X ptr += 2;
- X if (!MatchClass(*ptr, area[0]))
- X {
- X return ((char *) 0);
- X }
- X }
- X }
- X case RULE_MLAST:
- X if (!ptr[1] || (ptr[1] == RULE_CLASS && !ptr[2]))
- X {
- X Debug(1, "Mangle: ')' missing argument in '%s'\n", control);
- X return ((char *) 0);
- X } else
- X {
- X register int i;
- X
- X for (i = 0; area[i]; i++);
- X
- X if (i > 0)
- X {
- X i--;
- X } else
- X {
- X return ((char *) 0);
- X }
- X
- X if (ptr[1] != RULE_CLASS)
- X {
- X ptr++;
- X if (area[i] != *ptr)
- X {
- X return ((char *) 0);
- X }
- X } else
- X {
- X ptr += 2;
- X if (!MatchClass(*ptr, area[i]))
- X {
- X return ((char *) 0);
- X }
- X }
- X }
- X
- X default:
- X Debug(1, "Mangle: unknown command %c in %s\n", *ptr, control);
- X return ((char *) 0);
- X break;
- X }
- X }
- X if (!area[0]) /* have we deweted de poor widdle fing away? */
- X {
- X return ((char *) 0);
- X }
- X return (area);
- X}
- X
- Xint
- XPMatch(control, string)
- Xregister char *control;
- Xregister char *string;
- X{
- X while (*string && *control)
- X {
- X if (!MatchClass(*control, *string))
- X {
- X return(0);
- X }
- X
- X string++;
- X control++;
- X }
- X
- X if (*string || *control)
- X {
- X return(0);
- X }
- X
- X return(1);
- X}
- END_OF_FILE
- if test 15448 -ne `wc -c <'cracklib/rules.c'`; then
- echo shar: \"'cracklib/rules.c'\" unpacked with wrong size!
- fi
- # end of 'cracklib/rules.c'
- fi
- if test ! -d 'shadow' ; then
- echo shar: Creating directory \"'shadow'\"
- mkdir 'shadow'
- fi
- if test -f 'shadow/README,CL' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'shadow/README,CL'\"
- else
- echo shar: Extracting \"'shadow/README,CL'\" \(1362 characters\)
- sed "s/^X//" >'shadow/README,CL' <<'END_OF_FILE'
- XHi,
- X
- XThis here's a patch for John F Haugh's "shadow" password program, to get
- Xit using "CrackLib". I'm afraid I haven't had much opportunity to test
- Xit (I don't have the time or resources), but I'd like to know how you
- Xget on using it.
- X
- XInstructions:
- X
- X 1) Read the docs. Build and install CrackLib.
- X
- X 2) Install the latest version of "shadow" (patchlevel 6)
- X - available from comp.sources.misc archives everywhere.
- X
- X It's spattered amongst several directories (being a initial
- X distribution, + patches), so you'll need the contents of:
- X
- X usenet/comp.sources.misc/volume26/shadow
- X usenet/comp.sources.misc/volume28/shadow
- X usenet/comp.sources.misc/volume29/shadow
- X usenet/comp.sources.misc/volume30/shadow
- X usenet/comp.sources.misc/volume32/shadow
- X
- X 3) Install the enclosed file as "obscure.c" - it's only a
- X trivial change, you might like to hack it a bit yourself.
- X
- X 4) Edit the new "obscure.c" to change the value of:
- X
- X CRACKLIB_DICTPATH
- X
- X - to whatever you used during the CrackLib installation
- X
- X 5) Change the "shadow" Makefile to that shadow will be linked
- X with CrackLib, eg:
- X
- X change:
- X
- X LIBS = -lcrypt -lndbm
- X
- X to:
- X
- X LIBS = /where/ever/cracklib/cracklib.a -lcrypt -lndbm
- X
- X 6) Build and install "shadow"
- X
- X 7) Make sure you have obscure checks enabled
- X
- X 8) Run with it.
- X
- X
- X - alec (16 Jun 1993)
- END_OF_FILE
- if test 1362 -ne `wc -c <'shadow/README,CL'`; then
- echo shar: \"'shadow/README,CL'\" unpacked with wrong size!
- fi
- # end of 'shadow/README,CL'
- fi
- if test ! -d 'util' ; then
- echo shar: Creating directory \"'util'\"
- mkdir 'util'
- fi
- echo shar: End of archive 1 \(of 2\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 2 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked both archives.
- rm -f ark[1-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
-