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#include "packer.h"
10#include <string.h>
11#include <arpa/inet.h>
12
13static char __unused vers_id[] = "packlib.c : v2.3p2 Alec Muffett 18 May 1993";
14
15static void PWDictHeaderToHostOrder (struct pi_header* header)
16{
17    header->pih_magic = ntohl (header->pih_magic);
18    header->pih_numwords = ntohl (header->pih_numwords);
19    header->pih_blocklen = ntohs (header->pih_blocklen);
20}
21
22
23
24static void PWDictHeaderToNetworkOrder (struct pi_header* header)
25{
26    header->pih_magic = htonl (header->pih_magic);
27    header->pih_numwords = htonl (header->pih_numwords);
28    header->pih_blocklen = htons (header->pih_blocklen);
29}
30
31
32
33static void PWHwmsToHostOrder (int32 *array, size_t max)
34{
35	size_t i;
36	for (i = 0; i < max; ++i)
37	{
38		array[i] = ntohl (array[i]);
39	}
40}
41
42
43
44static void PWHwmnToNetworkOrder (int32 *array, size_t max)
45{
46	size_t i;
47	for (i = 0; i < max; ++i)
48	{
49		array[i] = htonl (array[i]);
50	}
51}
52
53
54
55extern int PutPW(PWDICT *pwp, char *string);
56
57PWDICT *
58PWOpen(prefix, mode)
59    char *prefix;
60    char *mode;
61{
62//    int32 i;
63    static PWDICT pdesc;
64    char iname[STRINGSIZE];
65    char dname[STRINGSIZE];
66    char wname[STRINGSIZE];
67//    char buffer[STRINGSIZE];
68    FILE *dfp;
69    FILE *ifp;
70    FILE *wfp;
71
72    if (pdesc.header.pih_magic == PIH_MAGIC)
73    {
74	fprintf(stderr, "%s: another dictionary already open\n", prefix);
75	return ((PWDICT *) 0);
76    }
77
78    memset(&pdesc, '\0', sizeof(pdesc));
79
80    snprintf(iname, sizeof(iname), "%s.pwi", prefix);
81    snprintf(dname, sizeof(dname), "%s.pwd", prefix);
82    snprintf(wname, sizeof(wname), "%s.hwm", prefix);
83
84    if (!(pdesc.dfp = fopen(dname, mode)))
85    {
86	perror(dname);
87	return ((PWDICT *) 0);
88    }
89
90    if (!(pdesc.ifp = fopen(iname, mode)))
91    {
92	fclose(pdesc.dfp);
93	perror(iname);
94	return ((PWDICT *) 0);
95    }
96
97    if (pdesc.wfp = fopen(wname, mode))
98    {
99	pdesc.flags |= PFOR_USEHWMS;
100    }
101
102    ifp = pdesc.ifp;
103    dfp = pdesc.dfp;
104    wfp = pdesc.wfp;
105
106    if (mode[0] == 'w')
107    {
108	pdesc.flags |= PFOR_WRITE;
109	pdesc.header.pih_magic = PIH_MAGIC;
110	pdesc.header.pih_blocklen = NUMWORDS;
111	pdesc.header.pih_numwords = 0;
112
113	// convert to "network" byte order
114	PWDictHeaderToNetworkOrder (&pdesc.header);
115	fwrite((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp);
116	PWDictHeaderToHostOrder (&pdesc.header);
117    } else
118    {
119	pdesc.flags &= ~PFOR_WRITE;
120
121	if (!fread((char *) &pdesc.header, sizeof(pdesc.header), 1, ifp))
122	{
123	    fprintf(stderr, "%s: error reading header\n", prefix);
124
125	    pdesc.header.pih_magic = 0;
126	    fclose(ifp);
127	    fclose(dfp);
128	    return ((PWDICT *) 0);
129	}
130
131	PWDictHeaderToHostOrder (&pdesc.header);
132
133	if (pdesc.header.pih_magic != PIH_MAGIC)
134	{
135	    fprintf(stderr, "%s: magic mismatch\n", prefix);
136
137	    pdesc.header.pih_magic = 0;
138	    fclose(ifp);
139	    fclose(dfp);
140	    return ((PWDICT *) 0);
141	}
142
143	if (pdesc.header.pih_blocklen != NUMWORDS)
144	{
145	    fprintf(stderr, "%s: size mismatch\n", prefix);
146
147	    pdesc.header.pih_magic = 0;
148	    fclose(ifp);
149	    fclose(dfp);
150	    return ((PWDICT *) 0);
151	}
152
153	if (pdesc.flags & PFOR_USEHWMS)
154	{
155	    if (fread(pdesc.hwms, 1, sizeof(pdesc.hwms), wfp) != sizeof(pdesc.hwms))
156	    {
157		pdesc.flags &= ~PFOR_USEHWMS;
158	    }
159
160		PWHwmsToHostOrder (pdesc.hwms, sizeof (pdesc.hwms) / sizeof (int32));
161	}
162    }
163
164    return (&pdesc);
165}
166
167int
168PWClose(pwp)
169    PWDICT *pwp;
170{
171	int result;
172
173    if (pwp->header.pih_magic != PIH_MAGIC)
174    {
175	fprintf(stderr, "PWClose: close magic mismatch\n");
176	return (-1);
177    }
178
179    if (pwp->flags & PFOR_WRITE)
180    {
181	pwp->flags |= PFOR_FLUSH;
182	PutPW(pwp, (char *) 0);	/* flush last index if necess */
183
184	if (fseek(pwp->ifp, 0L, 0))
185	{
186	    fprintf(stderr, "index magic fseek failed\n");
187	    return (-1);
188	}
189
190	PWDictHeaderToNetworkOrder (&pwp->header);
191	result = fwrite((char *) &pwp->header, sizeof(pwp->header), 1, pwp->ifp);
192	PWDictHeaderToHostOrder (&pwp->header);
193
194	if (!result)
195	{
196	    fprintf(stderr, "index magic fwrite failed\n");
197	    return (-1);
198	}
199
200	if (pwp->flags & PFOR_USEHWMS)
201	{
202	    int i;
203	    for (i=1; i<=0xff; i++)
204	    {
205	    	if (!pwp->hwms[i])
206	    	{
207	    	    pwp->hwms[i] = pwp->hwms[i-1];
208	    	}
209#ifdef DEBUG
210	    	printf("hwm[%02x] = %d\n", i, pwp->hwms[i]);
211#endif
212	    }
213
214		PWHwmnToNetworkOrder (pwp->hwms, sizeof (pwp->hwms) / sizeof (int32));
215	    fwrite(pwp->hwms, 1, sizeof(pwp->hwms), pwp->wfp);
216		PWHwmsToHostOrder (pwp->hwms, sizeof (pwp->hwms) / sizeof (int32));
217	}
218    }
219
220    fclose(pwp->ifp);
221    fclose(pwp->dfp);
222
223    pwp->header.pih_magic = 0;
224
225    return (0);
226}
227
228int
229PutPW(pwp, string)
230    PWDICT *pwp;
231    char *string;
232{
233    if (!(pwp->flags & PFOR_WRITE))
234    {
235	return (-1);
236    }
237
238    if (string)
239    {
240	strlcpy(pwp->data[pwp->count], string, MAXWORDLEN);
241
242	pwp->hwms[string[0] & 0xff]= pwp->header.pih_numwords;
243
244	++(pwp->count);
245	++(pwp->header.pih_numwords);
246
247    } else if (!(pwp->flags & PFOR_FLUSH))
248    {
249	return (-1);
250    }
251
252    if ((pwp->flags & PFOR_FLUSH) || !(pwp->count % NUMWORDS))
253    {
254	int i;
255	int32 datum;
256	register char *ostr;
257
258	datum = htonl ((int32) ftell(pwp->dfp));
259	fwrite((char *) &datum, sizeof(datum), 1, pwp->ifp);
260
261	fputs(pwp->data[0], pwp->dfp);
262	putc(0, pwp->dfp);
263
264	ostr = pwp->data[0];
265
266	for (i = 1; i < NUMWORDS; i++)
267	{
268	    register int j;
269	    register char *nstr;
270	    nstr = pwp->data[i];
271
272	    if (nstr[0])
273	    {
274		for (j = 0; ostr[j] && nstr[j] && (ostr[j] == nstr[j]); j++);
275		putc(j & 0xff, pwp->dfp);
276		fputs(nstr + j, pwp->dfp);
277	    }
278	    putc(0, pwp->dfp);
279
280	    ostr = nstr;
281	}
282
283	memset(pwp->data, '\0', sizeof(pwp->data));
284	pwp->count = 0;
285    }
286    return (0);
287}
288
289char *
290GetPW(pwp, number)
291    PWDICT *pwp;
292    int32 number;
293{
294    int32 datum;
295    register int i;
296    register char *ostr;
297    register char *nstr;
298    register char *bptr;
299    char buffer[NUMWORDS * MAXWORDLEN];
300    static char data[NUMWORDS][MAXWORDLEN];
301    static int32 prevblock = 0xffffffff;
302    int32 thisblock;
303
304    thisblock = number / NUMWORDS;
305
306    if (prevblock == thisblock)
307    {
308	return (data[number % NUMWORDS]);
309    }
310
311    if (fseek(pwp->ifp, sizeof(struct pi_header) + (thisblock * sizeof(int32)), 0))
312    {
313	perror("(index fseek failed)");
314	return ((char *) 0);
315    }
316
317    if (!fread((char *) &datum, sizeof(datum), 1, pwp->ifp))
318    {
319	perror("(index fread failed)");
320	return ((char *) 0);
321    }
322
323	datum = ntohl (datum);
324
325    if (fseek(pwp->dfp, datum, 0))
326    {
327	perror("(data fseek failed)");
328	return ((char *) 0);
329    }
330
331    if (!fread(buffer, 1, sizeof(buffer), pwp->dfp))
332    {
333	perror("(data fread failed)");
334	return ((char *) 0);
335    }
336
337    prevblock = thisblock;
338
339    bptr = buffer;
340
341    for (ostr = data[0]; *(ostr++) = *(bptr++); /* nothing */ );
342
343    ostr = data[0];
344
345    for (i = 1; i < NUMWORDS; i++)
346    {
347	nstr = data[i];
348	strlcpy(nstr, ostr, MAXWORDLEN);
349
350	ostr = nstr + *(bptr++);
351	while (*(ostr++) = *(bptr++));
352
353	ostr = nstr;
354    }
355
356    return (data[number % NUMWORDS]);
357}
358
359int32
360FindPW(pwp, string)
361    PWDICT *pwp;
362    char *string;
363{
364    register int32 lwm;
365    register int32 hwm;
366    register int32 middle;
367    register char *this;
368    int idx;
369
370    if (pwp->flags & PFOR_USEHWMS)
371    {
372	idx = string[0] & 0xff;
373    	lwm = idx ? pwp->hwms[idx - 1] : 0;
374    	hwm = pwp->hwms[idx];
375    } else
376    {
377    	lwm = 0;
378    	hwm = PW_WORDS(pwp) - 1;
379    }
380
381#ifdef DEBUG
382    printf("---- %lu, %lu ----\n", lwm, hwm);
383#endif
384
385    for (;;)
386    {
387	int cmp;
388
389#ifdef DEBUG
390	printf("%lu, %lu\n", lwm, hwm);
391#endif
392
393	middle = lwm + ((hwm - lwm + 1) / 2);
394
395	if (middle == hwm)
396	{
397	    break;
398	}
399
400	this = GetPW(pwp, middle);
401	cmp = strcmp(string, this);		/* INLINE ? */
402
403	if (cmp < 0)
404	{
405	    hwm = middle;
406	} else if (cmp > 0)
407	{
408	    lwm = middle;
409	} else
410	{
411	    return (middle);
412	}
413    }
414
415    return (PW_WORDS(pwp));
416}
417