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