diff options
Diffstat (limited to 'src/cmd/secstore/password.c')
-rw-r--r-- | src/cmd/secstore/password.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/cmd/secstore/password.c b/src/cmd/secstore/password.c new file mode 100644 index 00000000..aacadd9b --- /dev/null +++ b/src/cmd/secstore/password.c @@ -0,0 +1,136 @@ +/* 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); +} + |