OpenSolaris_b135/lib/pam_modules/authtok_check/packlib.c

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

/*
 * This program is copyright Alec Muffett 1993. The author disclaims all
 * responsibility or liability with respect to it's usage or its effect
 * upon hardware or computer systems, and maintains copyright as set out
 * in the "LICENCE" document which accompanies distributions of Crack v4.0
 * and upwards.
 */

#include "packer.h"

void
PWRemove(char *path)
{
	char fname[PATH_MAX];

	(void) snprintf(fname, sizeof (fname), "%s/%s", path,
	    DICT_DATABASE_PWI);
	(void) unlink(fname);
	(void) snprintf(fname, sizeof (fname), "%s/%s", path,
	    DICT_DATABASE_PWD);
	(void) unlink(fname);
	(void) snprintf(fname, sizeof (fname), "%s/%s", path,
	    DICT_DATABASE_HWM);
	(void) unlink(fname);
}

PWDICT *
PWOpen(char *path, char *mode)
{
	PWDICT *pdesc;
	char iname[PATH_MAX];
	char dname[PATH_MAX];
	char wname[PATH_MAX];
	int fd_d;
	int fd_i;
	int fd_w;
	FILE *dfp;
	FILE *ifp;
	FILE *wfp;

	if ((pdesc = calloc(1, sizeof (PWDICT))) == NULL)
		return ((PWDICT *) 0);

	if (pdesc->header.pih_magic == PIH_MAGIC) {
		return ((PWDICT *) 0);
	}
	(void) memset(pdesc, '\0', sizeof (pdesc));

	(void) snprintf(iname, sizeof (iname), "%s/%s", path,
	    DICT_DATABASE_PWI);
	(void) snprintf(dname, sizeof (dname), "%s/%s", path,
	    DICT_DATABASE_PWD);
	(void) snprintf(wname, sizeof (wname), "%s/%s", path,
	    DICT_DATABASE_HWM);

	if ((fd_d = open(dname, O_RDWR|O_CREAT, 0600)) == -1)
		syslog(LOG_ERR, "PWopen: can't open %s: %s", dname,
		    strerror(errno));
	if ((fd_i = open(iname, O_RDWR|O_CREAT, 0600)) == -1)
		syslog(LOG_ERR, "PWopen: can't open %s: %s", iname,
		    strerror(errno));
	if ((fd_w = open(wname, O_RDWR|O_CREAT, 0600)) == -1)
		syslog(LOG_ERR, "PWopen: can't open %s: %s", wname,
		    strerror(errno));

	if (!(pdesc->dfp = fdopen(fd_d, mode))) {
		return ((PWDICT *) 0);
	}

	if (!(pdesc->ifp = fdopen(fd_i, mode))) {
		(void) fclose(pdesc->dfp);
		return ((PWDICT *) 0);
	}

	if (pdesc->wfp = fdopen(fd_w, mode)) {
		pdesc->flags |= PFOR_USEHWMS;
	}

	ifp = pdesc->ifp;
	dfp = pdesc->dfp;
	wfp = pdesc->wfp;

	if (mode[0] == 'w') {
		pdesc->flags |= PFOR_WRITE;
		pdesc->header.pih_magic = PIH_MAGIC;
		pdesc->header.pih_blocklen = NUMWORDS;
		pdesc->header.pih_numwords = 0;

		(void) fwrite((char *)&(pdesc->header), sizeof (pdesc->header),
		    1, ifp);
	} else {
		pdesc->flags &= ~PFOR_WRITE;

		if (!fread((char *)&(pdesc->header), sizeof (pdesc->header),
		    1, ifp)) {
			pdesc->header.pih_magic = 0;
			(void) fclose(ifp);
			(void) fclose(dfp);
			return ((PWDICT *) 0);
		}

		if (pdesc->header.pih_magic != PIH_MAGIC) {
			pdesc->header.pih_magic = 0;
			(void) fclose(ifp);
			(void) fclose(dfp);
			return ((PWDICT *) 0);
		}

		if (pdesc->header.pih_blocklen != NUMWORDS) {
			pdesc->header.pih_magic = 0;
			(void) fclose(ifp);
			(void) fclose(dfp);
			return ((PWDICT *) 0);
		}

		if (pdesc->flags & PFOR_USEHWMS) {
			if (fread(pdesc->hwms, 1, sizeof (pdesc->hwms), wfp) !=
			    sizeof (pdesc->hwms)) {
				pdesc->flags &= ~PFOR_USEHWMS;
			}
		}
	}
	return (pdesc);
}

int
PWClose(PWDICT *pwp)
{
	if (pwp->header.pih_magic != PIH_MAGIC) {
		return (-1);
	}

	if (pwp->flags & PFOR_WRITE) {
		pwp->flags |= PFOR_FLUSH;
		(void) PutPW(pwp, (char *)0);	/* flush last index if necess */

		if (fseek(pwp->ifp, 0L, 0)) {
			return (-1);
		}

		if (!fwrite((char *)&pwp->header, sizeof (pwp->header),
		    1, pwp->ifp)) {
			return (-1);
		}

		if (pwp->flags & PFOR_USEHWMS) {
			int i;
			for (i = 1; i <= 0xff; i++) {
				if (!pwp->hwms[i]) {
					pwp->hwms[i] = pwp->hwms[i-1];
				}
			}
			(void) fwrite(pwp->hwms, 1, sizeof (pwp->hwms),
			    pwp->wfp);
		}
	}

	(void) fclose(pwp->ifp);
	(void) fclose(pwp->dfp);
	(void) fclose(pwp->wfp);

	pwp->header.pih_magic = 0;

	free(pwp);

	return (0);
}

int
PutPW(PWDICT *pwp, char *string)
{
	if (!(pwp->flags & PFOR_WRITE)) {
		return (-1);
	}

	if (string) {
		(void) strncpy(pwp->data[pwp->count], string, MAXWORDLEN);
		pwp->data[pwp->count][MAXWORDLEN - 1] = '\0';

		pwp->hwms[string[0] & 0xff] = pwp->header.pih_numwords;

		++(pwp->count);
		++(pwp->header.pih_numwords);

	} else if (!(pwp->flags & PFOR_FLUSH)) {
		return (-1);
	}

	if ((pwp->flags & PFOR_FLUSH) || !(pwp->count % NUMWORDS)) {
		int i;
		uint32_t datum;
		register char *ostr;

		datum = (uint32_t)ftell(pwp->dfp);

		(void) fwrite((char *)&datum, sizeof (datum), 1, pwp->ifp);

		(void) fputs(pwp->data[0], pwp->dfp);
		(void) putc(0, pwp->dfp);

		ostr = pwp->data[0];

		for (i = 1; i < NUMWORDS; i++) {
			register int j;
			register char *nstr;

			nstr = pwp->data[i];

			if (nstr[0]) {
				for (j = 0; ostr[j] && nstr[j] &&
				    (ostr[j] == nstr[j]); j++)
					;
				(void) putc(j & 0xff, pwp->dfp);
				(void) fputs(nstr + j, pwp->dfp);
			}
			(void) putc(0, pwp->dfp);

			ostr = nstr;
		}

	(void) memset(pwp->data, '\0', sizeof (pwp->data));
	pwp->count = 0;
	}
	return (0);
}

char *
GetPW(PWDICT *pwp, uint32_t number)
{
	uint32_t datum;
	register int i;
	register char *ostr;
	register char *nstr;
	register char *bptr;
	char buffer[NUMWORDS * MAXWORDLEN];
	static char data[NUMWORDS][MAXWORDLEN];
	static uint32_t prevblock = 0xffffffff;
	uint32_t thisblock;

	thisblock = number / NUMWORDS;

	if (prevblock == thisblock) {
		return (data[number % NUMWORDS]);
	}

	if (fseek(pwp->ifp, sizeof (struct pi_header) +
	    (thisblock * sizeof (uint32_t)), 0)) {
		return (NULL);
	}

	if (!fread((char *)&datum, sizeof (datum), 1, pwp->ifp)) {
		return (NULL);
	}

	if (fseek(pwp->dfp, datum, 0)) {
		return (NULL);
	}

	if (!fread(buffer, 1, sizeof (buffer), pwp->dfp)) {
		return (NULL);
	}

	prevblock = thisblock;

	bptr = buffer;

	for (ostr = data[0]; *(ostr++) = *(bptr++); /* nothing */)
		;

	ostr = data[0];

	for (i = 1; i < NUMWORDS; i++) {
		nstr = data[i];
		(void) strcpy(nstr, ostr);
		ostr = nstr + *(bptr++);
		while (*(ostr++) = *(bptr++))
			;

		ostr = nstr;
	}

	return (data[number % NUMWORDS]);
}

uint32_t
FindPW(PWDICT *pwp, char *string)
{
	int lwm;
	int hwm;
	int idx;

	if (string == NULL)
		return (PW_WORDS(pwp));

	if (pwp->flags & PFOR_USEHWMS) {
		idx = string[0] & 0xff;
		lwm = idx ? pwp->hwms[idx - 1] : 0;
		hwm = pwp->hwms[idx];
	} else {
		lwm = 0;
		hwm = PW_WORDS(pwp) - 1;
	}

	for (;;) {
		int cmp;
		int pivot;
		char *this;

		pivot = lwm + ((hwm+1)-lwm)/2;

		if (feof(pwp->ifp) && feof(pwp->dfp) && feof(pwp->wfp))
			break;

		if ((this = GetPW(pwp, pivot)) == NULL)
			break;

		cmp = strcmp(string, this);		/* INLINE ? */

		if (cmp == 0)
			return (pivot);
		else if (cmp < 0)
			hwm = pivot-1;
		else
			lwm = pivot+1;

		if (lwm > hwm)	/* searched all; not found */
			break;
	}

	/* not found */
	return (PW_WORDS(pwp));
}