|  | /* 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) | 
|  | { | 
|  | 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); | 
|  | } | 
|  |  |