155 lines · 3.4 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ /* password.c */#include <u.h>#include <libc.h>#include <bio.h>#include <mp.h>#include <libsec.h>#include "SConn.h"#include "secstore.h" static Biobuf*openPW(char *id, int mode){	int nfn = strlen(SECSTORE_DIR)+strlen(id)+20;	char *fn;	Biobuf *b; 	if(validatefile(id) == nil || strcmp(id,".") == 0)		return nil;	fn = emalloc(nfn);	snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id);	b = Bopen(fn, mode);	free(fn);	return b;} static ulongmtimePW(char *id){	ulong mt;	char *fn;	Dir *d; 	fn = smprint("%s/who/%s", SECSTORE_DIR, id);	d = dirstat(fn);	mt = (d? d->mtime: 0);	free(d);	free(fn);	return mt;} PW *getPW(char *id, int dead_or_alive){	ulong now = time(0);	char *f1, *f2, *oid;		/* fields 1, 2 = attribute, value */	Biobuf *bin;	PW *pw; 	oid = id;	if((bin = openPW(id, OREAD)) == 0){		id = "FICTITIOUS";		if((bin = openPW(id, OREAD)) == 0){			werrstr("accounts %s and FICTITIOUS do not exist", oid);			return nil;		}	}	pw = emalloc(sizeof *pw);	pw->id = estrdup(id);	pw->status |= Enabled;	while( (f1 = Brdline(bin, '\n')) != 0){		f1[Blinelen(bin)-1] = 0;		for(f2 = f1; *f2 && *f2 != ' ' && *f2 != '\t'; f2++)			;		if(*f2)			for(*f2++ = 0; *f2 && (*f2==' ' || *f2=='\t'); f2++)				;		if(strcmp(f1, "exp") == 0)			pw->expire = strtoul(f2, 0, 10);		else if(strcmp(f1, "DISABLED") == 0)			pw->status &= ~Enabled;		else if(strcmp(f1, "STA") == 0)			pw->status |= STA;		else if(strcmp(f1, "failed") == 0)			pw->failed = strtoul(f2, 0, 10);		else if(strcmp(f1, "other") == 0)			pw->other = estrdup(f2);		else if(strcmp(f1, "PAK-Hi") == 0)			pw->Hi = strtomp(f2, nil, 64, nil);	}	Bterm(bin);	if(pw->Hi == nil){		werrstr("corrupted account file for %s", pw->id);		freePW(pw);		return nil;	}	if(dead_or_alive)		return pw;  /* return for editing, whether valid now or not */	if(pw->expire != 0 && pw->expire <= now){		/* %.28s excludes ctime's newline */		werrstr("account %s expired at %.28s", pw->id,			ctime(pw->expire));		freePW(pw);		return nil;	}	if((pw->status & Enabled) == 0){		werrstr("account %s disabled", pw->id);		freePW(pw);		return nil;	}	if(pw->failed < 10)		return pw;	/* success */	if(now < mtimePW(id)+300){		werrstr("too many failures; try again in five minutes");		freePW(pw);		return nil;	}	pw->failed = 0;	putPW(pw);	/* reset failed-login-counter after five minutes */	return pw;} intputPW(PW *pw){	Biobuf *bout;	char *hexHi; 	if((bout = openPW(pw->id, OWRITE|OTRUNC)) ==0){		werrstr("can't open PW file for %s", pw->id);		return -1;	}	Bprint(bout, "exp	%lud\n", pw->expire);	if(!(pw->status & Enabled))		Bprint(bout, "DISABLED\n");	if(pw->status & STA)		Bprint(bout, "STA\n");	if(pw->failed)		Bprint(bout, "failed\t%d\n", pw->failed);	if(pw->other)		Bprint(bout,"other\t%s\n", pw->other);	hexHi = mptoa(pw->Hi, 64, nil, 0);	Bprint(bout, "PAK-Hi\t%s\n", hexHi);	free(hexHi);	return 0;} voidfreePW(PW *pw){	if(pw == nil)		return;	free(pw->id);	free(pw->other);	mpfree(pw->Hi);	free(pw);}