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