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