1 This directory contains the files from Alec Muffett's v2.7 release of the
2 CrackLib library (the cracklib subdirectory of the source) plus mkdict and
3 packer from the util directory. It has been modified for the needs of
4 this package in ways enumerated in HISTORY and noted in each source file.
6 Below is the original README.
9 CrackLib: A ProActive Password Sanity Library
11 Address: alecm@crypto.dircon.co.uk
12 Date: Sun Dec 14 22:16:48 GMT 1997
14 - This software is not my fault in any way, nor indeed anybody's -
17 *** What is CrackLib ***
20 CrackLib is a library containing a C function (well, lots of functions
21 really, but you only need to use one of them) which may be used in a
22 "passwd"-like program.
24 The idea is simple: try to prevent users from choosing passwords that
25 could be guessed by "Crack" by filtering them out, at source.
27 CrackLib is an offshoot of the the version 5 "Crack" software, and
28 contains a considerable number of ideas nicked from the new software.
30 At the time of writing, Crack 5 is incomplete (still awaiting purchase
31 of my home box) - but I though I could share this with you.
33 [ Incidentally, if Dell or anyone would like to "donate" a Linuxable
34 486DX2-66MHz box (EISA/16Mb RAM/640MB HD/AHA1740) as a development
35 platform for Crack, I'd be more than grateful to hear from you. 8-) ]
38 NOTE THIS WELL: CrackLib is NOT a replacement "passwd" program.
39 CrackLib is a LIBRARY. CrackLib is what trendy marketdroid types would
40 probably call an "enabler".
42 The idea is that you wire it into your _own_ "passwd" program (if you
43 have source); alternatively, you wire it into something like "shadow"
44 from off of the net. You can use it in other things, too.
46 You can use it almost _everywhere_.
49 *** Advantages of CrackLib ***
54 I wrote something similar ("goodpass") a few years back, which went out
57 Goodpass was slow and buggy and I think it was used (at least in part)
58 in "npasswd". Hopefully, CrackLib will supplant "goodpass" entirely.
63 CrackLib finds potential passwords quickly, by using an index file to
64 access dictionary words, and by keeping a table to assist binary
70 CrackLib's dictionary is modified-DAWG compressed with a chunksize of 16
71 words (see Crack v5.0 docs (when it comes out) for details) - and then
72 the index file is built, with one entry per chunk.
74 The upshot of all this is that CrackLib can do indexed, binary searches
75 in a 1.4 million word dictionary (raw size ~ 15Mb), but the CrackLib
76 files (data+index+watermarks) occupy only ~ 7Mb. (45% original size)
78 It's even efficient over NFS !
81 4) it's MIND-NUMBINGLY THOROUGH!
83 (is this beginning to read like a B-movie flyer, or what?)
85 CrackLib makes literally hundreds of tests to determine whether you've
86 chosen a bad password.
88 * It tries to generate words from your username and gecos entry to tries
89 to match them against what you've chosen.
91 * It checks for simplistic patterns.
93 * It then tries to reverse-engineer your password into a dictionary
94 word, and searches for it in your dictionary.
96 - after all that, it's PROBABLY a safe(-ish) password. 8-)
99 *** Instructions for building CrackLib...
102 STEP 0) Engage your brain.
104 I'm interested in improving the CrackLib software, doing bugfixes,
105 "guessing technique" improvements, and portability enhancements.
107 I'm NOT interested in unhelpful comments like "well, _my_ operating
108 system doesn't come with a dictionary". If it doesn't, either complain
109 to your vendor, or GO AND GET a dictionary off the net.
111 CrackLib is NOT a TOOL. It is not a complete package. It is not
112 something you can utilise directly.
114 It is a resource, an aid, something to enhance the functionality of
115 other software. You need to (either) write OR modify other software to
116 use it. If you can't do this, then you shouldn't be wasting your time
119 Regarding bugs and portability problems: please try to work them out for
120 yourself, and then (please) TELL me about them. This will help me
121 improve future versions.
124 STEP 1) Edit the Makefile to set your preferred value of DICTPATH
126 This it the directory+filename-prefix that your version of CrackLib will
127 go hunting for, and it must be visible to all programs on all hosts that
130 Hence, if you want to use a CrackLib binary on a distributed network,
131 these files are probably best placed on an NFS server.
133 Note: You have to specify a FILENAME PREFIX too, eg:
135 DICTPATH=/usr/local/lib/pw_dict
139 /usr/local/lib/pw_dict.pwd
140 /usr/local/lib/pw_dict.pwi
141 /usr/local/lib/pw_dict.hwm
143 which are the files that CrackLib needs.
145 These files are NOT byte-order independent, in fact they are probably
146 ARCHITECTURE SPECIFIC, mostly due to speed constraints. If this is a
147 problem, I suggest you use:
149 DICTPATH=/usr/local/lib/pw_dict.sun4
150 DICTPATH=/usr/local/lib/pw_dict.i386
151 DICTPATH=/usr/local/lib/pw_dict.cray
153 ...etc, and build several sets of files, as appropriate.
156 (Hackers Note: Strictly, only *.pwi and *.hwm should be architecture
157 dependent; however, if you build two dictionaries on two different
158 platforms, you MAY wind up with different *.pwd files too, due to
159 incompatibilities in the std Unix utilities, or from using different
162 I may try to work this out in the next release. In the mean time, if
163 your *.pwd files are EXACTLY identical (use "cmp" to test), you can
164 delete the multiple copies and use softlinks instead.)
167 STEP 2) Add to the SOURCEDICT variable, any files continaing extra words
168 that you wish CrackLib to use. CrackLib merges all of these files
169 together, removes redundant characters, and compresses them. Generally,
170 the output file is 40..60% the size of all the input files, combined.
172 NOTE: THE DEFAULT VALUE OF "SOURCEDICT" CONTAINS "/usr/dict/words" -
173 this is a file which can be found on many BSD-type Unix systems,
174 containing a list of words, one per line, suitable for use with
175 "cracklib". If you do not have such a file, refer to STEP 0.
186 which will build the CrackLib dictionary in $DICTPATH.
189 *** NOTE THIS WELL ***
191 If you supply massive amounts of text to CrackLib to use a a dictionary,
192 you must have enough free space available for use by the "sort" command,
193 when the dictionary is built.
195 So: If you do not have (say) about 20Mb free in /usr/tmp (or whatever
196 temporary area your "sort" command uses), have a look at the
197 "util/mkdict" script.
199 You can usually tweak the "sort" command to use any large area of disk
200 you desire, by use of the "-T" option, and "mkdict" has a hook for this.
203 STEP 4) Wire a call to "FascistCheck()" into your "passwd" program
206 - Left as an exercise for the reader.
209 *** Example of how to invoke CrackLib
211 Insert a call to the routine FascistCheck, which is defined thusly:
214 FascistCheck - check a potential password for guessability
219 char *FascistCheck(char *pw, char *dictpath);
224 FascistCheck() takes 2 arguments:
226 pw - a string continaing the users chosen "potential password"
228 dictpath - the full path name + filename prefix of the
229 CrackLib dictionary, specified in the installation Makefile.
230 (If you still haven't sussed, I'm talking about DICTPATH).
235 FascistCheck() returns the NULL pointer for a good password,
236 or a pointer to a diagnostic string if it is a bad password.
240 - it can't catch everything. Just most things.
242 - it calls getpwuid(getuid()) to look up the user,
243 this MAY affect poorly written programs
245 - using more than one pw_dict file, eg:
248 if (msg = FascistCheck(pw, "onepath") ||
249 msg = FascistCheck(pw, "anotherpath"))
251 printf("Bad Password: because %s\n", msg);
254 ...works, but it's a kludge. AVOID IT IF POSSIBLE.
255 Using just the one dictionary is more efficient, anyway.
257 - PWOpen() routines should cope with having more than 1
258 dictionary open at a time. I'll fix this RSN.
263 ---- modified extract from BSD distribution - "local_passwd.c" ----
265 #ifndef CRACKLIB_DICTPATH /* if possible, get from the same Makefile as CrackLib */
266 #define CRACKLIB_DICTPATH "/usr/local/lib/pw_dict"
267 #endif /* see examples on how to import DICTPATH into CRACKLIB_DICTPATH */
271 for (buf[0] = '\0', tries = 0;;) {
272 p = getpass("New password:");
274 (void)printf("Password unchanged.\n");
275 pw_error(NULL, 0, 0);
278 #ifndef CRACKLIB_DICTPATH
279 if (strlen(p) <= 5 && (uid != 0 || ++tries < 2)) {
280 (void)printf("Please enter a longer password.\n");
283 for (t = p; *t && islower(*t); ++t);
284 if (!*t && (uid != 0 || ++tries < 2)) {
285 (void)printf("Please don't use an all-lower case password.\nUnusual capitalization, control characters or digits are suggested.\n");
291 if (msg = (char *) FascistCheck(pwbuf, CRACKLIB_DICTPATH)) {
292 printf("Please use a different password.\n");
293 printf("The one you have chosen is unsuitable because %s.\n", msg);
294 continue; /* go round and round until they get it right */
297 #endif /* CRACKLIB_DICTPATH */
299 (void)strcpy(buf, p);
300 if (!strcmp(buf, getpass("Retype new password:")))
302 (void)printf("Mismatch; try again, EOF to quit.\n");
304 ---- end of extract ----