This package is an updated/modernized distribution of CrackLib as 
previously release by Alec Muffett. Pretty much all of the files have
been modified in some way to allow for this modernization and to 
apply numerous bug fixes and patches. 

Copyright in the original source is assigned to Alec Muffett, numerous
authors have contributed the patches applied to these sources, and
are included here without attribution as there are no good records.

The primary reason for the updated release was to apply bug fixes and 
get them distributed from some central place instead of trying to get all
of the various repackagers to apply additional packages.

BUILD/INSTALL NOTE: You must invoke 'create-cracklib-dict', preferably after 
getting a large wordlist, after install. Otherwise it will not install the 
dictionaries.  This is left as a manual step since on some systems generating 
the dictionary index can be time consuming.


============================
Original CrackLib 2.7 README
============================

CrackLib:	A ProActive Password Sanity Library
By: 		Alec Muffett
Address:	alecm@crypto.dircon.co.uk
Date:		Sun Dec 14 22:16:48 GMT 1997

- This software is not my fault in any way, nor indeed anybody's -


*** What is CrackLib ***


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.

[ Incidentally, if Dell or anyone would like to "donate" a Linuxable
486DX2-66MHz box (EISA/16Mb RAM/640MB HD/AHA1740) as a development
platform for Crack, I'd be more than grateful to hear from you.  8-) ]


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 in other things, too.

You can use it almost _everywhere_.


*** Advantages of CrackLib ***


1) it WORKS!

I wrote something similar ("goodpass") a few years back, which went out
with Crack v3.x.

Goodpass was slow and buggy and I think it was used (at least in part)
in "npasswd".  Hopefully, CrackLib will supplant "goodpass" entirely.


2) it's FAST!

CrackLib finds potential passwords quickly, by using an index file to
access dictionary words, and by keeping a table to assist binary
searching.


3) it's SMALL!

CrackLib's dictionary is modified-DAWG compressed with a chunksize of 16
words (see Crack v5.0 docs (when it comes out) for details) - and then
the index file is built, with one entry per chunk.

The upshot of all this is that CrackLib can do indexed, binary searches
in a 1.4 million word dictionary (raw size ~ 15Mb), but the CrackLib
files (data+index+watermarks) occupy only ~ 7Mb.  (45% original size)

It's even efficient over NFS !


4) it's MIND-NUMBINGLY THOROUGH!

(is this beginning to read like a B-movie flyer, or what?)

CrackLib makes literally hundreds of tests to determine whether you've
chosen a bad password.

* It tries to generate words from your username and gecos entry to tries
to match them against what you've chosen.

* It checks for simplistic patterns.

* It then tries to reverse-engineer your password into a dictionary
word, and searches for it in your dictionary.

- after all that, it's PROBABLY a safe(-ish) password.  8-)


*** Instructions for building CrackLib...


STEP 0) Engage your brain.

I'm interested in improving the CrackLib software, doing bugfixes,
"guessing technique" improvements, and portability enhancements. 

I'm NOT interested in unhelpful comments like "well, _my_ operating
system doesn't come with a dictionary".  If it doesn't, either complain
to your vendor, or GO AND GET a dictionary off the net. 

CrackLib is NOT a TOOL.  It is not a complete package.  It is not
something you can utilise directly. 

It is a resource, an aid, something to enhance the functionality of
other software.  You need to (either) write OR modify other software to
use it.  If you can't do this, then you shouldn't be wasting your time
with it. 

Regarding bugs and portability problems: please try to work them out for
yourself, and then (please) TELL me about them.  This will help me
improve future versions. 


STEP 1) Edit the Makefile to set your preferred value of DICTPATH

This it the directory+filename-prefix that your version of CrackLib will
go hunting for, and it must be visible to all programs on all hosts that
use CrackLib

Hence, if you want to use a CrackLib binary on a distributed network,
these files are probably best placed on an NFS server.

Note: You have to specify a FILENAME PREFIX too, eg:

	DICTPATH=/usr/local/lib/pw_dict

which will generate:

	/usr/local/lib/pw_dict.pwd
	/usr/local/lib/pw_dict.pwi
	/usr/local/lib/pw_dict.hwm

which are the files that CrackLib needs.

These files are NOT byte-order independent, in fact they are probably
ARCHITECTURE SPECIFIC, mostly due to speed constraints.  If this is a
problem, I suggest you use:

	DICTPATH=/usr/local/lib/pw_dict.sun4
	DICTPATH=/usr/local/lib/pw_dict.i386
	DICTPATH=/usr/local/lib/pw_dict.cray

...etc, and build several sets of files, as appropriate.


(Hackers Note: Strictly, only *.pwi and *.hwm should be architecture
dependent; however, if you build two dictionaries on two different
platforms, you MAY wind up with different *.pwd files too, due to
incompatibilities in the std Unix utilities, or from using different
SOURCEDICTs.

I may try to work this out in the next release.  In the mean time, if
your *.pwd files are EXACTLY identical (use "cmp" to test), you can
delete the multiple copies and use softlinks instead.)


STEP 2) Add to the SOURCEDICT variable, any files continaing extra words
that you wish CrackLib to use.  CrackLib merges all of these files
together, removes redundant characters, and compresses them.  Generally,
the output file is 40..60% the size of all the input files, combined.

NOTE: THE DEFAULT VALUE OF "SOURCEDICT" CONTAINS "/usr/dict/words" -
this is a file which can be found on many BSD-type Unix systems,
containing a list of words, one per line, suitable for use with
"cracklib".  If you do not have such a file, refer to STEP 0.


STEP 3) do:

	% make all

then do:

	% make install

which will build the CrackLib dictionary in $DICTPATH.


*** NOTE THIS WELL ***

If you supply massive amounts of text to CrackLib to use a a dictionary,
you must have enough free space available for use by the "sort" command,
when the dictionary is built.

So: If you do not have (say) about 20Mb free in /usr/tmp (or whatever
temporary area your "sort" command uses), have a look at the
"util/mkdict" script.

You can usually tweak the "sort" command to use any large area of disk
you desire, by use of the "-T" option, and "mkdict" has a hook for this.


STEP 4) Wire a call to "FascistCheck()" into your "passwd" program


- Left as an exercise for the reader.


*** Example of how to invoke CrackLib

Insert a call to the routine FascistCheck, which is defined thusly:

NAME
	FascistCheck - check a potential password for guessability


SYNOPSIS

	char *FascistCheck(char *pw, char *dictpath);


DESCRIPTION

	FascistCheck() takes 2 arguments:

	pw - a string continaing the users chosen "potential password"

	dictpath - the full path name + filename prefix of the
	CrackLib dictionary, specified in the installation Makefile.
	(If you still haven't sussed, I'm talking about DICTPATH).


RETURN VALUE

	FascistCheck() returns the NULL pointer for a good password,
	or a pointer to a diagnostic string if it is a bad password.


BUGS
	- it can't catch everything. Just most things.

	- it calls getpwuid(getuid()) to look up the user,
	  this MAY affect poorly written programs

	- using more than one pw_dict file, eg:

		char *msg;
		if (msg = FascistCheck(pw, "onepath") ||
		    msg = FascistCheck(pw, "anotherpath"))
		{
		    printf("Bad Password: because %s\n", msg);
		}

	   ...works, but it's a kludge. AVOID IT IF POSSIBLE.
	   Using just the one dictionary is more efficient, anyway.

	- PWOpen() routines should cope with having more than 1
	  dictionary open at a time.  I'll fix this RSN.


WORKED EXAMPLE

---- modified extract from BSD distribution - "local_passwd.c" ----

#ifndef CRACKLIB_DICTPATH /* if possible, get from the same Makefile as CrackLib */
#define CRACKLIB_DICTPATH "/usr/local/lib/pw_dict"
#endif		/* see examples on how to import DICTPATH into CRACKLIB_DICTPATH */
...
...
...
	for (buf[0] = '\0', tries = 0;;) {
		p = getpass("New password:");
		if (!*p) {
			(void)printf("Password unchanged.\n");
			pw_error(NULL, 0, 0);
		}

#ifndef CRACKLIB_DICTPATH
		if (strlen(p) <= 5 && (uid != 0 || ++tries < 2)) {
			(void)printf("Please enter a longer password.\n");
			continue;
		}
		for (t = p; *t && islower(*t); ++t);
		if (!*t && (uid != 0 || ++tries < 2)) {
			(void)printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
			continue;
		}
#else
		{
			char *msg;
			if (msg = (char *) FascistCheck(pwbuf, CRACKLIB_DICTPATH)) {
				printf("Please use a different password.\n");
				printf("The one you have chosen is unsuitable because %s.\n", msg);
				continue;	/* go round and round until they get it right */
			}
		}
#endif /* CRACKLIB_DICTPATH */

		(void)strcpy(buf, p);
		if (!strcmp(buf, getpass("Retype new password:")))
			break;
		(void)printf("Mismatch; try again, EOF to quit.\n");
	}
---- end of extract ----
