]> eyrie.org Git - kerberos/krb5-strength.git/blob - cracklib/README
Add NEWS entry for spec file
[kerberos/krb5-strength.git] / cracklib / README
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.
5
6 Below is the original README.
7
8
9 CrackLib:       A ProActive Password Sanity Library
10 By:             Alec Muffett
11 Address:        alecm@crypto.dircon.co.uk
12 Date:           Sun Dec 14 22:16:48 GMT 1997
13
14 - This software is not my fault in any way, nor indeed anybody's -
15
16
17 *** What is CrackLib ***
18
19
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.
23
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.
26
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.
29
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.
32
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-) ]
36
37
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".
41
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.
45
46 You can use it almost _everywhere_.
47
48
49 *** Advantages of CrackLib ***
50
51
52 1) it WORKS!
53
54 I wrote something similar ("goodpass") a few years back, which went out
55 with Crack v3.x.
56
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.
59
60
61 2) it's FAST!
62
63 CrackLib finds potential passwords quickly, by using an index file to
64 access dictionary words, and by keeping a table to assist binary
65 searching.
66
67
68 3) it's SMALL!
69
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.
73
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)
77
78 It's even efficient over NFS !
79
80
81 4) it's MIND-NUMBINGLY THOROUGH!
82
83 (is this beginning to read like a B-movie flyer, or what?)
84
85 CrackLib makes literally hundreds of tests to determine whether you've
86 chosen a bad password.
87
88 * It tries to generate words from your username and gecos entry to tries
89 to match them against what you've chosen.
90
91 * It checks for simplistic patterns.
92
93 * It then tries to reverse-engineer your password into a dictionary
94 word, and searches for it in your dictionary.
95
96 - after all that, it's PROBABLY a safe(-ish) password.  8-)
97
98
99 *** Instructions for building CrackLib...
100
101
102 STEP 0) Engage your brain.
103
104 I'm interested in improving the CrackLib software, doing bugfixes,
105 "guessing technique" improvements, and portability enhancements. 
106
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. 
110
111 CrackLib is NOT a TOOL.  It is not a complete package.  It is not
112 something you can utilise directly. 
113
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
117 with it. 
118
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. 
122
123
124 STEP 1) Edit the Makefile to set your preferred value of DICTPATH
125
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
128 use CrackLib
129
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.
132
133 Note: You have to specify a FILENAME PREFIX too, eg:
134
135         DICTPATH=/usr/local/lib/pw_dict
136
137 which will generate:
138
139         /usr/local/lib/pw_dict.pwd
140         /usr/local/lib/pw_dict.pwi
141         /usr/local/lib/pw_dict.hwm
142
143 which are the files that CrackLib needs.
144
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:
148
149         DICTPATH=/usr/local/lib/pw_dict.sun4
150         DICTPATH=/usr/local/lib/pw_dict.i386
151         DICTPATH=/usr/local/lib/pw_dict.cray
152
153 ...etc, and build several sets of files, as appropriate.
154
155
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
160 SOURCEDICTs.
161
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.)
165
166
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.
171
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.
176
177
178 STEP 3) do:
179
180         % make all
181
182 then do:
183
184         % make install
185
186 which will build the CrackLib dictionary in $DICTPATH.
187
188
189 *** NOTE THIS WELL ***
190
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.
194
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.
198
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.
201
202
203 STEP 4) Wire a call to "FascistCheck()" into your "passwd" program
204
205
206 - Left as an exercise for the reader.
207
208
209 *** Example of how to invoke CrackLib
210
211 Insert a call to the routine FascistCheck, which is defined thusly:
212
213 NAME
214         FascistCheck - check a potential password for guessability
215
216
217 SYNOPSIS
218
219         char *FascistCheck(char *pw, char *dictpath);
220
221
222 DESCRIPTION
223
224         FascistCheck() takes 2 arguments:
225
226         pw - a string continaing the users chosen "potential password"
227
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).
231
232
233 RETURN VALUE
234
235         FascistCheck() returns the NULL pointer for a good password,
236         or a pointer to a diagnostic string if it is a bad password.
237
238
239 BUGS
240         - it can't catch everything. Just most things.
241
242         - it calls getpwuid(getuid()) to look up the user,
243           this MAY affect poorly written programs
244
245         - using more than one pw_dict file, eg:
246
247                 char *msg;
248                 if (msg = FascistCheck(pw, "onepath") ||
249                     msg = FascistCheck(pw, "anotherpath"))
250                 {
251                     printf("Bad Password: because %s\n", msg);
252                 }
253
254            ...works, but it's a kludge. AVOID IT IF POSSIBLE.
255            Using just the one dictionary is more efficient, anyway.
256
257         - PWOpen() routines should cope with having more than 1
258           dictionary open at a time.  I'll fix this RSN.
259
260
261 WORKED EXAMPLE
262
263 ---- modified extract from BSD distribution - "local_passwd.c" ----
264
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 */
268 ...
269 ...
270 ...
271         for (buf[0] = '\0', tries = 0;;) {
272                 p = getpass("New password:");
273                 if (!*p) {
274                         (void)printf("Password unchanged.\n");
275                         pw_error(NULL, 0, 0);
276                 }
277
278 #ifndef CRACKLIB_DICTPATH
279                 if (strlen(p) <= 5 && (uid != 0 || ++tries < 2)) {
280                         (void)printf("Please enter a longer password.\n");
281                         continue;
282                 }
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");
286                         continue;
287                 }
288 #else
289                 {
290                         char *msg;
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 */
295                         }
296                 }
297 #endif /* CRACKLIB_DICTPATH */
298
299                 (void)strcpy(buf, p);
300                 if (!strcmp(buf, getpass("Retype new password:")))
301                         break;
302                 (void)printf("Mismatch; try again, EOF to quit.\n");
303         }
304 ---- end of extract ----