password.c (2781B)
1 /* password.c */ 2 #include <u.h> 3 #include <libc.h> 4 #include <bio.h> 5 #include <mp.h> 6 #include <libsec.h> 7 #include "SConn.h" 8 #include "secstore.h" 9 10 static Biobuf* 11 openPW(char *id, int mode) 12 { 13 Biobuf *b; 14 int nfn = strlen(SECSTORE_DIR)+strlen(id)+20; 15 char *fn = emalloc(nfn); 16 17 snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id); 18 b = Bopen(fn, mode); 19 free(fn); 20 return b; 21 } 22 23 static ulong 24 mtimePW(char *id) 25 { 26 Dir *d; 27 int nfn = strlen(SECSTORE_DIR)+strlen(id)+20; 28 char *fn = emalloc(nfn); 29 ulong mt; 30 31 snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id); 32 d = dirstat(fn); 33 free(fn); 34 mt = d->mtime; 35 free(d); 36 return mt; 37 } 38 39 PW * 40 getPW(char *id, int dead_or_alive) 41 { 42 uint now = time(0); 43 Biobuf *bin; 44 PW *pw; 45 char *f1, *f2; /* fields 1, 2 = attribute, value */ 46 47 if((bin = openPW(id, OREAD)) == 0){ 48 id = "FICTITIOUS"; 49 if((bin = openPW(id, OREAD)) == 0){ 50 werrstr("account does not exist"); 51 return nil; 52 } 53 } 54 pw = emalloc(sizeof(*pw)); 55 pw->id = estrdup(id); 56 pw->status |= Enabled; 57 while( (f1 = Brdline(bin, '\n')) != 0){ 58 f1[Blinelen(bin)-1] = 0; 59 for(f2 = f1; *f2 && (*f2!=' ') && (*f2!='\t'); f2++){} 60 if(*f2) 61 for(*f2++ = 0; *f2 && (*f2==' ' || *f2=='\t'); f2++){} 62 if(strcmp(f1, "exp") == 0){ 63 pw->expire = strtoul(f2, 0, 10); 64 }else if(strcmp(f1, "DISABLED") == 0){ 65 pw->status &= ~Enabled; 66 }else if(strcmp(f1, "STA") == 0){ 67 pw->status |= STA; 68 }else if(strcmp(f1, "failed") == 0){ 69 pw->failed = strtoul(f2, 0, 10); 70 }else if(strcmp(f1, "other") == 0){ 71 pw->other = estrdup(f2); 72 }else if(strcmp(f1, "PAK-Hi") == 0){ 73 pw->Hi = strtomp(f2, nil, 64, nil); 74 } 75 } 76 Bterm(bin); 77 if(dead_or_alive) 78 return pw; /* return PW entry for editing, whether currently valid or not */ 79 if(pw->expire <= now){ 80 werrstr("account expired"); 81 freePW(pw); 82 return nil; 83 } 84 if((pw->status & Enabled) == 0){ 85 werrstr("account disabled"); 86 freePW(pw); 87 return nil; 88 } 89 if(pw->failed < 10) 90 return pw; /* success */ 91 if(now < mtimePW(id)+300){ 92 werrstr("too many failures; try again in five minutes"); 93 freePW(pw); 94 return nil; 95 } 96 pw->failed = 0; 97 putPW(pw); /* reset failed-login-counter after five minutes */ 98 return pw; 99 } 100 101 int 102 putPW(PW *pw) 103 { 104 Biobuf *bout; 105 char *hexHi; 106 107 if((bout = openPW(pw->id, OWRITE|OTRUNC)) ==0){ 108 werrstr("can't open PW file"); 109 return -1; 110 } 111 Bprint(bout, "exp %lud\n", pw->expire); 112 if(!(pw->status & Enabled)) 113 Bprint(bout, "DISABLED\n"); 114 if(pw->status & STA) 115 Bprint(bout, "STA\n"); 116 if(pw->failed) 117 Bprint(bout, "failed\t%d\n", pw->failed); 118 if(pw->other) 119 Bprint(bout,"other\t%s\n", pw->other); 120 hexHi = mptoa(pw->Hi, 64, nil, 0); 121 Bprint(bout, "PAK-Hi\t%s\n", hexHi); 122 free(hexHi); 123 return 0; 124 } 125 126 void 127 freePW(PW *pw) 128 { 129 if(pw == nil) 130 return; 131 free(pw->id); 132 free(pw->other); 133 mpfree(pw->Hi); 134 free(pw); 135 }