19a747e4fSDavid du Colombier /* password.c */
29a747e4fSDavid du Colombier #include <u.h>
39a747e4fSDavid du Colombier #include <libc.h>
49a747e4fSDavid du Colombier #include <bio.h>
59a747e4fSDavid du Colombier #include <mp.h>
69a747e4fSDavid du Colombier #include <libsec.h>
79a747e4fSDavid du Colombier #include "SConn.h"
89a747e4fSDavid du Colombier #include "secstore.h"
99a747e4fSDavid du Colombier
109a747e4fSDavid du Colombier static Biobuf*
openPW(char * id,int mode)119a747e4fSDavid du Colombier openPW(char *id, int mode)
129a747e4fSDavid du Colombier {
139a747e4fSDavid du Colombier int nfn = strlen(SECSTORE_DIR)+strlen(id)+20;
1411c9ee8bSDavid du Colombier char *fn;
15*7e18f042SDavid du Colombier Biobuf *b;
169a747e4fSDavid du Colombier
1711c9ee8bSDavid du Colombier if(validatefile(id) == nil || strcmp(id,".") == 0)
1811c9ee8bSDavid du Colombier return nil;
1911c9ee8bSDavid du Colombier fn = emalloc(nfn);
209a747e4fSDavid du Colombier snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id);
219a747e4fSDavid du Colombier b = Bopen(fn, mode);
229a747e4fSDavid du Colombier free(fn);
239a747e4fSDavid du Colombier return b;
249a747e4fSDavid du Colombier }
259a747e4fSDavid du Colombier
269a747e4fSDavid du Colombier static ulong
mtimePW(char * id)279a747e4fSDavid du Colombier mtimePW(char *id)
289a747e4fSDavid du Colombier {
299a747e4fSDavid du Colombier ulong mt;
30*7e18f042SDavid du Colombier char *fn;
31*7e18f042SDavid du Colombier Dir *d;
329a747e4fSDavid du Colombier
33*7e18f042SDavid du Colombier fn = smprint("%s/who/%s", SECSTORE_DIR, id);
349a747e4fSDavid du Colombier d = dirstat(fn);
35*7e18f042SDavid du Colombier mt = (d? d->mtime: 0);
369a747e4fSDavid du Colombier free(d);
37*7e18f042SDavid du Colombier free(fn);
389a747e4fSDavid du Colombier return mt;
399a747e4fSDavid du Colombier }
409a747e4fSDavid du Colombier
419a747e4fSDavid du Colombier PW *
getPW(char * id,int dead_or_alive)42369036d9SDavid du Colombier getPW(char *id, int dead_or_alive)
439a747e4fSDavid du Colombier {
44*7e18f042SDavid du Colombier ulong now = time(0);
45*7e18f042SDavid du Colombier char *f1, *f2, *oid; /* fields 1, 2 = attribute, value */
469a747e4fSDavid du Colombier Biobuf *bin;
479a747e4fSDavid du Colombier PW *pw;
489a747e4fSDavid du Colombier
49*7e18f042SDavid du Colombier oid = id;
509a747e4fSDavid du Colombier if((bin = openPW(id, OREAD)) == 0){
51be0c1e85SDavid du Colombier id = "FICTITIOUS";
52be0c1e85SDavid du Colombier if((bin = openPW(id, OREAD)) == 0){
53*7e18f042SDavid du Colombier werrstr("accounts %s and FICTITIOUS do not exist", oid);
549a747e4fSDavid du Colombier return nil;
559a747e4fSDavid du Colombier }
56be0c1e85SDavid du Colombier }
57*7e18f042SDavid du Colombier pw = emalloc(sizeof *pw);
589a747e4fSDavid du Colombier pw->id = estrdup(id);
599a747e4fSDavid du Colombier pw->status |= Enabled;
609a747e4fSDavid du Colombier while( (f1 = Brdline(bin, '\n')) != 0){
619a747e4fSDavid du Colombier f1[Blinelen(bin)-1] = 0;
62*7e18f042SDavid du Colombier for(f2 = f1; *f2 && *f2 != ' ' && *f2 != '\t'; f2++)
63*7e18f042SDavid du Colombier ;
649a747e4fSDavid du Colombier if(*f2)
65*7e18f042SDavid du Colombier for(*f2++ = 0; *f2 && (*f2==' ' || *f2=='\t'); f2++)
66*7e18f042SDavid du Colombier ;
67*7e18f042SDavid du Colombier if(strcmp(f1, "exp") == 0)
689a747e4fSDavid du Colombier pw->expire = strtoul(f2, 0, 10);
69*7e18f042SDavid du Colombier else if(strcmp(f1, "DISABLED") == 0)
709a747e4fSDavid du Colombier pw->status &= ~Enabled;
71*7e18f042SDavid du Colombier else if(strcmp(f1, "STA") == 0)
729a747e4fSDavid du Colombier pw->status |= STA;
73*7e18f042SDavid du Colombier else if(strcmp(f1, "failed") == 0)
749a747e4fSDavid du Colombier pw->failed = strtoul(f2, 0, 10);
75*7e18f042SDavid du Colombier else if(strcmp(f1, "other") == 0)
769a747e4fSDavid du Colombier pw->other = estrdup(f2);
77*7e18f042SDavid du Colombier else if(strcmp(f1, "PAK-Hi") == 0)
789a747e4fSDavid du Colombier pw->Hi = strtomp(f2, nil, 64, nil);
799a747e4fSDavid du Colombier }
809a747e4fSDavid du Colombier Bterm(bin);
8111c9ee8bSDavid du Colombier if(pw->Hi == nil){
82*7e18f042SDavid du Colombier werrstr("corrupted account file for %s", pw->id);
8311c9ee8bSDavid du Colombier freePW(pw);
8411c9ee8bSDavid du Colombier return nil;
8511c9ee8bSDavid du Colombier }
86369036d9SDavid du Colombier if(dead_or_alive)
87*7e18f042SDavid du Colombier return pw; /* return for editing, whether valid now or not */
88*7e18f042SDavid du Colombier if(pw->expire != 0 && pw->expire <= now){
89*7e18f042SDavid du Colombier /* %.28s excludes ctime's newline */
90*7e18f042SDavid du Colombier werrstr("account %s expired at %.28s", pw->id,
91*7e18f042SDavid du Colombier ctime(pw->expire));
929a747e4fSDavid du Colombier freePW(pw);
939a747e4fSDavid du Colombier return nil;
949a747e4fSDavid du Colombier }
95369036d9SDavid du Colombier if((pw->status & Enabled) == 0){
96*7e18f042SDavid du Colombier werrstr("account %s disabled", pw->id);
979a747e4fSDavid du Colombier freePW(pw);
989a747e4fSDavid du Colombier return nil;
999a747e4fSDavid du Colombier }
1009a747e4fSDavid du Colombier if(pw->failed < 10)
101*7e18f042SDavid du Colombier return pw; /* success */
1029a747e4fSDavid du Colombier if(now < mtimePW(id)+300){
1035d459b5aSDavid du Colombier werrstr("too many failures; try again in five minutes");
1049a747e4fSDavid du Colombier freePW(pw);
1059a747e4fSDavid du Colombier return nil;
1069a747e4fSDavid du Colombier }
1079a747e4fSDavid du Colombier pw->failed = 0;
108*7e18f042SDavid du Colombier putPW(pw); /* reset failed-login-counter after five minutes */
1099a747e4fSDavid du Colombier return pw;
1109a747e4fSDavid du Colombier }
1119a747e4fSDavid du Colombier
1129a747e4fSDavid du Colombier int
putPW(PW * pw)1139a747e4fSDavid du Colombier putPW(PW *pw)
1149a747e4fSDavid du Colombier {
1159a747e4fSDavid du Colombier Biobuf *bout;
1169a747e4fSDavid du Colombier char *hexHi;
1179a747e4fSDavid du Colombier
1189a747e4fSDavid du Colombier if((bout = openPW(pw->id, OWRITE|OTRUNC)) ==0){
119*7e18f042SDavid du Colombier werrstr("can't open PW file for %s", pw->id);
1209a747e4fSDavid du Colombier return -1;
1219a747e4fSDavid du Colombier }
1229a747e4fSDavid du Colombier Bprint(bout, "exp %lud\n", pw->expire);
1239a747e4fSDavid du Colombier if(!(pw->status & Enabled))
1249a747e4fSDavid du Colombier Bprint(bout, "DISABLED\n");
1259a747e4fSDavid du Colombier if(pw->status & STA)
1269a747e4fSDavid du Colombier Bprint(bout, "STA\n");
1279a747e4fSDavid du Colombier if(pw->failed)
1289a747e4fSDavid du Colombier Bprint(bout, "failed\t%d\n", pw->failed);
1299a747e4fSDavid du Colombier if(pw->other)
1309a747e4fSDavid du Colombier Bprint(bout,"other\t%s\n", pw->other);
1319a747e4fSDavid du Colombier hexHi = mptoa(pw->Hi, 64, nil, 0);
1329a747e4fSDavid du Colombier Bprint(bout, "PAK-Hi\t%s\n", hexHi);
1339a747e4fSDavid du Colombier free(hexHi);
1349a747e4fSDavid du Colombier return 0;
1359a747e4fSDavid du Colombier }
1369a747e4fSDavid du Colombier
1379a747e4fSDavid du Colombier void
freePW(PW * pw)1389a747e4fSDavid du Colombier freePW(PW *pw)
1399a747e4fSDavid du Colombier {
1409a747e4fSDavid du Colombier if(pw == nil)
1419a747e4fSDavid du Colombier return;
1429a747e4fSDavid du Colombier free(pw->id);
1439a747e4fSDavid du Colombier free(pw->other);
1449a747e4fSDavid du Colombier mpfree(pw->Hi);
1459a747e4fSDavid du Colombier free(pw);
1469a747e4fSDavid du Colombier }
147