1 #include "all.h" 2 #include "io.h" 3 #include <authsrv.h> 4 5 Nvrsafe nvr; 6 7 static int gotnvr; /* flag: nvr contains nvram; it could be bad */ 8 9 char* 10 nvrgetconfig(void) 11 { 12 return conf.confdev; 13 } 14 15 /* 16 * we shouldn't be writing nvram any more. 17 * the secstore/config field is now just secstore key. 18 * we still use authid, authdom and machkey for authentication. 19 */ 20 21 int 22 nvrcheck(void) 23 { 24 uchar csum; 25 26 if (readnvram(&nvr, NVread) < 0) { 27 print("nvrcheck: can't read nvram\n"); 28 return 1; 29 } else 30 gotnvr = 1; 31 print("nvr read\n"); 32 33 csum = nvcsum(nvr.machkey, sizeof nvr.machkey); 34 if(csum != nvr.machsum) { 35 print("\n\n ** NVR key checksum is incorrect **\n"); 36 print(" ** set password to allow attaches **\n\n"); 37 memset(nvr.machkey, 0, sizeof nvr.machkey); 38 return 1; 39 } 40 41 return 0; 42 } 43 44 int 45 nvrsetconfig(char* word) 46 { 47 /* config block is on device `word' */ 48 USED(word); 49 return 0; 50 } 51 52 int 53 conslock(void) 54 { 55 char *ln; 56 char nkey1[DESKEYLEN]; 57 static char zeroes[DESKEYLEN]; 58 59 if(memcmp(nvr.machkey, zeroes, DESKEYLEN) == 0) { 60 print("no password set\n"); 61 return 0; 62 } 63 64 for(;;) { 65 print("%s password:", service); 66 /* could turn off echo here */ 67 68 if ((ln = Brdline(&bin, '\n')) == nil) 69 return 0; 70 ln[Blinelen(&bin)-1] = '\0'; 71 72 /* could turn on echo here */ 73 memset(nkey1, 0, DESKEYLEN); 74 passtokey(nkey1, ln); 75 if(memcmp(nkey1, nvr.machkey, DESKEYLEN) == 0) { 76 prdate(); 77 break; 78 } 79 80 print("Bad password\n"); 81 delay(1000); 82 } 83 return 1; 84 } 85 86 /* 87 * authentication specific to 9P2000 88 */ 89 90 /* authentication states */ 91 enum 92 { 93 HaveProtos=1, 94 NeedProto, 95 HaveOK, 96 NeedCchal, 97 HaveSinfo, 98 NeedTicket, 99 HaveSauthenticator, 100 SSuccess, 101 }; 102 103 char *phasename[] = 104 { 105 [HaveProtos] "HaveProtos", 106 [NeedProto] "NeedProto", 107 [HaveOK] "HaveOK", 108 [NeedCchal] "NeedCchal", 109 [HaveSinfo] "HaveSinfo", 110 [NeedTicket] "NeedTicket", 111 [HaveSauthenticator] "HaveSauthenticator", 112 [SSuccess] "SSuccess", 113 }; 114 115 /* authentication structure */ 116 struct Auth 117 { 118 int inuse; 119 char uname[NAMELEN]; /* requestor's remote user name */ 120 char aname[NAMELEN]; /* requested aname */ 121 Userid uid; /* uid decided on */ 122 int phase; 123 char cchal[CHALLEN]; 124 char tbuf[TICKETLEN+AUTHENTLEN]; /* server ticket */ 125 Ticket t; 126 Ticketreq tr; 127 }; 128 129 Auth* auths; 130 Lock authlock; 131 132 void 133 authinit(void) 134 { 135 auths = malloc(conf.nauth * sizeof(*auths)); 136 } 137 138 static int 139 failure(Auth *s, char *why) 140 { 141 int i; 142 143 if(*why)print("authentication failed: %s: %s\n", phasename[s->phase], why); 144 srand((uintptr)s + time(nil)); 145 for(i = 0; i < CHALLEN; i++) 146 s->tr.chal[i] = nrand(256); 147 s->uid = -1; 148 strncpy(s->tr.authid, nvr.authid, NAMELEN); 149 strncpy(s->tr.authdom, nvr.authdom, DOMLEN); 150 memmove(s->cchal, s->tr.chal, sizeof(s->cchal)); 151 s->phase = HaveProtos; 152 return -1; 153 } 154 155 Auth* 156 authnew(char *uname, char *aname) 157 { 158 static int si = 0; 159 int i, nwrap; 160 Auth *s; 161 162 i = si; 163 nwrap = 0; 164 for(;;){ 165 if(i < 0 || i >= conf.nauth){ 166 if(++nwrap > 1) 167 return nil; 168 i = 0; 169 } 170 s = &auths[i++]; 171 if(s->inuse) 172 continue; 173 lock(&authlock); 174 if(s->inuse == 0){ 175 s->inuse = 1; 176 strncpy(s->uname, uname, NAMELEN-1); 177 strncpy(s->aname, aname, NAMELEN-1); 178 failure(s, ""); 179 si = i; 180 unlock(&authlock); 181 break; 182 } 183 unlock(&authlock); 184 } 185 return s; 186 } 187 188 void 189 authfree(Auth *s) 190 { 191 if(s != nil) 192 s->inuse = 0; 193 } 194 195 int 196 authread(File* file, uchar* data, int n) 197 { 198 Auth *s; 199 int m; 200 201 s = file->auth; 202 if(s == nil) 203 return -1; 204 205 switch(s->phase){ 206 default: 207 return failure(s, "unexpected phase"); 208 case HaveProtos: 209 m = snprint((char*)data, n, "v.2 p9sk1@%s", nvr.authdom) + 1; 210 s->phase = NeedProto; 211 break; 212 case HaveOK: 213 m = 3; 214 if(n < m) 215 return failure(s, "read too short"); 216 strcpy((char*)data, "OK"); 217 s->phase = NeedCchal; 218 break; 219 case HaveSinfo: 220 m = TICKREQLEN; 221 if(n < m) 222 return failure(s, "read too short"); 223 convTR2M(&s->tr, (char*)data); 224 s->phase = NeedTicket; 225 break; 226 case HaveSauthenticator: 227 m = AUTHENTLEN; 228 if(n < m) 229 return failure(s, "read too short"); 230 memmove(data, s->tbuf+TICKETLEN, m); 231 s->phase = SSuccess; 232 break; 233 } 234 return m; 235 } 236 237 int 238 authwrite(File* file, uchar *data, int n) 239 { 240 Auth *s; 241 int m; 242 char *p, *d; 243 Authenticator a; 244 245 s = file->auth; 246 if(s == nil) 247 return -1; 248 249 switch(s->phase){ 250 default: 251 return failure(s, "unknown phase"); 252 case NeedProto: 253 p = (char*)data; 254 if(p[n-1] != 0) 255 return failure(s, "proto missing terminator"); 256 d = strchr(p, ' '); 257 if(d == nil) 258 return failure(s, "proto missing separator"); 259 *d++ = 0; 260 if(strcmp(p, "p9sk1") != 0) 261 return failure(s, "unknown proto"); 262 if(strcmp(d, nvr.authdom) != 0) 263 return failure(s, "unknown domain"); 264 s->phase = HaveOK; 265 m = n; 266 break; 267 case NeedCchal: 268 m = CHALLEN; 269 if(n < m) 270 return failure(s, "client challenge too short"); 271 memmove(s->cchal, data, sizeof(s->cchal)); 272 s->phase = HaveSinfo; 273 break; 274 case NeedTicket: 275 m = TICKETLEN+AUTHENTLEN; 276 if(n < m) 277 return failure(s, "ticket+auth too short"); 278 279 convM2T((char*)data, &s->t, nvr.machkey); 280 if(s->t.num != AuthTs 281 || memcmp(s->t.chal, s->tr.chal, sizeof(s->t.chal)) != 0) 282 return failure(s, "bad ticket"); 283 284 convM2A((char*)data+TICKETLEN, &a, s->t.key); 285 if(a.num != AuthAc 286 || memcmp(a.chal, s->tr.chal, sizeof(a.chal)) != 0 287 || a.id != 0) 288 return failure(s, "bad authenticator"); 289 290 /* at this point, we're convinced */ 291 s->uid = strtouid(s->t.suid); 292 if(s->uid < 0) 293 return failure(s, "unknown user"); 294 if(cons.flags & authdebugflag) 295 print("user %s = %d authenticated\n", 296 s->t.suid, s->uid); 297 298 /* create an authenticator to send back */ 299 a.num = AuthAs; 300 memmove(a.chal, s->cchal, sizeof(a.chal)); 301 a.id = 0; 302 convA2M(&a, s->tbuf+TICKETLEN, s->t.key); 303 304 s->phase = HaveSauthenticator; 305 break; 306 } 307 return m; 308 } 309 310 int 311 authuid(Auth* s) 312 { 313 return s->uid; 314 } 315 316 char* 317 authaname(Auth* s) 318 { 319 return s->aname; 320 } 321 322 char* 323 authuname(Auth* s) 324 { 325 return s->uname; 326 } 327