]> eyrie.org Git - kerberos/krb5-strength.git/blob - cracklib/fascist.c
Update DocKnot configuration
[kerberos/krb5-strength.git] / cracklib / fascist.c
1 /*
2  * This program is copyright Alec Muffett 1993. The author disclaims all
3  * responsibility or liability with respect to it's usage or its effect
4  * upon hardware or computer systems, and maintains copyright as set out
5  * in the "LICENCE" document which accompanies distributions of Crack v4.0
6  * and upwards.
7  */
8
9 /*
10  * Modified as part of the krb5-strength project as follows:
11  *
12  * 2007-03-22  Russ Allbery <eagle@eyrie.org>
13  *   - Add four-, five-, and six-character prefix and suffix rules.
14  *   - Longer passwords must contain more different characters, up to 8.
15  *   - Disable GECOS checking (useless for a server).
16  *   - Replace exit(-1) with return when dictionary doesn't exist.
17  *   - Additional system includes for other functions.
18  * 2009-10-14  Russ Allbery <eagle@eyrie.org>
19  *   - Add ANSI C protototypes for all functions.
20  *   - Tweaks for const cleanliness.
21  *   - Add parentheses around assignment used for its truth value.
22  *   - Change a variable to unsigned int to avoid gcc warnings.
23  *   - Remove the unused FascistGecos function.
24  * 2012-05-11  Russ Allbery <eagle@eyrie.org>
25  *   - Change MINLENGTH to 8.
26  *   - Use a separate buffer to hold the reversed password.
27  *   - Also check whether a password is a duplicated dictionary word.
28  * 2013-09-24  Russ Allbery <eagle@eyrie.org>
29  *   - Replaced MAXSTEP with allowing one increment per four characters.
30  *   - Changed error for very short passwords to match current CrackLib.
31  *   - Close the dictionary after each password lookup.
32  * 2016-11-06  Russ Allbery <eagle@eyrie.org>
33  *   - Remove unused vers_id to silence GCC warnings
34  *   - Changed some variables from int or unsigned int to size_t
35  */
36
37 #include "packer.h"
38 #include <sys/types.h>
39 #include <pwd.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43
44 #define ISSKIP(x) (isspace(x) || ispunct(x))
45
46 #define MINDIFF 5
47 #define MINLEN 8
48 #define MAXMINDIFF 8
49
50 #undef DEBUG
51 #undef DEBUG2
52
53 static const char *r_destructors[] = {
54     ":",                        /* noop - must do this to test raw word. */
55
56 #ifdef DEBUG2
57     (char *) 0,
58 #endif
59
60     "[",                        /* trimming leading/trailing junk */
61     "]",
62     "[[",
63     "]]",
64     "[[[",
65     "]]]", /* 5 for 8 char passwords */ 
66     /* This is for longer passwords, it should be based on length */ 
67     "]]]]", /* 6 for 10 char passwords */ 
68     "[[[[",
69     "]]]]]", /* 7 for 12 char passwords */ 
70     "[[[[[",
71     "]]]]]]", /* 8 for 14 char passwords */ 
72     "[[[[[[",
73
74     "/?p@?p",                   /* purging out punctuation/symbols/junk */
75     "/?s@?s",
76     "/?X@?X",
77
78     /* attempt reverse engineering of password strings */
79
80     "/$s$s",
81     "/$s$s/0s0o",
82     "/$s$s/0s0o/2s2a",
83     "/$s$s/0s0o/2s2a/3s3e",
84     "/$s$s/0s0o/2s2a/3s3e/5s5s",
85     "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i",
86     "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l",
87     "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i/4s4a",
88     "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i/4s4h",
89     "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l/4s4a",
90     "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l/4s4h",
91     "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4a",
92     "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4h",
93     "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4a",
94     "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4h",
95     "/$s$s/0s0o/2s2a/3s3e/1s1i",
96     "/$s$s/0s0o/2s2a/3s3e/1s1l",
97     "/$s$s/0s0o/2s2a/3s3e/1s1i/4s4a",
98     "/$s$s/0s0o/2s2a/3s3e/1s1i/4s4h",
99     "/$s$s/0s0o/2s2a/3s3e/1s1l/4s4a",
100     "/$s$s/0s0o/2s2a/3s3e/1s1l/4s4h",
101     "/$s$s/0s0o/2s2a/3s3e/4s4a",
102     "/$s$s/0s0o/2s2a/3s3e/4s4h",
103     "/$s$s/0s0o/2s2a/3s3e/4s4a",
104     "/$s$s/0s0o/2s2a/3s3e/4s4h",
105     "/$s$s/0s0o/2s2a/5s5s",
106     "/$s$s/0s0o/2s2a/5s5s/1s1i",
107     "/$s$s/0s0o/2s2a/5s5s/1s1l",
108     "/$s$s/0s0o/2s2a/5s5s/1s1i/4s4a",
109     "/$s$s/0s0o/2s2a/5s5s/1s1i/4s4h",
110     "/$s$s/0s0o/2s2a/5s5s/1s1l/4s4a",
111     "/$s$s/0s0o/2s2a/5s5s/1s1l/4s4h",
112     "/$s$s/0s0o/2s2a/5s5s/4s4a",
113     "/$s$s/0s0o/2s2a/5s5s/4s4h",
114     "/$s$s/0s0o/2s2a/5s5s/4s4a",
115     "/$s$s/0s0o/2s2a/5s5s/4s4h",
116     "/$s$s/0s0o/2s2a/1s1i",
117     "/$s$s/0s0o/2s2a/1s1l",
118     "/$s$s/0s0o/2s2a/1s1i/4s4a",
119     "/$s$s/0s0o/2s2a/1s1i/4s4h",
120     "/$s$s/0s0o/2s2a/1s1l/4s4a",
121     "/$s$s/0s0o/2s2a/1s1l/4s4h",
122     "/$s$s/0s0o/2s2a/4s4a",
123     "/$s$s/0s0o/2s2a/4s4h",
124     "/$s$s/0s0o/2s2a/4s4a",
125     "/$s$s/0s0o/2s2a/4s4h",
126     "/$s$s/0s0o/3s3e",
127     "/$s$s/0s0o/3s3e/5s5s",
128     "/$s$s/0s0o/3s3e/5s5s/1s1i",
129     "/$s$s/0s0o/3s3e/5s5s/1s1l",
130     "/$s$s/0s0o/3s3e/5s5s/1s1i/4s4a",
131     "/$s$s/0s0o/3s3e/5s5s/1s1i/4s4h",
132     "/$s$s/0s0o/3s3e/5s5s/1s1l/4s4a",
133     "/$s$s/0s0o/3s3e/5s5s/1s1l/4s4h",
134     "/$s$s/0s0o/3s3e/5s5s/4s4a",
135     "/$s$s/0s0o/3s3e/5s5s/4s4h",
136     "/$s$s/0s0o/3s3e/5s5s/4s4a",
137     "/$s$s/0s0o/3s3e/5s5s/4s4h",
138     "/$s$s/0s0o/3s3e/1s1i",
139     "/$s$s/0s0o/3s3e/1s1l",
140     "/$s$s/0s0o/3s3e/1s1i/4s4a",
141     "/$s$s/0s0o/3s3e/1s1i/4s4h",
142     "/$s$s/0s0o/3s3e/1s1l/4s4a",
143     "/$s$s/0s0o/3s3e/1s1l/4s4h",
144     "/$s$s/0s0o/3s3e/4s4a",
145     "/$s$s/0s0o/3s3e/4s4h",
146     "/$s$s/0s0o/3s3e/4s4a",
147     "/$s$s/0s0o/3s3e/4s4h",
148     "/$s$s/0s0o/5s5s",
149     "/$s$s/0s0o/5s5s/1s1i",
150     "/$s$s/0s0o/5s5s/1s1l",
151     "/$s$s/0s0o/5s5s/1s1i/4s4a",
152     "/$s$s/0s0o/5s5s/1s1i/4s4h",
153     "/$s$s/0s0o/5s5s/1s1l/4s4a",
154     "/$s$s/0s0o/5s5s/1s1l/4s4h",
155     "/$s$s/0s0o/5s5s/4s4a",
156     "/$s$s/0s0o/5s5s/4s4h",
157     "/$s$s/0s0o/5s5s/4s4a",
158     "/$s$s/0s0o/5s5s/4s4h",
159     "/$s$s/0s0o/1s1i",
160     "/$s$s/0s0o/1s1l",
161     "/$s$s/0s0o/1s1i/4s4a",
162     "/$s$s/0s0o/1s1i/4s4h",
163     "/$s$s/0s0o/1s1l/4s4a",
164     "/$s$s/0s0o/1s1l/4s4h",
165     "/$s$s/0s0o/4s4a",
166     "/$s$s/0s0o/4s4h",
167     "/$s$s/0s0o/4s4a",
168     "/$s$s/0s0o/4s4h",
169     "/$s$s/2s2a",
170     "/$s$s/2s2a/3s3e",
171     "/$s$s/2s2a/3s3e/5s5s",
172     "/$s$s/2s2a/3s3e/5s5s/1s1i",
173     "/$s$s/2s2a/3s3e/5s5s/1s1l",
174     "/$s$s/2s2a/3s3e/5s5s/1s1i/4s4a",
175     "/$s$s/2s2a/3s3e/5s5s/1s1i/4s4h",
176     "/$s$s/2s2a/3s3e/5s5s/1s1l/4s4a",
177     "/$s$s/2s2a/3s3e/5s5s/1s1l/4s4h",
178     "/$s$s/2s2a/3s3e/5s5s/4s4a",
179     "/$s$s/2s2a/3s3e/5s5s/4s4h",
180     "/$s$s/2s2a/3s3e/5s5s/4s4a",
181     "/$s$s/2s2a/3s3e/5s5s/4s4h",
182     "/$s$s/2s2a/3s3e/1s1i",
183     "/$s$s/2s2a/3s3e/1s1l",
184     "/$s$s/2s2a/3s3e/1s1i/4s4a",
185     "/$s$s/2s2a/3s3e/1s1i/4s4h",
186     "/$s$s/2s2a/3s3e/1s1l/4s4a",
187     "/$s$s/2s2a/3s3e/1s1l/4s4h",
188     "/$s$s/2s2a/3s3e/4s4a",
189     "/$s$s/2s2a/3s3e/4s4h",
190     "/$s$s/2s2a/3s3e/4s4a",
191     "/$s$s/2s2a/3s3e/4s4h",
192     "/$s$s/2s2a/5s5s",
193     "/$s$s/2s2a/5s5s/1s1i",
194     "/$s$s/2s2a/5s5s/1s1l",
195     "/$s$s/2s2a/5s5s/1s1i/4s4a",
196     "/$s$s/2s2a/5s5s/1s1i/4s4h",
197     "/$s$s/2s2a/5s5s/1s1l/4s4a",
198     "/$s$s/2s2a/5s5s/1s1l/4s4h",
199     "/$s$s/2s2a/5s5s/4s4a",
200     "/$s$s/2s2a/5s5s/4s4h",
201     "/$s$s/2s2a/5s5s/4s4a",
202     "/$s$s/2s2a/5s5s/4s4h",
203     "/$s$s/2s2a/1s1i",
204     "/$s$s/2s2a/1s1l",
205     "/$s$s/2s2a/1s1i/4s4a",
206     "/$s$s/2s2a/1s1i/4s4h",
207     "/$s$s/2s2a/1s1l/4s4a",
208     "/$s$s/2s2a/1s1l/4s4h",
209     "/$s$s/2s2a/4s4a",
210     "/$s$s/2s2a/4s4h",
211     "/$s$s/2s2a/4s4a",
212     "/$s$s/2s2a/4s4h",
213     "/$s$s/3s3e",
214     "/$s$s/3s3e/5s5s",
215     "/$s$s/3s3e/5s5s/1s1i",
216     "/$s$s/3s3e/5s5s/1s1l",
217     "/$s$s/3s3e/5s5s/1s1i/4s4a",
218     "/$s$s/3s3e/5s5s/1s1i/4s4h",
219     "/$s$s/3s3e/5s5s/1s1l/4s4a",
220     "/$s$s/3s3e/5s5s/1s1l/4s4h",
221     "/$s$s/3s3e/5s5s/4s4a",
222     "/$s$s/3s3e/5s5s/4s4h",
223     "/$s$s/3s3e/5s5s/4s4a",
224     "/$s$s/3s3e/5s5s/4s4h",
225     "/$s$s/3s3e/1s1i",
226     "/$s$s/3s3e/1s1l",
227     "/$s$s/3s3e/1s1i/4s4a",
228     "/$s$s/3s3e/1s1i/4s4h",
229     "/$s$s/3s3e/1s1l/4s4a",
230     "/$s$s/3s3e/1s1l/4s4h",
231     "/$s$s/3s3e/4s4a",
232     "/$s$s/3s3e/4s4h",
233     "/$s$s/3s3e/4s4a",
234     "/$s$s/3s3e/4s4h",
235     "/$s$s/5s5s",
236     "/$s$s/5s5s/1s1i",
237     "/$s$s/5s5s/1s1l",
238     "/$s$s/5s5s/1s1i/4s4a",
239     "/$s$s/5s5s/1s1i/4s4h",
240     "/$s$s/5s5s/1s1l/4s4a",
241     "/$s$s/5s5s/1s1l/4s4h",
242     "/$s$s/5s5s/4s4a",
243     "/$s$s/5s5s/4s4h",
244     "/$s$s/5s5s/4s4a",
245     "/$s$s/5s5s/4s4h",
246     "/$s$s/1s1i",
247     "/$s$s/1s1l",
248     "/$s$s/1s1i/4s4a",
249     "/$s$s/1s1i/4s4h",
250     "/$s$s/1s1l/4s4a",
251     "/$s$s/1s1l/4s4h",
252     "/$s$s/4s4a",
253     "/$s$s/4s4h",
254     "/$s$s/4s4a",
255     "/$s$s/4s4h",
256     "/0s0o",
257     "/0s0o/2s2a",
258     "/0s0o/2s2a/3s3e",
259     "/0s0o/2s2a/3s3e/5s5s",
260     "/0s0o/2s2a/3s3e/5s5s/1s1i",
261     "/0s0o/2s2a/3s3e/5s5s/1s1l",
262     "/0s0o/2s2a/3s3e/5s5s/1s1i/4s4a",
263     "/0s0o/2s2a/3s3e/5s5s/1s1i/4s4h",
264     "/0s0o/2s2a/3s3e/5s5s/1s1l/4s4a",
265     "/0s0o/2s2a/3s3e/5s5s/1s1l/4s4h",
266     "/0s0o/2s2a/3s3e/5s5s/4s4a",
267     "/0s0o/2s2a/3s3e/5s5s/4s4h",
268     "/0s0o/2s2a/3s3e/5s5s/4s4a",
269     "/0s0o/2s2a/3s3e/5s5s/4s4h",
270     "/0s0o/2s2a/3s3e/1s1i",
271     "/0s0o/2s2a/3s3e/1s1l",
272     "/0s0o/2s2a/3s3e/1s1i/4s4a",
273     "/0s0o/2s2a/3s3e/1s1i/4s4h",
274     "/0s0o/2s2a/3s3e/1s1l/4s4a",
275     "/0s0o/2s2a/3s3e/1s1l/4s4h",
276     "/0s0o/2s2a/3s3e/4s4a",
277     "/0s0o/2s2a/3s3e/4s4h",
278     "/0s0o/2s2a/3s3e/4s4a",
279     "/0s0o/2s2a/3s3e/4s4h",
280     "/0s0o/2s2a/5s5s",
281     "/0s0o/2s2a/5s5s/1s1i",
282     "/0s0o/2s2a/5s5s/1s1l",
283     "/0s0o/2s2a/5s5s/1s1i/4s4a",
284     "/0s0o/2s2a/5s5s/1s1i/4s4h",
285     "/0s0o/2s2a/5s5s/1s1l/4s4a",
286     "/0s0o/2s2a/5s5s/1s1l/4s4h",
287     "/0s0o/2s2a/5s5s/4s4a",
288     "/0s0o/2s2a/5s5s/4s4h",
289     "/0s0o/2s2a/5s5s/4s4a",
290     "/0s0o/2s2a/5s5s/4s4h",
291     "/0s0o/2s2a/1s1i",
292     "/0s0o/2s2a/1s1l",
293     "/0s0o/2s2a/1s1i/4s4a",
294     "/0s0o/2s2a/1s1i/4s4h",
295     "/0s0o/2s2a/1s1l/4s4a",
296     "/0s0o/2s2a/1s1l/4s4h",
297     "/0s0o/2s2a/4s4a",
298     "/0s0o/2s2a/4s4h",
299     "/0s0o/2s2a/4s4a",
300     "/0s0o/2s2a/4s4h",
301     "/0s0o/3s3e",
302     "/0s0o/3s3e/5s5s",
303     "/0s0o/3s3e/5s5s/1s1i",
304     "/0s0o/3s3e/5s5s/1s1l",
305     "/0s0o/3s3e/5s5s/1s1i/4s4a",
306     "/0s0o/3s3e/5s5s/1s1i/4s4h",
307     "/0s0o/3s3e/5s5s/1s1l/4s4a",
308     "/0s0o/3s3e/5s5s/1s1l/4s4h",
309     "/0s0o/3s3e/5s5s/4s4a",
310     "/0s0o/3s3e/5s5s/4s4h",
311     "/0s0o/3s3e/5s5s/4s4a",
312     "/0s0o/3s3e/5s5s/4s4h",
313     "/0s0o/3s3e/1s1i",
314     "/0s0o/3s3e/1s1l",
315     "/0s0o/3s3e/1s1i/4s4a",
316     "/0s0o/3s3e/1s1i/4s4h",
317     "/0s0o/3s3e/1s1l/4s4a",
318     "/0s0o/3s3e/1s1l/4s4h",
319     "/0s0o/3s3e/4s4a",
320     "/0s0o/3s3e/4s4h",
321     "/0s0o/3s3e/4s4a",
322     "/0s0o/3s3e/4s4h",
323     "/0s0o/5s5s",
324     "/0s0o/5s5s/1s1i",
325     "/0s0o/5s5s/1s1l",
326     "/0s0o/5s5s/1s1i/4s4a",
327     "/0s0o/5s5s/1s1i/4s4h",
328     "/0s0o/5s5s/1s1l/4s4a",
329     "/0s0o/5s5s/1s1l/4s4h",
330     "/0s0o/5s5s/4s4a",
331     "/0s0o/5s5s/4s4h",
332     "/0s0o/5s5s/4s4a",
333     "/0s0o/5s5s/4s4h",
334     "/0s0o/1s1i",
335     "/0s0o/1s1l",
336     "/0s0o/1s1i/4s4a",
337     "/0s0o/1s1i/4s4h",
338     "/0s0o/1s1l/4s4a",
339     "/0s0o/1s1l/4s4h",
340     "/0s0o/4s4a",
341     "/0s0o/4s4h",
342     "/0s0o/4s4a",
343     "/0s0o/4s4h",
344     "/2s2a",
345     "/2s2a/3s3e",
346     "/2s2a/3s3e/5s5s",
347     "/2s2a/3s3e/5s5s/1s1i",
348     "/2s2a/3s3e/5s5s/1s1l",
349     "/2s2a/3s3e/5s5s/1s1i/4s4a",
350     "/2s2a/3s3e/5s5s/1s1i/4s4h",
351     "/2s2a/3s3e/5s5s/1s1l/4s4a",
352     "/2s2a/3s3e/5s5s/1s1l/4s4h",
353     "/2s2a/3s3e/5s5s/4s4a",
354     "/2s2a/3s3e/5s5s/4s4h",
355     "/2s2a/3s3e/5s5s/4s4a",
356     "/2s2a/3s3e/5s5s/4s4h",
357     "/2s2a/3s3e/1s1i",
358     "/2s2a/3s3e/1s1l",
359     "/2s2a/3s3e/1s1i/4s4a",
360     "/2s2a/3s3e/1s1i/4s4h",
361     "/2s2a/3s3e/1s1l/4s4a",
362     "/2s2a/3s3e/1s1l/4s4h",
363     "/2s2a/3s3e/4s4a",
364     "/2s2a/3s3e/4s4h",
365     "/2s2a/3s3e/4s4a",
366     "/2s2a/3s3e/4s4h",
367     "/2s2a/5s5s",
368     "/2s2a/5s5s/1s1i",
369     "/2s2a/5s5s/1s1l",
370     "/2s2a/5s5s/1s1i/4s4a",
371     "/2s2a/5s5s/1s1i/4s4h",
372     "/2s2a/5s5s/1s1l/4s4a",
373     "/2s2a/5s5s/1s1l/4s4h",
374     "/2s2a/5s5s/4s4a",
375     "/2s2a/5s5s/4s4h",
376     "/2s2a/5s5s/4s4a",
377     "/2s2a/5s5s/4s4h",
378     "/2s2a/1s1i",
379     "/2s2a/1s1l",
380     "/2s2a/1s1i/4s4a",
381     "/2s2a/1s1i/4s4h",
382     "/2s2a/1s1l/4s4a",
383     "/2s2a/1s1l/4s4h",
384     "/2s2a/4s4a",
385     "/2s2a/4s4h",
386     "/2s2a/4s4a",
387     "/2s2a/4s4h",
388     "/3s3e",
389     "/3s3e/5s5s",
390     "/3s3e/5s5s/1s1i",
391     "/3s3e/5s5s/1s1l",
392     "/3s3e/5s5s/1s1i/4s4a",
393     "/3s3e/5s5s/1s1i/4s4h",
394     "/3s3e/5s5s/1s1l/4s4a",
395     "/3s3e/5s5s/1s1l/4s4h",
396     "/3s3e/5s5s/4s4a",
397     "/3s3e/5s5s/4s4h",
398     "/3s3e/5s5s/4s4a",
399     "/3s3e/5s5s/4s4h",
400     "/3s3e/1s1i",
401     "/3s3e/1s1l",
402     "/3s3e/1s1i/4s4a",
403     "/3s3e/1s1i/4s4h",
404     "/3s3e/1s1l/4s4a",
405     "/3s3e/1s1l/4s4h",
406     "/3s3e/4s4a",
407     "/3s3e/4s4h",
408     "/3s3e/4s4a",
409     "/3s3e/4s4h",
410     "/5s5s",
411     "/5s5s/1s1i",
412     "/5s5s/1s1l",
413     "/5s5s/1s1i/4s4a",
414     "/5s5s/1s1i/4s4h",
415     "/5s5s/1s1l/4s4a",
416     "/5s5s/1s1l/4s4h",
417     "/5s5s/4s4a",
418     "/5s5s/4s4h",
419     "/5s5s/4s4a",
420     "/5s5s/4s4h",
421     "/1s1i",
422     "/1s1l",
423     "/1s1i/4s4a",
424     "/1s1i/4s4h",
425     "/1s1l/4s4a",
426     "/1s1l/4s4h",
427     "/4s4a",
428     "/4s4h",
429     "/4s4a",
430     "/4s4h",
431
432     /* done */
433     (char *) 0
434 };
435
436 static const char *
437 FascistLook(PWDICT *pwp, const char *instring)
438 {
439     int i;
440     size_t pw_len, mindiff;
441     char *ptr;
442     char *jptr;
443     char junk[STRINGSIZE];
444     char *password;
445     char rpassword[STRINGSIZE];
446     char reverse[STRINGSIZE];
447     int32 notfound;
448
449     notfound = PW_WORDS(pwp);
450     /* already truncated if from FascistCheck() */
451     /* but pretend it wasn't ... */
452     strncpy(rpassword, instring, TRUNCSTRINGSIZE);
453     rpassword[TRUNCSTRINGSIZE - 1] = '\0';
454     password = rpassword;
455
456     pw_len = strlen(password); 
457     if (pw_len < 4)
458     {
459         return ("it is WAY too short");
460     }
461
462     if (pw_len < MINLEN)
463     {
464         return ("it is too short");
465     }
466
467     jptr = junk;
468     *jptr = '\0';
469
470     for (i = 0; i < STRINGSIZE && password[i]; i++)
471     {
472         if (!strchr(junk, password[i]))
473         {
474             *(jptr++) = password[i];
475             *jptr = '\0';
476         }
477     }
478
479     /*
480      * mindiff is the number of different characters the password has to
481      * contain.  The original CrackLib always requires five different
482      * characters.  This increases that number up to 8 for passwords longer
483      * than nine characters.
484      */
485     if (pw_len < 2 * MINDIFF)
486     { 
487         mindiff = MINDIFF;
488     } else
489     {
490         if ((pw_len % 2) == 0)
491         {
492             mindiff = (pw_len + 1) / 2;
493         } else
494         {
495             mindiff = pw_len / 2;
496         }
497         mindiff++;
498         if (mindiff > MAXMINDIFF)
499         {
500             mindiff = MAXMINDIFF;
501         }
502     }
503
504     if (strlen(junk) < mindiff)
505     {
506         return ("it does not contain enough DIFFERENT characters");
507     }
508
509     strcpy(password, Lowercase(password));
510
511     Trim(password);
512
513     while (*password && isspace(*password))
514     {
515         password++;
516     }
517
518     if (!*password)
519     {
520         return ("it is all whitespace");
521     }
522
523     i = 0;
524     ptr = password;
525     while (ptr[0] && ptr[1])
526     {
527         if ((ptr[1] == (ptr[0] + 1)) || (ptr[1] == (ptr[0] - 1)))
528         {
529             i++;
530         }
531         ptr++;
532     }
533
534     /* Allow one simple letter increment per three characters. */
535     if (i > (int) strlen(password) / 3)
536     {
537         return ("it is too simplistic/systematic");
538     }
539
540     if (PMatch("aadddddda", password))  /* smirk */
541     {
542         return ("it looks like a National Insurance number.");
543     }
544
545     /* it should be safe to use Mangle with its reliance on STRINGSIZE
546        since password cannot be longer than TRUNCSTRINGSIZE;
547        nonetheless this is not an elegant solution */
548
549     for (i = 0; r_destructors[i]; i++)
550     {
551         char *a;
552
553         if (!(a = Mangle(password, r_destructors[i])))
554         {
555             continue;
556         }
557
558 #ifdef DEBUG
559         printf("%-16s (dict)\n", a);
560 #endif
561
562         if (FindPW(pwp, a) != notfound)
563         {
564             return ("it is based on a dictionary word");
565         }
566     }
567
568     strcpy(reverse, Reverse(password));
569
570     for (i = 0; r_destructors[i]; i++)
571     {
572         char *a;
573
574         if (!(a = Mangle(reverse, r_destructors[i])))
575         {
576             continue;
577         }
578 #ifdef DEBUG
579         printf("%-16s (reversed dict)\n", a);
580 #endif
581         if (FindPW(pwp, a) != notfound)
582         {
583             return ("it is based on a (reversed) dictionary word");
584         }
585     }
586
587     /* Check for a duplicated word. */
588
589     if ((pw_len % 2) == 0)
590     {
591         if (strncmp(password, password + (pw_len / 2), pw_len / 2) == 0)
592         {
593             password[pw_len / 2] = '\0';
594             for (i = 0; r_destructors[i]; i++)
595             {
596                 char *a;
597
598                 if (!(a = Mangle(password, r_destructors[i])))
599                 {
600                     continue;
601                 }
602 #ifdef DEBUG
603                 printf("%-16s (duplicated dict)\n", a);
604 #endif
605                 if (FindPW(pwp, a) != notfound)
606                 {
607                     return ("it is based on a (duplicated) dictionary word");
608                 }
609             }
610         }
611     }
612
613     return ((char *) 0);
614 }
615
616 const char *
617 FascistCheck(const char *password, const char *path)
618 {
619     PWDICT *pwp;
620     char pwtrunced[STRINGSIZE];
621     const char *result;
622
623     /* security problem: assume we may have been given a really long
624        password (buffer attack) and so truncate it to a workable size;
625        try to define workable size as something from which we cannot
626        extend a buffer beyond its limits in the rest of the code */
627
628     strncpy(pwtrunced, password, TRUNCSTRINGSIZE);
629     pwtrunced[TRUNCSTRINGSIZE - 1] = '\0'; /* enforce */
630
631     /* perhaps someone should put something here to check if password
632        is really long and syslog() a message denoting buffer attacks?  */
633
634     if (!(pwp = PWOpen(path, "r")))
635     {
636         perror("PWOpen");
637         return "Cannot check password: dictionary unavailable";
638     }
639
640     result = FascistLook(pwp, pwtrunced);
641     PWClose(pwp);
642     return result;
643 }