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#include "packer.h"
11#include <sys/types.h>
12#include <unistd.h>
13#include <stdlib.h>
14#include <pwd.h>
15#include <string.h>
16
17static char __unused vers_id[] = "fascist.c : v2.3p3 Alec Muffett 14 dec 1997";
18
19#define ISSKIP(x) (isspace(x) || ispunct(x))
20
21#define MINDIFF 5
22#define MINLEN 6
23#define MAXSTEP 4
24
25#undef DEBUG
26#undef DEBUG2
27
28extern char *Reverse();
29extern char *Lowercase();
30extern char *Trim(char *string);
31extern int PMatch(char *control, char *string);
32extern int32 FindPW(PWDICT *pwp, char *string);
33extern int PWClose(PWDICT *pwp);
34
35static char *r_destructors[] = {
36    ":",                        /* noop - must do this to test raw word. */
37
38#ifdef DEBUG2
39    (char *) 0,
40#endif
41
42    "[",                        /* trimming leading/trailing junk */
43    "]",
44    "[[",
45    "]]",
46    "[[[",
47    "]]]",
48
49    "/?p@?p",                   /* purging out punctuation/symbols/junk */
50    "/?s@?s",
51    "/?X@?X",
52
53    /* attempt reverse engineering of password strings */
54
55    "/$s$s",
56    "/$s$s/0s0o",
57    "/$s$s/0s0o/2s2a",
58    "/$s$s/0s0o/2s2a/3s3e",
59    "/$s$s/0s0o/2s2a/3s3e/5s5s",
60    "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i",
61    "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l",
62    "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i/4s4a",
63    "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1i/4s4h",
64    "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l/4s4a",
65    "/$s$s/0s0o/2s2a/3s3e/5s5s/1s1l/4s4h",
66    "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4a",
67    "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4h",
68    "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4a",
69    "/$s$s/0s0o/2s2a/3s3e/5s5s/4s4h",
70    "/$s$s/0s0o/2s2a/3s3e/1s1i",
71    "/$s$s/0s0o/2s2a/3s3e/1s1l",
72    "/$s$s/0s0o/2s2a/3s3e/1s1i/4s4a",
73    "/$s$s/0s0o/2s2a/3s3e/1s1i/4s4h",
74    "/$s$s/0s0o/2s2a/3s3e/1s1l/4s4a",
75    "/$s$s/0s0o/2s2a/3s3e/1s1l/4s4h",
76    "/$s$s/0s0o/2s2a/3s3e/4s4a",
77    "/$s$s/0s0o/2s2a/3s3e/4s4h",
78    "/$s$s/0s0o/2s2a/3s3e/4s4a",
79    "/$s$s/0s0o/2s2a/3s3e/4s4h",
80    "/$s$s/0s0o/2s2a/5s5s",
81    "/$s$s/0s0o/2s2a/5s5s/1s1i",
82    "/$s$s/0s0o/2s2a/5s5s/1s1l",
83    "/$s$s/0s0o/2s2a/5s5s/1s1i/4s4a",
84    "/$s$s/0s0o/2s2a/5s5s/1s1i/4s4h",
85    "/$s$s/0s0o/2s2a/5s5s/1s1l/4s4a",
86    "/$s$s/0s0o/2s2a/5s5s/1s1l/4s4h",
87    "/$s$s/0s0o/2s2a/5s5s/4s4a",
88    "/$s$s/0s0o/2s2a/5s5s/4s4h",
89    "/$s$s/0s0o/2s2a/5s5s/4s4a",
90    "/$s$s/0s0o/2s2a/5s5s/4s4h",
91    "/$s$s/0s0o/2s2a/1s1i",
92    "/$s$s/0s0o/2s2a/1s1l",
93    "/$s$s/0s0o/2s2a/1s1i/4s4a",
94    "/$s$s/0s0o/2s2a/1s1i/4s4h",
95    "/$s$s/0s0o/2s2a/1s1l/4s4a",
96    "/$s$s/0s0o/2s2a/1s1l/4s4h",
97    "/$s$s/0s0o/2s2a/4s4a",
98    "/$s$s/0s0o/2s2a/4s4h",
99    "/$s$s/0s0o/2s2a/4s4a",
100    "/$s$s/0s0o/2s2a/4s4h",
101    "/$s$s/0s0o/3s3e",
102    "/$s$s/0s0o/3s3e/5s5s",
103    "/$s$s/0s0o/3s3e/5s5s/1s1i",
104    "/$s$s/0s0o/3s3e/5s5s/1s1l",
105    "/$s$s/0s0o/3s3e/5s5s/1s1i/4s4a",
106    "/$s$s/0s0o/3s3e/5s5s/1s1i/4s4h",
107    "/$s$s/0s0o/3s3e/5s5s/1s1l/4s4a",
108    "/$s$s/0s0o/3s3e/5s5s/1s1l/4s4h",
109    "/$s$s/0s0o/3s3e/5s5s/4s4a",
110    "/$s$s/0s0o/3s3e/5s5s/4s4h",
111    "/$s$s/0s0o/3s3e/5s5s/4s4a",
112    "/$s$s/0s0o/3s3e/5s5s/4s4h",
113    "/$s$s/0s0o/3s3e/1s1i",
114    "/$s$s/0s0o/3s3e/1s1l",
115    "/$s$s/0s0o/3s3e/1s1i/4s4a",
116    "/$s$s/0s0o/3s3e/1s1i/4s4h",
117    "/$s$s/0s0o/3s3e/1s1l/4s4a",
118    "/$s$s/0s0o/3s3e/1s1l/4s4h",
119    "/$s$s/0s0o/3s3e/4s4a",
120    "/$s$s/0s0o/3s3e/4s4h",
121    "/$s$s/0s0o/3s3e/4s4a",
122    "/$s$s/0s0o/3s3e/4s4h",
123    "/$s$s/0s0o/5s5s",
124    "/$s$s/0s0o/5s5s/1s1i",
125    "/$s$s/0s0o/5s5s/1s1l",
126    "/$s$s/0s0o/5s5s/1s1i/4s4a",
127    "/$s$s/0s0o/5s5s/1s1i/4s4h",
128    "/$s$s/0s0o/5s5s/1s1l/4s4a",
129    "/$s$s/0s0o/5s5s/1s1l/4s4h",
130    "/$s$s/0s0o/5s5s/4s4a",
131    "/$s$s/0s0o/5s5s/4s4h",
132    "/$s$s/0s0o/5s5s/4s4a",
133    "/$s$s/0s0o/5s5s/4s4h",
134    "/$s$s/0s0o/1s1i",
135    "/$s$s/0s0o/1s1l",
136    "/$s$s/0s0o/1s1i/4s4a",
137    "/$s$s/0s0o/1s1i/4s4h",
138    "/$s$s/0s0o/1s1l/4s4a",
139    "/$s$s/0s0o/1s1l/4s4h",
140    "/$s$s/0s0o/4s4a",
141    "/$s$s/0s0o/4s4h",
142    "/$s$s/0s0o/4s4a",
143    "/$s$s/0s0o/4s4h",
144    "/$s$s/2s2a",
145    "/$s$s/2s2a/3s3e",
146    "/$s$s/2s2a/3s3e/5s5s",
147    "/$s$s/2s2a/3s3e/5s5s/1s1i",
148    "/$s$s/2s2a/3s3e/5s5s/1s1l",
149    "/$s$s/2s2a/3s3e/5s5s/1s1i/4s4a",
150    "/$s$s/2s2a/3s3e/5s5s/1s1i/4s4h",
151    "/$s$s/2s2a/3s3e/5s5s/1s1l/4s4a",
152    "/$s$s/2s2a/3s3e/5s5s/1s1l/4s4h",
153    "/$s$s/2s2a/3s3e/5s5s/4s4a",
154    "/$s$s/2s2a/3s3e/5s5s/4s4h",
155    "/$s$s/2s2a/3s3e/5s5s/4s4a",
156    "/$s$s/2s2a/3s3e/5s5s/4s4h",
157    "/$s$s/2s2a/3s3e/1s1i",
158    "/$s$s/2s2a/3s3e/1s1l",
159    "/$s$s/2s2a/3s3e/1s1i/4s4a",
160    "/$s$s/2s2a/3s3e/1s1i/4s4h",
161    "/$s$s/2s2a/3s3e/1s1l/4s4a",
162    "/$s$s/2s2a/3s3e/1s1l/4s4h",
163    "/$s$s/2s2a/3s3e/4s4a",
164    "/$s$s/2s2a/3s3e/4s4h",
165    "/$s$s/2s2a/3s3e/4s4a",
166    "/$s$s/2s2a/3s3e/4s4h",
167    "/$s$s/2s2a/5s5s",
168    "/$s$s/2s2a/5s5s/1s1i",
169    "/$s$s/2s2a/5s5s/1s1l",
170    "/$s$s/2s2a/5s5s/1s1i/4s4a",
171    "/$s$s/2s2a/5s5s/1s1i/4s4h",
172    "/$s$s/2s2a/5s5s/1s1l/4s4a",
173    "/$s$s/2s2a/5s5s/1s1l/4s4h",
174    "/$s$s/2s2a/5s5s/4s4a",
175    "/$s$s/2s2a/5s5s/4s4h",
176    "/$s$s/2s2a/5s5s/4s4a",
177    "/$s$s/2s2a/5s5s/4s4h",
178    "/$s$s/2s2a/1s1i",
179    "/$s$s/2s2a/1s1l",
180    "/$s$s/2s2a/1s1i/4s4a",
181    "/$s$s/2s2a/1s1i/4s4h",
182    "/$s$s/2s2a/1s1l/4s4a",
183    "/$s$s/2s2a/1s1l/4s4h",
184    "/$s$s/2s2a/4s4a",
185    "/$s$s/2s2a/4s4h",
186    "/$s$s/2s2a/4s4a",
187    "/$s$s/2s2a/4s4h",
188    "/$s$s/3s3e",
189    "/$s$s/3s3e/5s5s",
190    "/$s$s/3s3e/5s5s/1s1i",
191    "/$s$s/3s3e/5s5s/1s1l",
192    "/$s$s/3s3e/5s5s/1s1i/4s4a",
193    "/$s$s/3s3e/5s5s/1s1i/4s4h",
194    "/$s$s/3s3e/5s5s/1s1l/4s4a",
195    "/$s$s/3s3e/5s5s/1s1l/4s4h",
196    "/$s$s/3s3e/5s5s/4s4a",
197    "/$s$s/3s3e/5s5s/4s4h",
198    "/$s$s/3s3e/5s5s/4s4a",
199    "/$s$s/3s3e/5s5s/4s4h",
200    "/$s$s/3s3e/1s1i",
201    "/$s$s/3s3e/1s1l",
202    "/$s$s/3s3e/1s1i/4s4a",
203    "/$s$s/3s3e/1s1i/4s4h",
204    "/$s$s/3s3e/1s1l/4s4a",
205    "/$s$s/3s3e/1s1l/4s4h",
206    "/$s$s/3s3e/4s4a",
207    "/$s$s/3s3e/4s4h",
208    "/$s$s/3s3e/4s4a",
209    "/$s$s/3s3e/4s4h",
210    "/$s$s/5s5s",
211    "/$s$s/5s5s/1s1i",
212    "/$s$s/5s5s/1s1l",
213    "/$s$s/5s5s/1s1i/4s4a",
214    "/$s$s/5s5s/1s1i/4s4h",
215    "/$s$s/5s5s/1s1l/4s4a",
216    "/$s$s/5s5s/1s1l/4s4h",
217    "/$s$s/5s5s/4s4a",
218    "/$s$s/5s5s/4s4h",
219    "/$s$s/5s5s/4s4a",
220    "/$s$s/5s5s/4s4h",
221    "/$s$s/1s1i",
222    "/$s$s/1s1l",
223    "/$s$s/1s1i/4s4a",
224    "/$s$s/1s1i/4s4h",
225    "/$s$s/1s1l/4s4a",
226    "/$s$s/1s1l/4s4h",
227    "/$s$s/4s4a",
228    "/$s$s/4s4h",
229    "/$s$s/4s4a",
230    "/$s$s/4s4h",
231    "/0s0o",
232    "/0s0o/2s2a",
233    "/0s0o/2s2a/3s3e",
234    "/0s0o/2s2a/3s3e/5s5s",
235    "/0s0o/2s2a/3s3e/5s5s/1s1i",
236    "/0s0o/2s2a/3s3e/5s5s/1s1l",
237    "/0s0o/2s2a/3s3e/5s5s/1s1i/4s4a",
238    "/0s0o/2s2a/3s3e/5s5s/1s1i/4s4h",
239    "/0s0o/2s2a/3s3e/5s5s/1s1l/4s4a",
240    "/0s0o/2s2a/3s3e/5s5s/1s1l/4s4h",
241    "/0s0o/2s2a/3s3e/5s5s/4s4a",
242    "/0s0o/2s2a/3s3e/5s5s/4s4h",
243    "/0s0o/2s2a/3s3e/5s5s/4s4a",
244    "/0s0o/2s2a/3s3e/5s5s/4s4h",
245    "/0s0o/2s2a/3s3e/1s1i",
246    "/0s0o/2s2a/3s3e/1s1l",
247    "/0s0o/2s2a/3s3e/1s1i/4s4a",
248    "/0s0o/2s2a/3s3e/1s1i/4s4h",
249    "/0s0o/2s2a/3s3e/1s1l/4s4a",
250    "/0s0o/2s2a/3s3e/1s1l/4s4h",
251    "/0s0o/2s2a/3s3e/4s4a",
252    "/0s0o/2s2a/3s3e/4s4h",
253    "/0s0o/2s2a/3s3e/4s4a",
254    "/0s0o/2s2a/3s3e/4s4h",
255    "/0s0o/2s2a/5s5s",
256    "/0s0o/2s2a/5s5s/1s1i",
257    "/0s0o/2s2a/5s5s/1s1l",
258    "/0s0o/2s2a/5s5s/1s1i/4s4a",
259    "/0s0o/2s2a/5s5s/1s1i/4s4h",
260    "/0s0o/2s2a/5s5s/1s1l/4s4a",
261    "/0s0o/2s2a/5s5s/1s1l/4s4h",
262    "/0s0o/2s2a/5s5s/4s4a",
263    "/0s0o/2s2a/5s5s/4s4h",
264    "/0s0o/2s2a/5s5s/4s4a",
265    "/0s0o/2s2a/5s5s/4s4h",
266    "/0s0o/2s2a/1s1i",
267    "/0s0o/2s2a/1s1l",
268    "/0s0o/2s2a/1s1i/4s4a",
269    "/0s0o/2s2a/1s1i/4s4h",
270    "/0s0o/2s2a/1s1l/4s4a",
271    "/0s0o/2s2a/1s1l/4s4h",
272    "/0s0o/2s2a/4s4a",
273    "/0s0o/2s2a/4s4h",
274    "/0s0o/2s2a/4s4a",
275    "/0s0o/2s2a/4s4h",
276    "/0s0o/3s3e",
277    "/0s0o/3s3e/5s5s",
278    "/0s0o/3s3e/5s5s/1s1i",
279    "/0s0o/3s3e/5s5s/1s1l",
280    "/0s0o/3s3e/5s5s/1s1i/4s4a",
281    "/0s0o/3s3e/5s5s/1s1i/4s4h",
282    "/0s0o/3s3e/5s5s/1s1l/4s4a",
283    "/0s0o/3s3e/5s5s/1s1l/4s4h",
284    "/0s0o/3s3e/5s5s/4s4a",
285    "/0s0o/3s3e/5s5s/4s4h",
286    "/0s0o/3s3e/5s5s/4s4a",
287    "/0s0o/3s3e/5s5s/4s4h",
288    "/0s0o/3s3e/1s1i",
289    "/0s0o/3s3e/1s1l",
290    "/0s0o/3s3e/1s1i/4s4a",
291    "/0s0o/3s3e/1s1i/4s4h",
292    "/0s0o/3s3e/1s1l/4s4a",
293    "/0s0o/3s3e/1s1l/4s4h",
294    "/0s0o/3s3e/4s4a",
295    "/0s0o/3s3e/4s4h",
296    "/0s0o/3s3e/4s4a",
297    "/0s0o/3s3e/4s4h",
298    "/0s0o/5s5s",
299    "/0s0o/5s5s/1s1i",
300    "/0s0o/5s5s/1s1l",
301    "/0s0o/5s5s/1s1i/4s4a",
302    "/0s0o/5s5s/1s1i/4s4h",
303    "/0s0o/5s5s/1s1l/4s4a",
304    "/0s0o/5s5s/1s1l/4s4h",
305    "/0s0o/5s5s/4s4a",
306    "/0s0o/5s5s/4s4h",
307    "/0s0o/5s5s/4s4a",
308    "/0s0o/5s5s/4s4h",
309    "/0s0o/1s1i",
310    "/0s0o/1s1l",
311    "/0s0o/1s1i/4s4a",
312    "/0s0o/1s1i/4s4h",
313    "/0s0o/1s1l/4s4a",
314    "/0s0o/1s1l/4s4h",
315    "/0s0o/4s4a",
316    "/0s0o/4s4h",
317    "/0s0o/4s4a",
318    "/0s0o/4s4h",
319    "/2s2a",
320    "/2s2a/3s3e",
321    "/2s2a/3s3e/5s5s",
322    "/2s2a/3s3e/5s5s/1s1i",
323    "/2s2a/3s3e/5s5s/1s1l",
324    "/2s2a/3s3e/5s5s/1s1i/4s4a",
325    "/2s2a/3s3e/5s5s/1s1i/4s4h",
326    "/2s2a/3s3e/5s5s/1s1l/4s4a",
327    "/2s2a/3s3e/5s5s/1s1l/4s4h",
328    "/2s2a/3s3e/5s5s/4s4a",
329    "/2s2a/3s3e/5s5s/4s4h",
330    "/2s2a/3s3e/5s5s/4s4a",
331    "/2s2a/3s3e/5s5s/4s4h",
332    "/2s2a/3s3e/1s1i",
333    "/2s2a/3s3e/1s1l",
334    "/2s2a/3s3e/1s1i/4s4a",
335    "/2s2a/3s3e/1s1i/4s4h",
336    "/2s2a/3s3e/1s1l/4s4a",
337    "/2s2a/3s3e/1s1l/4s4h",
338    "/2s2a/3s3e/4s4a",
339    "/2s2a/3s3e/4s4h",
340    "/2s2a/3s3e/4s4a",
341    "/2s2a/3s3e/4s4h",
342    "/2s2a/5s5s",
343    "/2s2a/5s5s/1s1i",
344    "/2s2a/5s5s/1s1l",
345    "/2s2a/5s5s/1s1i/4s4a",
346    "/2s2a/5s5s/1s1i/4s4h",
347    "/2s2a/5s5s/1s1l/4s4a",
348    "/2s2a/5s5s/1s1l/4s4h",
349    "/2s2a/5s5s/4s4a",
350    "/2s2a/5s5s/4s4h",
351    "/2s2a/5s5s/4s4a",
352    "/2s2a/5s5s/4s4h",
353    "/2s2a/1s1i",
354    "/2s2a/1s1l",
355    "/2s2a/1s1i/4s4a",
356    "/2s2a/1s1i/4s4h",
357    "/2s2a/1s1l/4s4a",
358    "/2s2a/1s1l/4s4h",
359    "/2s2a/4s4a",
360    "/2s2a/4s4h",
361    "/2s2a/4s4a",
362    "/2s2a/4s4h",
363    "/3s3e",
364    "/3s3e/5s5s",
365    "/3s3e/5s5s/1s1i",
366    "/3s3e/5s5s/1s1l",
367    "/3s3e/5s5s/1s1i/4s4a",
368    "/3s3e/5s5s/1s1i/4s4h",
369    "/3s3e/5s5s/1s1l/4s4a",
370    "/3s3e/5s5s/1s1l/4s4h",
371    "/3s3e/5s5s/4s4a",
372    "/3s3e/5s5s/4s4h",
373    "/3s3e/5s5s/4s4a",
374    "/3s3e/5s5s/4s4h",
375    "/3s3e/1s1i",
376    "/3s3e/1s1l",
377    "/3s3e/1s1i/4s4a",
378    "/3s3e/1s1i/4s4h",
379    "/3s3e/1s1l/4s4a",
380    "/3s3e/1s1l/4s4h",
381    "/3s3e/4s4a",
382    "/3s3e/4s4h",
383    "/3s3e/4s4a",
384    "/3s3e/4s4h",
385    "/5s5s",
386    "/5s5s/1s1i",
387    "/5s5s/1s1l",
388    "/5s5s/1s1i/4s4a",
389    "/5s5s/1s1i/4s4h",
390    "/5s5s/1s1l/4s4a",
391    "/5s5s/1s1l/4s4h",
392    "/5s5s/4s4a",
393    "/5s5s/4s4h",
394    "/5s5s/4s4a",
395    "/5s5s/4s4h",
396    "/1s1i",
397    "/1s1l",
398    "/1s1i/4s4a",
399    "/1s1i/4s4h",
400    "/1s1l/4s4a",
401    "/1s1l/4s4h",
402    "/4s4a",
403    "/4s4h",
404    "/4s4a",
405    "/4s4h",
406
407    /* done */
408    (char *) 0
409};
410
411static char *r_constructors[] = {
412    ":",
413
414#ifdef DEBUG2
415    (char *) 0,
416#endif
417
418    "r",
419    "d",
420    "f",
421    "dr",
422    "fr",
423    "rf",
424    (char *) 0
425};
426
427int
428GTry(rawtext, password)
429    char *rawtext;
430    char *password;
431{
432    int i;
433    int len;
434    char *mp;
435
436    /* use destructors to turn password into rawtext */
437    /* note use of Reverse() to save duplicating all rules */
438
439    len = strlen(password);
440
441    for (i = 0; r_destructors[i]; i++)
442    {
443	if (!(mp = Mangle(password, r_destructors[i])))
444	{
445	    continue;
446	}
447
448#ifdef DEBUG
449	printf("%-16s = %-16s (destruct %s)\n", mp, rawtext, r_destructors[i]);
450#endif
451
452	if (!strncmp(mp, rawtext, len))
453	{
454	    return (1);
455	}
456
457#ifdef DEBUG
458	printf("%-16s = %-16s (destruct %s reversed)\n", Reverse(mp), rawtext, r_destructors[i]);
459#endif
460
461	if (!strncmp(Reverse(mp), rawtext, len))
462	{
463	    return (1);
464	}
465    }
466
467    for (i = 0; r_constructors[i]; i++)
468    {
469	if (!(mp = Mangle(rawtext, r_constructors[i])))
470	{
471	    continue;
472	}
473
474#ifdef DEBUG
475	printf("%-16s = %-16s (construct %s)\n", mp, password, r_constructors[i]);
476#endif
477
478	if (!strncmp(mp, password, len))
479	{
480	    return (1);
481	}
482    }
483
484    return (0);
485}
486
487char *
488FascistGecos(password, uid)
489    char *password;
490    int uid;
491{
492    int i;
493    int j;
494    int wc;
495    char *ptr;
496    int gwords;
497    struct passwd *pwp;
498    char gbuffer[STRINGSIZE];
499    char tbuffer[STRINGSIZE];
500    char *uwords[STRINGSIZE];
501    char longbuffer[STRINGSIZE * 2];
502
503    if (!(pwp = getpwuid(uid)))
504    {
505	return ("you are not registered in the password file");
506    }
507
508    /* lets get really paranoid and assume a dangerously long gecos entry */
509
510    strlcpy(tbuffer, pwp->pw_name, sizeof(tbuffer));
511    if (GTry(tbuffer, password))
512    {
513	return ("it is based on your username");
514    }
515
516    /* it never used to be that you got passwd strings > 1024 chars, but now... */
517
518    strlcpy(tbuffer, pwp->pw_gecos, sizeof(tbuffer));
519    strlcpy(gbuffer, Lowercase(tbuffer), sizeof(gbuffer));
520
521    wc = 0;
522    ptr = gbuffer;
523    gwords = 0;
524    uwords[0] = (char *)0;
525
526    while (*ptr)
527    {
528	while (*ptr && ISSKIP(*ptr))
529	{
530	    ptr++;
531	}
532
533	if (ptr != gbuffer)
534	{
535	    ptr[-1] = '\0';
536	}
537
538	gwords++;
539	uwords[wc++] = ptr;
540
541	if (wc == STRINGSIZE)
542	{
543	    uwords[--wc] = (char *) 0;  /* to hell with it */
544	    break;
545	} else
546	{
547	    uwords[wc] = (char *) 0;
548	}
549
550	while (*ptr && !ISSKIP(*ptr))
551	{
552	    ptr++;
553	}
554
555	if (*ptr)
556	{
557	    *(ptr++) = '\0';
558	}
559    }
560
561#ifdef DEBUG
562    for (i = 0; uwords[i]; i++)
563    {
564	printf("gecosword %s\n", uwords[i]);
565    }
566#endif
567
568    for (i = 0; uwords[i]; i++)
569    {
570	if (GTry(uwords[i], password))
571	{
572	    return ("it is based upon your password entry");
573	}
574    }
575
576    /* since uwords are taken from gbuffer, no uword can be longer than gbuffer */
577
578    for (j = 1; (j < gwords) && uwords[j]; j++)
579    {
580	for (i = 0; i < j; i++)
581	{
582	    strlcpy(longbuffer, uwords[i], sizeof(longbuffer));
583	    strlcat(longbuffer, uwords[j], sizeof(longbuffer));
584
585	    if (GTry(longbuffer, password))
586	    {
587		return ("it is derived from your password entry");
588	    }
589
590	    strlcpy(longbuffer, uwords[j], sizeof(longbuffer));
591	    strlcat(longbuffer, uwords[i], sizeof(longbuffer));
592
593	    if (GTry(longbuffer, password))
594	    {
595		return ("it's derived from your password entry");
596	    }
597
598	    longbuffer[0] = uwords[i][0];
599	    longbuffer[1] = '\0';
600	    strlcat(longbuffer, uwords[j], sizeof(longbuffer));
601
602	    if (GTry(longbuffer, password))
603	    {
604		return ("it is derivable from your password entry");
605	    }
606
607	    longbuffer[0] = uwords[j][0];
608	    longbuffer[1] = '\0';
609	    strlcat(longbuffer, uwords[i], sizeof(longbuffer));
610
611	    if (GTry(longbuffer, password))
612	    {
613		return ("it's derivable from your password entry");
614	    }
615	}
616    }
617
618    return ((char *) 0);
619}
620
621char *
622FascistLook(pwp, instring)
623    PWDICT *pwp;
624    char *instring;
625{
626    int i;
627    char *ptr;
628    char *jptr;
629    char junk[STRINGSIZE];
630    char *password;
631    char rpassword[STRINGSIZE];
632    int32 notfound;
633
634    notfound = PW_WORDS(pwp);
635    /* already truncated if from FascistCheck() */
636    /* but pretend it wasn't ... */
637    strlcpy(rpassword, instring, TRUNCSTRINGSIZE);
638    password = rpassword;
639
640    if (strlen(password) < 4)
641    {
642	return ("it's WAY too short");
643    }
644
645    if (strlen(password) < MINLEN)
646    {
647	return ("it is too short");
648    }
649
650    jptr = junk;
651    *jptr = '\0';
652
653    for (i = 0; i < STRINGSIZE && password[i]; i++)
654    {
655	if (!strchr(junk, password[i]))
656	{
657	    *(jptr++) = password[i];
658	    *jptr = '\0';
659	}
660    }
661
662    if (strlen(junk) < MINDIFF)
663    {
664	return ("it does not contain enough DIFFERENT characters");
665    }
666
667    strlcpy(password, Lowercase(password), STRINGSIZE);
668
669    Trim(password);
670
671    while (*password && isspace(*password))
672    {
673	password++;
674    }
675
676    if (!*password)
677    {
678	return ("it is all whitespace");
679    }
680
681    i = 0;
682    ptr = password;
683    while (ptr[0] && ptr[1])
684    {
685	if ((ptr[1] == (ptr[0] + 1)) || (ptr[1] == (ptr[0] - 1)))
686	{
687	    i++;
688	}
689	ptr++;
690    }
691
692    if (i > MAXSTEP)
693    {
694	return ("it is too simplistic/systematic");
695    }
696
697    if (PMatch("aadddddda", password))  /* smirk */
698    {
699	return ("it looks like a National Insurance number.");
700    }
701
702    if (ptr = FascistGecos(password, getuid()))
703    {
704	return (ptr);
705    }
706
707    /* it should be safe to use Mangle with its reliance on STRINGSIZE
708       since password cannot be longer than TRUNCSTRINGSIZE;
709       nonetheless this is not an elegant solution */
710
711    for (i = 0; r_destructors[i]; i++)
712    {
713	char *a;
714
715	if (!(a = Mangle(password, r_destructors[i])))
716	{
717	    continue;
718	}
719
720#ifdef DEBUG
721	printf("%-16s (dict)\n", a);
722#endif
723
724	if (FindPW(pwp, a) != notfound)
725	{
726	    return ("it is based on a dictionary word");
727	}
728    }
729
730    strlcpy(password, Reverse(password), STRINGSIZE);
731
732    for (i = 0; r_destructors[i]; i++)
733    {
734	char *a;
735
736	if (!(a = Mangle(password, r_destructors[i])))
737	{
738	    continue;
739	}
740#ifdef DEBUG
741	printf("%-16s (reversed dict)\n", a);
742#endif
743	if (FindPW(pwp, a) != notfound)
744	{
745	    return ("it is based on a (reversed) dictionary word");
746	}
747    }
748
749    return ((char *) 0);
750}
751
752char *
753FascistCheck(password, path)
754    char *password;
755    char *path;
756{
757    static char lastpath[STRINGSIZE];
758    static PWDICT *pwp;
759    char pwtrunced[STRINGSIZE];
760
761    /* security problem: assume we may have been given a really long
762       password (buffer attack) and so truncate it to a workable size;
763       try to define workable size as something from which we cannot
764       extend a buffer beyond its limits in the rest of the code */
765
766    strlcpy(pwtrunced, password, TRUNCSTRINGSIZE);
767
768    /* perhaps someone should put something here to check if password
769       is really long and syslog() a message denoting buffer attacks?  */
770
771    if (pwp && strncmp(lastpath, path, sizeof(lastpath)))
772    {
773	PWClose(pwp);
774	pwp = (PWDICT *)0;
775    }
776
777    if (!pwp)
778    {
779	if (!(pwp = PWOpen(path, "r")))
780	{
781	    perror("PWOpen");
782	    exit(-1);
783	}
784	strlcpy(lastpath, path, sizeof(lastpath));
785    }
786
787    return (FascistLook(pwp, pwtrunced));
788}
789