/* password.c */ #include #include #include #include #include #include "SConn.h" #include "secstore.h" static Biobuf* openPW(char *id, int mode) { Biobuf *b; int nfn = strlen(SECSTORE_DIR)+strlen(id)+20; char *fn = emalloc(nfn); snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id); b = Bopen(fn, mode); free(fn); return b; } static ulong mtimePW(char *id) { Dir *d; int nfn = strlen(SECSTORE_DIR)+strlen(id)+20; char *fn = emalloc(nfn); ulong mt; snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id); d = dirstat(fn); free(fn); mt = d->mtime; free(d); return mt; } PW * getPW(char *id, int dead_or_alive) { uint now = time(0); Biobuf *bin; PW *pw; char *f1, *f2; // fields 1, 2 = attribute, value if((bin = openPW(id, OREAD)) == 0){ id = "FICTITIOUS"; if((bin = openPW(id, OREAD)) == 0){ werrstr("account does not exist"); 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(dead_or_alive) return pw; // return PW entry for editing, whether currently valid or not if(pw->expire <= now){ werrstr("account expired"); freePW(pw); return nil; } if((pw->status & Enabled) == 0){ werrstr("account disabled"); 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; } int putPW(PW *pw) { Biobuf *bout; char *hexHi; if((bout = openPW(pw->id, OWRITE|OTRUNC)) ==0){ werrstr("can't open PW file"); 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; } void freePW(PW *pw) { if(pw == nil) return; free(pw->id); free(pw->other); mpfree(pw->Hi); free(pw); }