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*
openPW(char * id,int mode)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
mtimePW(char * id)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 *
getPW(char * id,int dead_or_alive)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
putPW(PW * pw)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
freePW(PW * pw)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