1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate /*
9*0Sstevel@tonic-gate  * This program is copyright Alec Muffett 1993. The author disclaims all
10*0Sstevel@tonic-gate  * responsibility or liability with respect to it's usage or its effect
11*0Sstevel@tonic-gate  * upon hardware or computer systems, and maintains copyright as set out
12*0Sstevel@tonic-gate  * in the "LICENCE" document which accompanies distributions of Crack v4.0
13*0Sstevel@tonic-gate  * and upwards.
14*0Sstevel@tonic-gate  */
15*0Sstevel@tonic-gate 
16*0Sstevel@tonic-gate #include "packer.h"
17*0Sstevel@tonic-gate 
18*0Sstevel@tonic-gate void
19*0Sstevel@tonic-gate PWRemove(char *path)
20*0Sstevel@tonic-gate {
21*0Sstevel@tonic-gate 	char fname[PATH_MAX];
22*0Sstevel@tonic-gate 
23*0Sstevel@tonic-gate 	(void) snprintf(fname, sizeof (fname), "%s/%s", path,
24*0Sstevel@tonic-gate 	    DICT_DATABASE_PWI);
25*0Sstevel@tonic-gate 	(void) unlink(fname);
26*0Sstevel@tonic-gate 	(void) snprintf(fname, sizeof (fname), "%s/%s", path,
27*0Sstevel@tonic-gate 	    DICT_DATABASE_PWD);
28*0Sstevel@tonic-gate 	(void) unlink(fname);
29*0Sstevel@tonic-gate 	(void) snprintf(fname, sizeof (fname), "%s/%s", path,
30*0Sstevel@tonic-gate 	    DICT_DATABASE_HWM);
31*0Sstevel@tonic-gate 	(void) unlink(fname);
32*0Sstevel@tonic-gate }
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate PWDICT *
35*0Sstevel@tonic-gate PWOpen(char *path, char *mode)
36*0Sstevel@tonic-gate {
37*0Sstevel@tonic-gate 	PWDICT *pdesc;
38*0Sstevel@tonic-gate 	char iname[PATH_MAX];
39*0Sstevel@tonic-gate 	char dname[PATH_MAX];
40*0Sstevel@tonic-gate 	char wname[PATH_MAX];
41*0Sstevel@tonic-gate 	int fd_d;
42*0Sstevel@tonic-gate 	int fd_i;
43*0Sstevel@tonic-gate 	int fd_w;
44*0Sstevel@tonic-gate 	FILE *dfp;
45*0Sstevel@tonic-gate 	FILE *ifp;
46*0Sstevel@tonic-gate 	FILE *wfp;
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate 	if ((pdesc = calloc(1, sizeof (PWDICT))) == NULL)
49*0Sstevel@tonic-gate 		return ((PWDICT *) 0);
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate 	if (pdesc->header.pih_magic == PIH_MAGIC) {
52*0Sstevel@tonic-gate 		return ((PWDICT *) 0);
53*0Sstevel@tonic-gate 	}
54*0Sstevel@tonic-gate 	(void) memset(pdesc, '\0', sizeof (pdesc));
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 	(void) snprintf(iname, sizeof (iname), "%s/%s", path,
57*0Sstevel@tonic-gate 	    DICT_DATABASE_PWI);
58*0Sstevel@tonic-gate 	(void) snprintf(dname, sizeof (dname), "%s/%s", path,
59*0Sstevel@tonic-gate 	    DICT_DATABASE_PWD);
60*0Sstevel@tonic-gate 	(void) snprintf(wname, sizeof (wname), "%s/%s", path,
61*0Sstevel@tonic-gate 	    DICT_DATABASE_HWM);
62*0Sstevel@tonic-gate 
63*0Sstevel@tonic-gate 	if ((fd_d = open(dname, O_RDWR|O_CREAT, 0600)) == -1)
64*0Sstevel@tonic-gate 		syslog(LOG_ERR, "PWopen: can't open %s: %s", dname,
65*0Sstevel@tonic-gate 		    strerror(errno));
66*0Sstevel@tonic-gate 	if ((fd_i = open(iname, O_RDWR|O_CREAT, 0600)) == -1)
67*0Sstevel@tonic-gate 		syslog(LOG_ERR, "PWopen: can't open %s: %s", iname,
68*0Sstevel@tonic-gate 		    strerror(errno));
69*0Sstevel@tonic-gate 	if ((fd_w = open(wname, O_RDWR|O_CREAT, 0600)) == -1)
70*0Sstevel@tonic-gate 		syslog(LOG_ERR, "PWopen: can't open %s: %s", wname,
71*0Sstevel@tonic-gate 		    strerror(errno));
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	if (!(pdesc->dfp = fdopen(fd_d, mode))) {
74*0Sstevel@tonic-gate 		return ((PWDICT *) 0);
75*0Sstevel@tonic-gate 	}
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate 	if (!(pdesc->ifp = fdopen(fd_i, mode))) {
78*0Sstevel@tonic-gate 		(void) fclose(pdesc->dfp);
79*0Sstevel@tonic-gate 		return ((PWDICT *) 0);
80*0Sstevel@tonic-gate 	}
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate 	if (pdesc->wfp = fdopen(fd_w, mode)) {
83*0Sstevel@tonic-gate 		pdesc->flags |= PFOR_USEHWMS;
84*0Sstevel@tonic-gate 	}
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 	ifp = pdesc->ifp;
87*0Sstevel@tonic-gate 	dfp = pdesc->dfp;
88*0Sstevel@tonic-gate 	wfp = pdesc->wfp;
89*0Sstevel@tonic-gate 
90*0Sstevel@tonic-gate 	if (mode[0] == 'w') {
91*0Sstevel@tonic-gate 		pdesc->flags |= PFOR_WRITE;
92*0Sstevel@tonic-gate 		pdesc->header.pih_magic = PIH_MAGIC;
93*0Sstevel@tonic-gate 		pdesc->header.pih_blocklen = NUMWORDS;
94*0Sstevel@tonic-gate 		pdesc->header.pih_numwords = 0;
95*0Sstevel@tonic-gate 
96*0Sstevel@tonic-gate 		(void) fwrite((char *)&(pdesc->header), sizeof (pdesc->header),
97*0Sstevel@tonic-gate 		    1, ifp);
98*0Sstevel@tonic-gate 	} else {
99*0Sstevel@tonic-gate 		pdesc->flags &= ~PFOR_WRITE;
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 		if (!fread((char *)&(pdesc->header), sizeof (pdesc->header),
102*0Sstevel@tonic-gate 		    1, ifp)) {
103*0Sstevel@tonic-gate 			pdesc->header.pih_magic = 0;
104*0Sstevel@tonic-gate 			(void) fclose(ifp);
105*0Sstevel@tonic-gate 			(void) fclose(dfp);
106*0Sstevel@tonic-gate 			return ((PWDICT *) 0);
107*0Sstevel@tonic-gate 		}
108*0Sstevel@tonic-gate 
109*0Sstevel@tonic-gate 		if (pdesc->header.pih_magic != PIH_MAGIC) {
110*0Sstevel@tonic-gate 			pdesc->header.pih_magic = 0;
111*0Sstevel@tonic-gate 			(void) fclose(ifp);
112*0Sstevel@tonic-gate 			(void) fclose(dfp);
113*0Sstevel@tonic-gate 			return ((PWDICT *) 0);
114*0Sstevel@tonic-gate 		}
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate 		if (pdesc->header.pih_blocklen != NUMWORDS) {
117*0Sstevel@tonic-gate 			pdesc->header.pih_magic = 0;
118*0Sstevel@tonic-gate 			(void) fclose(ifp);
119*0Sstevel@tonic-gate 			(void) fclose(dfp);
120*0Sstevel@tonic-gate 			return ((PWDICT *) 0);
121*0Sstevel@tonic-gate 		}
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate 		if (pdesc->flags & PFOR_USEHWMS) {
124*0Sstevel@tonic-gate 			if (fread(pdesc->hwms, 1, sizeof (pdesc->hwms), wfp) !=
125*0Sstevel@tonic-gate 			    sizeof (pdesc->hwms)) {
126*0Sstevel@tonic-gate 				pdesc->flags &= ~PFOR_USEHWMS;
127*0Sstevel@tonic-gate 			}
128*0Sstevel@tonic-gate 		}
129*0Sstevel@tonic-gate 	}
130*0Sstevel@tonic-gate 	return (pdesc);
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate int
134*0Sstevel@tonic-gate PWClose(PWDICT *pwp)
135*0Sstevel@tonic-gate {
136*0Sstevel@tonic-gate 	if (pwp->header.pih_magic != PIH_MAGIC) {
137*0Sstevel@tonic-gate 		return (-1);
138*0Sstevel@tonic-gate 	}
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	if (pwp->flags & PFOR_WRITE) {
141*0Sstevel@tonic-gate 		pwp->flags |= PFOR_FLUSH;
142*0Sstevel@tonic-gate 		(void) PutPW(pwp, (char *)0);	/* flush last index if necess */
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 		if (fseek(pwp->ifp, 0L, 0)) {
145*0Sstevel@tonic-gate 			return (-1);
146*0Sstevel@tonic-gate 		}
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 		if (!fwrite((char *)&pwp->header, sizeof (pwp->header),
149*0Sstevel@tonic-gate 		    1, pwp->ifp)) {
150*0Sstevel@tonic-gate 			return (-1);
151*0Sstevel@tonic-gate 		}
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate 		if (pwp->flags & PFOR_USEHWMS) {
154*0Sstevel@tonic-gate 			int i;
155*0Sstevel@tonic-gate 			for (i = 1; i <= 0xff; i++) {
156*0Sstevel@tonic-gate 				if (!pwp->hwms[i]) {
157*0Sstevel@tonic-gate 					pwp->hwms[i] = pwp->hwms[i-1];
158*0Sstevel@tonic-gate 				}
159*0Sstevel@tonic-gate 			}
160*0Sstevel@tonic-gate 			(void) fwrite(pwp->hwms, 1, sizeof (pwp->hwms),
161*0Sstevel@tonic-gate 			    pwp->wfp);
162*0Sstevel@tonic-gate 		}
163*0Sstevel@tonic-gate 	}
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate 	(void) fclose(pwp->ifp);
166*0Sstevel@tonic-gate 	(void) fclose(pwp->dfp);
167*0Sstevel@tonic-gate 	(void) fclose(pwp->wfp);
168*0Sstevel@tonic-gate 
169*0Sstevel@tonic-gate 	pwp->header.pih_magic = 0;
170*0Sstevel@tonic-gate 
171*0Sstevel@tonic-gate 	free(pwp);
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 	return (0);
174*0Sstevel@tonic-gate }
175*0Sstevel@tonic-gate 
176*0Sstevel@tonic-gate int
177*0Sstevel@tonic-gate PutPW(PWDICT *pwp, char *string)
178*0Sstevel@tonic-gate {
179*0Sstevel@tonic-gate 	if (!(pwp->flags & PFOR_WRITE)) {
180*0Sstevel@tonic-gate 		return (-1);
181*0Sstevel@tonic-gate 	}
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	if (string) {
184*0Sstevel@tonic-gate 		(void) strncpy(pwp->data[pwp->count], string, MAXWORDLEN);
185*0Sstevel@tonic-gate 		pwp->data[pwp->count][MAXWORDLEN - 1] = '\0';
186*0Sstevel@tonic-gate 
187*0Sstevel@tonic-gate 		pwp->hwms[string[0] & 0xff] = pwp->header.pih_numwords;
188*0Sstevel@tonic-gate 
189*0Sstevel@tonic-gate 		++(pwp->count);
190*0Sstevel@tonic-gate 		++(pwp->header.pih_numwords);
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	} else if (!(pwp->flags & PFOR_FLUSH)) {
193*0Sstevel@tonic-gate 		return (-1);
194*0Sstevel@tonic-gate 	}
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	if ((pwp->flags & PFOR_FLUSH) || !(pwp->count % NUMWORDS)) {
197*0Sstevel@tonic-gate 		int i;
198*0Sstevel@tonic-gate 		int32 datum;
199*0Sstevel@tonic-gate 		register char *ostr;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 		datum = (int32) ftell(pwp->dfp);
202*0Sstevel@tonic-gate 
203*0Sstevel@tonic-gate 		(void) fwrite((char *)&datum, sizeof (datum), 1, pwp->ifp);
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 		(void) fputs(pwp->data[0], pwp->dfp);
206*0Sstevel@tonic-gate 		(void) putc(0, pwp->dfp);
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 		ostr = pwp->data[0];
209*0Sstevel@tonic-gate 
210*0Sstevel@tonic-gate 		for (i = 1; i < NUMWORDS; i++) {
211*0Sstevel@tonic-gate 			register int j;
212*0Sstevel@tonic-gate 			register char *nstr;
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate 			nstr = pwp->data[i];
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 			if (nstr[0]) {
217*0Sstevel@tonic-gate 				for (j = 0;
218*0Sstevel@tonic-gate 				    ostr[j] && nstr[j] && (ostr[j] == nstr[j]);
219*0Sstevel@tonic-gate 				    j++);
220*0Sstevel@tonic-gate 					(void) putc(j & 0xff, pwp->dfp);
221*0Sstevel@tonic-gate 				(void) fputs(nstr + j, pwp->dfp);
222*0Sstevel@tonic-gate 			}
223*0Sstevel@tonic-gate 			(void) putc(0, pwp->dfp);
224*0Sstevel@tonic-gate 
225*0Sstevel@tonic-gate 			ostr = nstr;
226*0Sstevel@tonic-gate 		}
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate 	(void) memset(pwp->data, '\0', sizeof (pwp->data));
229*0Sstevel@tonic-gate 	pwp->count = 0;
230*0Sstevel@tonic-gate 	}
231*0Sstevel@tonic-gate 	return (0);
232*0Sstevel@tonic-gate }
233*0Sstevel@tonic-gate 
234*0Sstevel@tonic-gate char *
235*0Sstevel@tonic-gate GetPW(PWDICT *pwp, int32 number)
236*0Sstevel@tonic-gate {
237*0Sstevel@tonic-gate 	int32 datum;
238*0Sstevel@tonic-gate 	register int i;
239*0Sstevel@tonic-gate 	register char *ostr;
240*0Sstevel@tonic-gate 	register char *nstr;
241*0Sstevel@tonic-gate 	register char *bptr;
242*0Sstevel@tonic-gate 	char buffer[NUMWORDS * MAXWORDLEN];
243*0Sstevel@tonic-gate 	static char data[NUMWORDS][MAXWORDLEN];
244*0Sstevel@tonic-gate 	static int32 prevblock = 0xffffffff;
245*0Sstevel@tonic-gate 	int32 thisblock;
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 	thisblock = number / NUMWORDS;
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 	if (prevblock == thisblock) {
250*0Sstevel@tonic-gate 		return (data[number % NUMWORDS]);
251*0Sstevel@tonic-gate 	}
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 	if (fseek(pwp->ifp, sizeof (struct pi_header) +
254*0Sstevel@tonic-gate 	    (thisblock * sizeof (int32)), 0)) {
255*0Sstevel@tonic-gate 		return (NULL);
256*0Sstevel@tonic-gate 	}
257*0Sstevel@tonic-gate 
258*0Sstevel@tonic-gate 	if (!fread((char *)&datum, sizeof (datum), 1, pwp->ifp)) {
259*0Sstevel@tonic-gate 		return (NULL);
260*0Sstevel@tonic-gate 	}
261*0Sstevel@tonic-gate 
262*0Sstevel@tonic-gate 	if (fseek(pwp->dfp, datum, 0)) {
263*0Sstevel@tonic-gate 		return (NULL);
264*0Sstevel@tonic-gate 	}
265*0Sstevel@tonic-gate 
266*0Sstevel@tonic-gate 	if (!fread(buffer, 1, sizeof (buffer), pwp->dfp)) {
267*0Sstevel@tonic-gate 		return (NULL);
268*0Sstevel@tonic-gate 	}
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	prevblock = thisblock;
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	bptr = buffer;
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	for (ostr = data[0]; *(ostr++) = *(bptr++); /* nothing */);
275*0Sstevel@tonic-gate 
276*0Sstevel@tonic-gate 	ostr = data[0];
277*0Sstevel@tonic-gate 
278*0Sstevel@tonic-gate 	for (i = 1; i < NUMWORDS; i++) {
279*0Sstevel@tonic-gate 		nstr = data[i];
280*0Sstevel@tonic-gate 		(void) strcpy(nstr, ostr);
281*0Sstevel@tonic-gate 		ostr = nstr + *(bptr++);
282*0Sstevel@tonic-gate 		while (*(ostr++) = *(bptr++));
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 		ostr = nstr;
285*0Sstevel@tonic-gate 	}
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 	return (data[number % NUMWORDS]);
288*0Sstevel@tonic-gate }
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate int32
291*0Sstevel@tonic-gate FindPW(PWDICT *pwp, char *string)
292*0Sstevel@tonic-gate {
293*0Sstevel@tonic-gate 	int lwm;
294*0Sstevel@tonic-gate 	int hwm;
295*0Sstevel@tonic-gate 	int idx;
296*0Sstevel@tonic-gate 
297*0Sstevel@tonic-gate 	if (string == NULL)
298*0Sstevel@tonic-gate 		return (PW_WORDS(pwp));
299*0Sstevel@tonic-gate 
300*0Sstevel@tonic-gate 	if (pwp->flags & PFOR_USEHWMS) {
301*0Sstevel@tonic-gate 		idx = string[0] & 0xff;
302*0Sstevel@tonic-gate 		lwm = idx ? pwp->hwms[idx - 1] : 0;
303*0Sstevel@tonic-gate 		hwm = pwp->hwms[idx];
304*0Sstevel@tonic-gate 	} else {
305*0Sstevel@tonic-gate 		lwm = 0;
306*0Sstevel@tonic-gate 		hwm = PW_WORDS(pwp) - 1;
307*0Sstevel@tonic-gate 	}
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 	for (;;) {
310*0Sstevel@tonic-gate 		int cmp;
311*0Sstevel@tonic-gate 		int pivot;
312*0Sstevel@tonic-gate 		char *this;
313*0Sstevel@tonic-gate 
314*0Sstevel@tonic-gate 		pivot = lwm + ((hwm+1)-lwm)/2;
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate 		if (feof(pwp->ifp) && feof(pwp->dfp) && feof(pwp->wfp))
317*0Sstevel@tonic-gate 			break;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 		if ((this = GetPW(pwp, pivot)) == NULL)
320*0Sstevel@tonic-gate 			break;
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 		cmp = strcmp(string, this);		/* INLINE ? */
323*0Sstevel@tonic-gate 
324*0Sstevel@tonic-gate 		if (cmp == 0)
325*0Sstevel@tonic-gate 			return (pivot);
326*0Sstevel@tonic-gate 		else if (cmp < 0)
327*0Sstevel@tonic-gate 			hwm = pivot-1;
328*0Sstevel@tonic-gate 		else
329*0Sstevel@tonic-gate 			lwm = pivot+1;
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate 		if (lwm > hwm)	/* searched all; not found */
332*0Sstevel@tonic-gate 			break;
333*0Sstevel@tonic-gate 	}
334*0Sstevel@tonic-gate 
335*0Sstevel@tonic-gate 	/* not found */
336*0Sstevel@tonic-gate 	return (PW_WORDS(pwp));
337*0Sstevel@tonic-gate }
338