1*219b2ee8SDavid du Colombier #include "u.h" 2*219b2ee8SDavid du Colombier #include "../port/lib.h" 3*219b2ee8SDavid du Colombier #include "mem.h" 4*219b2ee8SDavid du Colombier #include "dat.h" 5*219b2ee8SDavid du Colombier #include "fns.h" 6*219b2ee8SDavid du Colombier #include "io.h" 7*219b2ee8SDavid du Colombier #include "../port/error.h" 8*219b2ee8SDavid du Colombier 9*219b2ee8SDavid du Colombier typedef struct Crypt Crypt; 10*219b2ee8SDavid du Colombier struct Crypt 11*219b2ee8SDavid du Colombier { 12*219b2ee8SDavid du Colombier Crypt *next; 13*219b2ee8SDavid du Colombier Ticket t; 14*219b2ee8SDavid du Colombier Authenticator a; 15*219b2ee8SDavid du Colombier char tbuf[TICKETLEN]; /* remote ticket */ 16*219b2ee8SDavid du Colombier }; 17*219b2ee8SDavid du Colombier 18*219b2ee8SDavid du Colombier typedef struct Session Session; 19*219b2ee8SDavid du Colombier struct Session 20*219b2ee8SDavid du Colombier { 21*219b2ee8SDavid du Colombier Lock; 22*219b2ee8SDavid du Colombier QLock send; 23*219b2ee8SDavid du Colombier Crypt *cache; /* cache of tickets */ 24*219b2ee8SDavid du Colombier char cchal[CHALLEN]; /* client challenge */ 25*219b2ee8SDavid du Colombier char schal[CHALLEN]; /* server challenge */ 26*219b2ee8SDavid du Colombier char authid[NAMELEN]; /* server encryption uid */ 27*219b2ee8SDavid du Colombier char authdom[DOMLEN]; /* server encryption domain */ 28*219b2ee8SDavid du Colombier ulong cid; /* challenge id */ 29*219b2ee8SDavid du Colombier int valid; 30*219b2ee8SDavid du Colombier }; 31*219b2ee8SDavid du Colombier 32*219b2ee8SDavid du Colombier struct 33*219b2ee8SDavid du Colombier { 34*219b2ee8SDavid du Colombier Lock; 35*219b2ee8SDavid du Colombier Crypt *free; 36*219b2ee8SDavid du Colombier } cryptalloc; 37*219b2ee8SDavid du Colombier 38*219b2ee8SDavid du Colombier char eve[NAMELEN] = "bootes"; 39*219b2ee8SDavid du Colombier char evekey[DESKEYLEN]; 40*219b2ee8SDavid du Colombier char hostdomain[DOMLEN]; 41*219b2ee8SDavid du Colombier 42*219b2ee8SDavid du Colombier /* 43*219b2ee8SDavid du Colombier * return true if current user is eve 44*219b2ee8SDavid du Colombier */ 45*219b2ee8SDavid du Colombier int 46*219b2ee8SDavid du Colombier iseve(void) 47*219b2ee8SDavid du Colombier { 48*219b2ee8SDavid du Colombier return strcmp(eve, u->p->user) == 0; 49*219b2ee8SDavid du Colombier } 50*219b2ee8SDavid du Colombier 51*219b2ee8SDavid du Colombier /* 52*219b2ee8SDavid du Colombier * crypt entries are allocated from a pool rather than allocated using malloc so 53*219b2ee8SDavid du Colombier * the memory can be protected from reading by devproc. The base and top of the 54*219b2ee8SDavid du Colombier * crypt arena is stored in palloc for devproc. 55*219b2ee8SDavid du Colombier */ 56*219b2ee8SDavid du Colombier Crypt* 57*219b2ee8SDavid du Colombier newcrypt(void) 58*219b2ee8SDavid du Colombier { 59*219b2ee8SDavid du Colombier Crypt *c; 60*219b2ee8SDavid du Colombier 61*219b2ee8SDavid du Colombier lock(&cryptalloc); 62*219b2ee8SDavid du Colombier if(cryptalloc.free) { 63*219b2ee8SDavid du Colombier c = cryptalloc.free; 64*219b2ee8SDavid du Colombier cryptalloc.free = c->next; 65*219b2ee8SDavid du Colombier unlock(&cryptalloc); 66*219b2ee8SDavid du Colombier memset(c, 0, sizeof(Crypt)); 67*219b2ee8SDavid du Colombier return c; 68*219b2ee8SDavid du Colombier } 69*219b2ee8SDavid du Colombier 70*219b2ee8SDavid du Colombier cryptalloc.free = xalloc(sizeof(Crypt)*conf.nproc); 71*219b2ee8SDavid du Colombier if(cryptalloc.free == 0) 72*219b2ee8SDavid du Colombier panic("newcrypt"); 73*219b2ee8SDavid du Colombier 74*219b2ee8SDavid du Colombier for(c = cryptalloc.free; c < cryptalloc.free+conf.nproc-1; c++) 75*219b2ee8SDavid du Colombier c->next = c+1; 76*219b2ee8SDavid du Colombier 77*219b2ee8SDavid du Colombier palloc.cmembase = (ulong)cryptalloc.free; 78*219b2ee8SDavid du Colombier palloc.cmemtop = palloc.cmembase+(sizeof(Crypt)*conf.nproc); 79*219b2ee8SDavid du Colombier unlock(&cryptalloc); 80*219b2ee8SDavid du Colombier return newcrypt(); 81*219b2ee8SDavid du Colombier } 82*219b2ee8SDavid du Colombier 83*219b2ee8SDavid du Colombier void 84*219b2ee8SDavid du Colombier freecrypt(Crypt *c) 85*219b2ee8SDavid du Colombier { 86*219b2ee8SDavid du Colombier lock(&cryptalloc); 87*219b2ee8SDavid du Colombier c->next = cryptalloc.free; 88*219b2ee8SDavid du Colombier cryptalloc.free = c; 89*219b2ee8SDavid du Colombier unlock(&cryptalloc); 90*219b2ee8SDavid du Colombier } 91*219b2ee8SDavid du Colombier 92*219b2ee8SDavid du Colombier /* 93*219b2ee8SDavid du Colombier * return the info received in the session message on this channel. 94*219b2ee8SDavid du Colombier * if no session message has been exchanged, do it. 95*219b2ee8SDavid du Colombier */ 96*219b2ee8SDavid du Colombier long 97*219b2ee8SDavid du Colombier sysfsession(ulong *arg) 98*219b2ee8SDavid du Colombier { 99*219b2ee8SDavid du Colombier int i, n; 100*219b2ee8SDavid du Colombier Chan *c; 101*219b2ee8SDavid du Colombier Crypt *cp; 102*219b2ee8SDavid du Colombier Session *s; 103*219b2ee8SDavid du Colombier Ticketreq tr; 104*219b2ee8SDavid du Colombier Fcall f; 105*219b2ee8SDavid du Colombier char buf[MAXMSG]; 106*219b2ee8SDavid du Colombier 107*219b2ee8SDavid du Colombier validaddr(arg[1], TICKREQLEN, 1); 108*219b2ee8SDavid du Colombier c = fdtochan(arg[0], OWRITE, 0, 1); 109*219b2ee8SDavid du Colombier if(waserror()){ 110*219b2ee8SDavid du Colombier close(c); 111*219b2ee8SDavid du Colombier nexterror(); 112*219b2ee8SDavid du Colombier } 113*219b2ee8SDavid du Colombier 114*219b2ee8SDavid du Colombier /* add a session structure to the channel if it has none */ 115*219b2ee8SDavid du Colombier lock(c); 116*219b2ee8SDavid du Colombier s = c->session; 117*219b2ee8SDavid du Colombier if(s == 0){ 118*219b2ee8SDavid du Colombier s = malloc(sizeof(Session)); 119*219b2ee8SDavid du Colombier if(s == 0){ 120*219b2ee8SDavid du Colombier unlock(c); 121*219b2ee8SDavid du Colombier error(Enomem); 122*219b2ee8SDavid du Colombier } 123*219b2ee8SDavid du Colombier c->session = s; 124*219b2ee8SDavid du Colombier } 125*219b2ee8SDavid du Colombier unlock(c); 126*219b2ee8SDavid du Colombier 127*219b2ee8SDavid du Colombier qlock(&s->send); 128*219b2ee8SDavid du Colombier if(s->valid == 0){ 129*219b2ee8SDavid du Colombier /* 130*219b2ee8SDavid du Colombier * Exchange a session message with the server. 131*219b2ee8SDavid du Colombier */ 132*219b2ee8SDavid du Colombier for(i = 0; i < CHALLEN; i++) 133*219b2ee8SDavid du Colombier s->cchal[i] = nrand(256); 134*219b2ee8SDavid du Colombier 135*219b2ee8SDavid du Colombier f.tag = NOTAG; 136*219b2ee8SDavid du Colombier f.type = Tsession; 137*219b2ee8SDavid du Colombier memmove(f.chal, s->cchal, CHALLEN); 138*219b2ee8SDavid du Colombier n = convS2M(&f, buf); 139*219b2ee8SDavid du Colombier 140*219b2ee8SDavid du Colombier /* 141*219b2ee8SDavid du Colombier * If an error occurs reading or writing, 142*219b2ee8SDavid du Colombier * this probably is a mount of a mount so turn off 143*219b2ee8SDavid du Colombier * authentication. 144*219b2ee8SDavid du Colombier */ 145*219b2ee8SDavid du Colombier if(waserror()) 146*219b2ee8SDavid du Colombier goto noauth; 147*219b2ee8SDavid du Colombier 148*219b2ee8SDavid du Colombier if((*devtab[c->type].write)(c, buf, n, 0) != n) 149*219b2ee8SDavid du Colombier error(Esession); 150*219b2ee8SDavid du Colombier n = (*devtab[c->type].read)(c, buf, sizeof buf, 0); 151*219b2ee8SDavid du Colombier /* OK is sometimes sent as a Datakit sign-on */ 152*219b2ee8SDavid du Colombier if(n == 2 && buf[0] == 'O' && buf[1] == 'K') 153*219b2ee8SDavid du Colombier n = (*devtab[c->type].read)(c, buf, sizeof buf, 0); 154*219b2ee8SDavid du Colombier 155*219b2ee8SDavid du Colombier poperror(); 156*219b2ee8SDavid du Colombier 157*219b2ee8SDavid du Colombier if(convM2S(buf, &f, n) == 0){ 158*219b2ee8SDavid du Colombier qunlock(&s->send); 159*219b2ee8SDavid du Colombier error(Esession); 160*219b2ee8SDavid du Colombier } 161*219b2ee8SDavid du Colombier switch(f.type){ 162*219b2ee8SDavid du Colombier case Rsession: 163*219b2ee8SDavid du Colombier memmove(s->schal, f.chal, CHALLEN); 164*219b2ee8SDavid du Colombier memmove(s->authid, f.authid, NAMELEN); 165*219b2ee8SDavid du Colombier memmove(s->authdom, f.authdom, DOMLEN); 166*219b2ee8SDavid du Colombier break; 167*219b2ee8SDavid du Colombier case Rerror: 168*219b2ee8SDavid du Colombier qunlock(&s->send); 169*219b2ee8SDavid du Colombier error(f.ename); 170*219b2ee8SDavid du Colombier default: 171*219b2ee8SDavid du Colombier qunlock(&s->send); 172*219b2ee8SDavid du Colombier error(Esession); 173*219b2ee8SDavid du Colombier } 174*219b2ee8SDavid du Colombier noauth: 175*219b2ee8SDavid du Colombier s->valid = 1; 176*219b2ee8SDavid du Colombier } 177*219b2ee8SDavid du Colombier qunlock(&s->send); 178*219b2ee8SDavid du Colombier 179*219b2ee8SDavid du Colombier /* 180*219b2ee8SDavid du Colombier * If server requires no ticket, or user is "none", or a ticket 181*219b2ee8SDavid du Colombier * is already cached, zero the request type 182*219b2ee8SDavid du Colombier */ 183*219b2ee8SDavid du Colombier tr.type = AuthTreq; 184*219b2ee8SDavid du Colombier if(strcmp(u->p->user, "none") == 0 || s->authid[0] == 0) 185*219b2ee8SDavid du Colombier tr.type = 0; 186*219b2ee8SDavid du Colombier else{ 187*219b2ee8SDavid du Colombier lock(s); 188*219b2ee8SDavid du Colombier for(cp = s->cache; cp; cp = cp->next) 189*219b2ee8SDavid du Colombier if(strcmp(cp->t.cuid, u->p->user) == 0){ 190*219b2ee8SDavid du Colombier tr.type = 0; 191*219b2ee8SDavid du Colombier break; 192*219b2ee8SDavid du Colombier } 193*219b2ee8SDavid du Colombier unlock(s); 194*219b2ee8SDavid du Colombier } 195*219b2ee8SDavid du Colombier 196*219b2ee8SDavid du Colombier /* create ticket request */ 197*219b2ee8SDavid du Colombier memmove(tr.chal, s->schal, CHALLEN); 198*219b2ee8SDavid du Colombier memmove(tr.authid, s->authid, NAMELEN); 199*219b2ee8SDavid du Colombier memmove(tr.authdom, s->authdom, DOMLEN); 200*219b2ee8SDavid du Colombier memmove(tr.uid, u->p->user, NAMELEN); 201*219b2ee8SDavid du Colombier memmove(tr.hostid, eve, NAMELEN); 202*219b2ee8SDavid du Colombier convTR2M(&tr, (char*)arg[1]); 203*219b2ee8SDavid du Colombier 204*219b2ee8SDavid du Colombier close(c); 205*219b2ee8SDavid du Colombier poperror(); 206*219b2ee8SDavid du Colombier return 0; 207*219b2ee8SDavid du Colombier } 208*219b2ee8SDavid du Colombier 209*219b2ee8SDavid du Colombier /* 210*219b2ee8SDavid du Colombier * attach tickets to a session 211*219b2ee8SDavid du Colombier */ 212*219b2ee8SDavid du Colombier long 213*219b2ee8SDavid du Colombier sysfauth(ulong *arg) 214*219b2ee8SDavid du Colombier { 215*219b2ee8SDavid du Colombier Chan *c; 216*219b2ee8SDavid du Colombier char *ta; 217*219b2ee8SDavid du Colombier Session *s; 218*219b2ee8SDavid du Colombier Crypt *cp, *ncp, **l; 219*219b2ee8SDavid du Colombier char tbuf[2*TICKETLEN]; 220*219b2ee8SDavid du Colombier 221*219b2ee8SDavid du Colombier validaddr(arg[1], 2*TICKETLEN, 0); 222*219b2ee8SDavid du Colombier c = fdtochan(arg[0], OWRITE, 0, 1); 223*219b2ee8SDavid du Colombier s = c->session; 224*219b2ee8SDavid du Colombier if(s == 0) 225*219b2ee8SDavid du Colombier error("fauth must follow fsession"); 226*219b2ee8SDavid du Colombier cp = newcrypt(); 227*219b2ee8SDavid du Colombier if(waserror()){ 228*219b2ee8SDavid du Colombier freecrypt(cp); 229*219b2ee8SDavid du Colombier nexterror(); 230*219b2ee8SDavid du Colombier } 231*219b2ee8SDavid du Colombier 232*219b2ee8SDavid du Colombier /* ticket supplied, use it */ 233*219b2ee8SDavid du Colombier ta = (char*)arg[1]; 234*219b2ee8SDavid du Colombier memmove(tbuf, ta, 2*TICKETLEN); 235*219b2ee8SDavid du Colombier convM2T(tbuf, &cp->t, evekey); 236*219b2ee8SDavid du Colombier if(cp->t.num != AuthTc) 237*219b2ee8SDavid du Colombier error("bad AuthTc in ticket"); 238*219b2ee8SDavid du Colombier if(strncmp(u->p->user, cp->t.cuid, NAMELEN) != 0) 239*219b2ee8SDavid du Colombier error("bad uid in ticket"); 240*219b2ee8SDavid du Colombier if(memcmp(cp->t.chal, s->schal, CHALLEN) != 0) 241*219b2ee8SDavid du Colombier error("bad chal in ticket"); 242*219b2ee8SDavid du Colombier memmove(cp->tbuf, tbuf+TICKETLEN, TICKETLEN); 243*219b2ee8SDavid du Colombier 244*219b2ee8SDavid du Colombier /* string onto local list, replace old version */ 245*219b2ee8SDavid du Colombier lock(s); 246*219b2ee8SDavid du Colombier l = &s->cache; 247*219b2ee8SDavid du Colombier for(ncp = s->cache; ncp; ncp = *l){ 248*219b2ee8SDavid du Colombier if(strcmp(ncp->t.cuid, u->p->user) == 0){ 249*219b2ee8SDavid du Colombier *l = ncp->next; 250*219b2ee8SDavid du Colombier freecrypt(ncp); 251*219b2ee8SDavid du Colombier break; 252*219b2ee8SDavid du Colombier } 253*219b2ee8SDavid du Colombier l = &ncp->next; 254*219b2ee8SDavid du Colombier } 255*219b2ee8SDavid du Colombier cp->next = s->cache; 256*219b2ee8SDavid du Colombier s->cache = cp; 257*219b2ee8SDavid du Colombier unlock(s); 258*219b2ee8SDavid du Colombier poperror(); 259*219b2ee8SDavid du Colombier return 0; 260*219b2ee8SDavid du Colombier } 261*219b2ee8SDavid du Colombier 262*219b2ee8SDavid du Colombier /* 263*219b2ee8SDavid du Colombier * free a session created by fsession 264*219b2ee8SDavid du Colombier */ 265*219b2ee8SDavid du Colombier void 266*219b2ee8SDavid du Colombier freesession(Session *s) 267*219b2ee8SDavid du Colombier { 268*219b2ee8SDavid du Colombier Crypt *cp, *next; 269*219b2ee8SDavid du Colombier 270*219b2ee8SDavid du Colombier for(cp = s->cache; cp; cp = next) { 271*219b2ee8SDavid du Colombier next = cp->next; 272*219b2ee8SDavid du Colombier freecrypt(cp); 273*219b2ee8SDavid du Colombier } 274*219b2ee8SDavid du Colombier free(s); 275*219b2ee8SDavid du Colombier } 276*219b2ee8SDavid du Colombier 277*219b2ee8SDavid du Colombier /* 278*219b2ee8SDavid du Colombier * called by mattach() to fill in the Tattach message 279*219b2ee8SDavid du Colombier */ 280*219b2ee8SDavid du Colombier ulong 281*219b2ee8SDavid du Colombier authrequest(Session *s, Fcall *f) 282*219b2ee8SDavid du Colombier { 283*219b2ee8SDavid du Colombier Crypt *cp; 284*219b2ee8SDavid du Colombier ulong id, dofree; 285*219b2ee8SDavid du Colombier 286*219b2ee8SDavid du Colombier /* no authentication if user is "none" or if no ticket required by remote */ 287*219b2ee8SDavid du Colombier if(s == 0 || s->authid[0] == 0 || strcmp(u->p->user, "none") == 0){ 288*219b2ee8SDavid du Colombier memset(f->ticket, 0, TICKETLEN); 289*219b2ee8SDavid du Colombier memset(f->auth, 0, AUTHENTLEN); 290*219b2ee8SDavid du Colombier return 0; 291*219b2ee8SDavid du Colombier } 292*219b2ee8SDavid du Colombier 293*219b2ee8SDavid du Colombier /* look for ticket in cache */ 294*219b2ee8SDavid du Colombier dofree = 0; 295*219b2ee8SDavid du Colombier lock(s); 296*219b2ee8SDavid du Colombier for(cp = s->cache; cp; cp = cp->next) 297*219b2ee8SDavid du Colombier if(strcmp(cp->t.cuid, u->p->user) == 0) 298*219b2ee8SDavid du Colombier break; 299*219b2ee8SDavid du Colombier 300*219b2ee8SDavid du Colombier id = s->cid++; 301*219b2ee8SDavid du Colombier unlock(s); 302*219b2ee8SDavid du Colombier 303*219b2ee8SDavid du Colombier if(cp == 0){ 304*219b2ee8SDavid du Colombier /* 305*219b2ee8SDavid du Colombier * create a ticket using hostkey, this solves the 306*219b2ee8SDavid du Colombier * chicken and egg problem 307*219b2ee8SDavid du Colombier */ 308*219b2ee8SDavid du Colombier cp = newcrypt(); 309*219b2ee8SDavid du Colombier cp->t.num = AuthTs; 310*219b2ee8SDavid du Colombier memmove(cp->t.chal, s->schal, CHALLEN); 311*219b2ee8SDavid du Colombier memmove(cp->t.cuid, u->p->user, NAMELEN); 312*219b2ee8SDavid du Colombier memmove(cp->t.suid, u->p->user, NAMELEN); 313*219b2ee8SDavid du Colombier memmove(cp->t.key, evekey, DESKEYLEN); 314*219b2ee8SDavid du Colombier convT2M(&cp->t, f->ticket, evekey); 315*219b2ee8SDavid du Colombier dofree = 1; 316*219b2ee8SDavid du Colombier } else 317*219b2ee8SDavid du Colombier memmove(f->ticket, cp->tbuf, TICKETLEN); 318*219b2ee8SDavid du Colombier 319*219b2ee8SDavid du Colombier /* create an authenticator */ 320*219b2ee8SDavid du Colombier memmove(cp->a.chal, s->schal, CHALLEN); 321*219b2ee8SDavid du Colombier cp->a.num = AuthAc; 322*219b2ee8SDavid du Colombier cp->a.id = id; 323*219b2ee8SDavid du Colombier convA2M(&cp->a, f->auth, cp->t.key); 324*219b2ee8SDavid du Colombier if(dofree) 325*219b2ee8SDavid du Colombier freecrypt(cp); 326*219b2ee8SDavid du Colombier return id; 327*219b2ee8SDavid du Colombier } 328*219b2ee8SDavid du Colombier 329*219b2ee8SDavid du Colombier /* 330*219b2ee8SDavid du Colombier * called by mattach() to check the Rattach message 331*219b2ee8SDavid du Colombier */ 332*219b2ee8SDavid du Colombier void 333*219b2ee8SDavid du Colombier authreply(Session *s, ulong id, Fcall *f) 334*219b2ee8SDavid du Colombier { 335*219b2ee8SDavid du Colombier Crypt *cp; 336*219b2ee8SDavid du Colombier 337*219b2ee8SDavid du Colombier if(s == 0) 338*219b2ee8SDavid du Colombier return; 339*219b2ee8SDavid du Colombier 340*219b2ee8SDavid du Colombier lock(s); 341*219b2ee8SDavid du Colombier for(cp = s->cache; cp; cp = cp->next) 342*219b2ee8SDavid du Colombier if(strcmp(cp->t.cuid, u->p->user) == 0) 343*219b2ee8SDavid du Colombier break; 344*219b2ee8SDavid du Colombier unlock(s); 345*219b2ee8SDavid du Colombier 346*219b2ee8SDavid du Colombier /* we're getting around authentication */ 347*219b2ee8SDavid du Colombier if(s == 0 || cp == 0 || s->authid[0] == 0 || strcmp(u->p->user, "none") == 0) 348*219b2ee8SDavid du Colombier return; 349*219b2ee8SDavid du Colombier 350*219b2ee8SDavid du Colombier convM2A(f->rauth, &cp->a, cp->t.key); 351*219b2ee8SDavid du Colombier if(cp->a.num != AuthAs){ 352*219b2ee8SDavid du Colombier print("bad encryption type\n"); 353*219b2ee8SDavid du Colombier error("server lies"); 354*219b2ee8SDavid du Colombier } 355*219b2ee8SDavid du Colombier if(memcmp(cp->a.chal, s->cchal, sizeof(cp->a.chal))){ 356*219b2ee8SDavid du Colombier print("bad returned challenge\n"); 357*219b2ee8SDavid du Colombier error("server lies"); 358*219b2ee8SDavid du Colombier } 359*219b2ee8SDavid du Colombier if(cp->a.id != id){ 360*219b2ee8SDavid du Colombier print("bad returned id\n"); 361*219b2ee8SDavid du Colombier error("server lies"); 362*219b2ee8SDavid du Colombier } 363*219b2ee8SDavid du Colombier } 364*219b2ee8SDavid du Colombier 365*219b2ee8SDavid du Colombier /* 366*219b2ee8SDavid du Colombier * called by devcons() for #c/authenticate 367*219b2ee8SDavid du Colombier * 368*219b2ee8SDavid du Colombier * The protocol is 369*219b2ee8SDavid du Colombier * 1) read ticket request from #c/authenticate 370*219b2ee8SDavid du Colombier * 2) write ticket+authenticator to #c/authenticate. if it matches 371*219b2ee8SDavid du Colombier * the challenge the user is changed to the suid field of the ticket 372*219b2ee8SDavid du Colombier * 3) read authenticator (to confirm this is the server advertised) 373*219b2ee8SDavid du Colombier */ 374*219b2ee8SDavid du Colombier long 375*219b2ee8SDavid du Colombier authread(Chan *c, char *a, int n) 376*219b2ee8SDavid du Colombier { 377*219b2ee8SDavid du Colombier Crypt *cp; 378*219b2ee8SDavid du Colombier int i; 379*219b2ee8SDavid du Colombier Ticketreq tr; 380*219b2ee8SDavid du Colombier 381*219b2ee8SDavid du Colombier if(c->aux == 0){ 382*219b2ee8SDavid du Colombier /* 383*219b2ee8SDavid du Colombier * first read returns a ticket request 384*219b2ee8SDavid du Colombier */ 385*219b2ee8SDavid du Colombier if(n != TICKREQLEN) 386*219b2ee8SDavid du Colombier error(Ebadarg); 387*219b2ee8SDavid du Colombier c->aux = newcrypt(); 388*219b2ee8SDavid du Colombier cp = c->aux; 389*219b2ee8SDavid du Colombier 390*219b2ee8SDavid du Colombier memset(&tr, 0, sizeof(tr)); 391*219b2ee8SDavid du Colombier tr.type = AuthTreq; 392*219b2ee8SDavid du Colombier strcpy(tr.hostid, eve); 393*219b2ee8SDavid du Colombier strcpy(tr.authid, eve); 394*219b2ee8SDavid du Colombier strcpy(tr.authdom, hostdomain); 395*219b2ee8SDavid du Colombier strcpy(tr.uid, u->p->user); 396*219b2ee8SDavid du Colombier for(i = 0; i < CHALLEN; i++) 397*219b2ee8SDavid du Colombier tr.chal[i] = nrand(256); 398*219b2ee8SDavid du Colombier memmove(cp->a.chal, tr.chal, CHALLEN); 399*219b2ee8SDavid du Colombier convTR2M(&tr, a); 400*219b2ee8SDavid du Colombier } else { 401*219b2ee8SDavid du Colombier /* 402*219b2ee8SDavid du Colombier * subsequent read returns an authenticator 403*219b2ee8SDavid du Colombier */ 404*219b2ee8SDavid du Colombier if(n != AUTHENTLEN) 405*219b2ee8SDavid du Colombier error(Ebadarg); 406*219b2ee8SDavid du Colombier cp = c->aux; 407*219b2ee8SDavid du Colombier 408*219b2ee8SDavid du Colombier cp->a.num = AuthAs; 409*219b2ee8SDavid du Colombier memmove(cp->a.chal, cp->t.chal, CHALLEN); 410*219b2ee8SDavid du Colombier cp->a.id = 0; 411*219b2ee8SDavid du Colombier convA2M(&cp->a, cp->tbuf, cp->t.key); 412*219b2ee8SDavid du Colombier memmove(a, cp->tbuf, AUTHENTLEN); 413*219b2ee8SDavid du Colombier 414*219b2ee8SDavid du Colombier freecrypt(cp); 415*219b2ee8SDavid du Colombier c->aux = 0; 416*219b2ee8SDavid du Colombier } 417*219b2ee8SDavid du Colombier return n; 418*219b2ee8SDavid du Colombier } 419*219b2ee8SDavid du Colombier 420*219b2ee8SDavid du Colombier long 421*219b2ee8SDavid du Colombier authwrite(Chan *c, char *a, int n) 422*219b2ee8SDavid du Colombier { 423*219b2ee8SDavid du Colombier Crypt *cp; 424*219b2ee8SDavid du Colombier 425*219b2ee8SDavid du Colombier if(n != TICKETLEN+AUTHENTLEN) 426*219b2ee8SDavid du Colombier error(Ebadarg); 427*219b2ee8SDavid du Colombier if(c->aux == 0) 428*219b2ee8SDavid du Colombier error(Ebadarg); 429*219b2ee8SDavid du Colombier cp = c->aux; 430*219b2ee8SDavid du Colombier 431*219b2ee8SDavid du Colombier memmove(cp->tbuf, a, TICKETLEN); 432*219b2ee8SDavid du Colombier convM2T(cp->tbuf, &cp->t, evekey); 433*219b2ee8SDavid du Colombier if(cp->t.num != AuthTs || memcmp(cp->a.chal, cp->t.chal, CHALLEN)) 434*219b2ee8SDavid du Colombier error(Eperm); 435*219b2ee8SDavid du Colombier 436*219b2ee8SDavid du Colombier memmove(cp->tbuf, a+TICKETLEN, AUTHENTLEN); 437*219b2ee8SDavid du Colombier convM2A(cp->tbuf, &cp->a, cp->t.key); 438*219b2ee8SDavid du Colombier if(cp->a.num != AuthAc || memcmp(cp->a.chal, cp->t.chal, CHALLEN)) 439*219b2ee8SDavid du Colombier error(Eperm); 440*219b2ee8SDavid du Colombier 441*219b2ee8SDavid du Colombier memmove(u->p->user, cp->t.suid, NAMELEN); 442*219b2ee8SDavid du Colombier return n; 443*219b2ee8SDavid du Colombier } 444*219b2ee8SDavid du Colombier 445*219b2ee8SDavid du Colombier /* 446*219b2ee8SDavid du Colombier * called by devcons() for #c/authcheck 447*219b2ee8SDavid du Colombier * 448*219b2ee8SDavid du Colombier * a write of a ticket+authenticator [+challenge+id] succeeds if they match 449*219b2ee8SDavid du Colombier */ 450*219b2ee8SDavid du Colombier long 451*219b2ee8SDavid du Colombier authcheck(Chan *c, char *a, int n) 452*219b2ee8SDavid du Colombier { 453*219b2ee8SDavid du Colombier Crypt *cp; 454*219b2ee8SDavid du Colombier char *chal; 455*219b2ee8SDavid du Colombier ulong id; 456*219b2ee8SDavid du Colombier 457*219b2ee8SDavid du Colombier if(n != TICKETLEN+AUTHENTLEN && n != TICKETLEN+AUTHENTLEN+CHALLEN+4) 458*219b2ee8SDavid du Colombier error(Ebadarg); 459*219b2ee8SDavid du Colombier if(c->aux == 0) 460*219b2ee8SDavid du Colombier c->aux = newcrypt(); 461*219b2ee8SDavid du Colombier cp = c->aux; 462*219b2ee8SDavid du Colombier 463*219b2ee8SDavid du Colombier memmove(cp->tbuf, a, TICKETLEN); 464*219b2ee8SDavid du Colombier convM2T(cp->tbuf, &cp->t, evekey); 465*219b2ee8SDavid du Colombier if(cp->t.num != AuthTc) 466*219b2ee8SDavid du Colombier error(Ebadarg); 467*219b2ee8SDavid du Colombier if(strcmp(u->p->user, cp->t.cuid)) 468*219b2ee8SDavid du Colombier error(cp->t.cuid); 469*219b2ee8SDavid du Colombier 470*219b2ee8SDavid du Colombier memmove(cp->tbuf, a+TICKETLEN, AUTHENTLEN); 471*219b2ee8SDavid du Colombier convM2A(cp->tbuf, &cp->a, cp->t.key); 472*219b2ee8SDavid du Colombier if(n == TICKETLEN+AUTHENTLEN+CHALLEN+4){ 473*219b2ee8SDavid du Colombier uchar *p = (uchar *)&a[TICKETLEN+AUTHENTLEN+CHALLEN]; 474*219b2ee8SDavid du Colombier id = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); 475*219b2ee8SDavid du Colombier chal = &a[TICKETLEN+AUTHENTLEN]; 476*219b2ee8SDavid du Colombier }else{ 477*219b2ee8SDavid du Colombier id = 0; 478*219b2ee8SDavid du Colombier chal = cp->t.chal; 479*219b2ee8SDavid du Colombier } 480*219b2ee8SDavid du Colombier if(cp->a.num != AuthAs || memcmp(chal, cp->a.chal, CHALLEN) || cp->a.id != id) 481*219b2ee8SDavid du Colombier error(Eperm); 482*219b2ee8SDavid du Colombier 483*219b2ee8SDavid du Colombier return n; 484*219b2ee8SDavid du Colombier } 485*219b2ee8SDavid du Colombier 486*219b2ee8SDavid du Colombier /* 487*219b2ee8SDavid du Colombier * called by devcons() for #c/authenticator 488*219b2ee8SDavid du Colombier * 489*219b2ee8SDavid du Colombier * a read after a write of a ticket (or ticket+id) returns an authenticator 490*219b2ee8SDavid du Colombier * for that ticket. 491*219b2ee8SDavid du Colombier */ 492*219b2ee8SDavid du Colombier long 493*219b2ee8SDavid du Colombier authentwrite(Chan *c, char *a, int n) 494*219b2ee8SDavid du Colombier { 495*219b2ee8SDavid du Colombier Crypt *cp; 496*219b2ee8SDavid du Colombier 497*219b2ee8SDavid du Colombier if(n != TICKETLEN && n != TICKETLEN+4) 498*219b2ee8SDavid du Colombier error(Ebadarg); 499*219b2ee8SDavid du Colombier if(c->aux == 0) 500*219b2ee8SDavid du Colombier c->aux = newcrypt(); 501*219b2ee8SDavid du Colombier cp = c->aux; 502*219b2ee8SDavid du Colombier 503*219b2ee8SDavid du Colombier memmove(cp->tbuf, a, TICKETLEN); 504*219b2ee8SDavid du Colombier convM2T(cp->tbuf, &cp->t, evekey); 505*219b2ee8SDavid du Colombier if(cp->t.num != AuthTc || strcmp(cp->t.cuid, u->p->user)){ 506*219b2ee8SDavid du Colombier freecrypt(cp); 507*219b2ee8SDavid du Colombier c->aux = 0; 508*219b2ee8SDavid du Colombier error(Ebadarg); 509*219b2ee8SDavid du Colombier } 510*219b2ee8SDavid du Colombier if(n == TICKETLEN+4){ 511*219b2ee8SDavid du Colombier uchar *p = (uchar *)&a[TICKETLEN]; 512*219b2ee8SDavid du Colombier cp->a.id = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); 513*219b2ee8SDavid du Colombier }else 514*219b2ee8SDavid du Colombier cp->a.id = 0; 515*219b2ee8SDavid du Colombier 516*219b2ee8SDavid du Colombier return n; 517*219b2ee8SDavid du Colombier } 518*219b2ee8SDavid du Colombier long 519*219b2ee8SDavid du Colombier authentread(Chan *c, char *a, int n) 520*219b2ee8SDavid du Colombier { 521*219b2ee8SDavid du Colombier Crypt *cp; 522*219b2ee8SDavid du Colombier 523*219b2ee8SDavid du Colombier cp = c->aux; 524*219b2ee8SDavid du Colombier if(cp == 0) 525*219b2ee8SDavid du Colombier error("authenticator read must follow a write"); 526*219b2ee8SDavid du Colombier 527*219b2ee8SDavid du Colombier cp->a.num = AuthAc; 528*219b2ee8SDavid du Colombier memmove(cp->a.chal, cp->t.chal, CHALLEN); 529*219b2ee8SDavid du Colombier convA2M(&cp->a, cp->tbuf, cp->t.key); 530*219b2ee8SDavid du Colombier memmove(a, cp->tbuf, AUTHENTLEN); 531*219b2ee8SDavid du Colombier 532*219b2ee8SDavid du Colombier return n; 533*219b2ee8SDavid du Colombier } 534*219b2ee8SDavid du Colombier 535*219b2ee8SDavid du Colombier void 536*219b2ee8SDavid du Colombier authclose(Chan *c) 537*219b2ee8SDavid du Colombier { 538*219b2ee8SDavid du Colombier if(c->aux) 539*219b2ee8SDavid du Colombier freecrypt(c->aux); 540*219b2ee8SDavid du Colombier c->aux = 0; 541*219b2ee8SDavid du Colombier } 542*219b2ee8SDavid du Colombier 543*219b2ee8SDavid du Colombier /* 544*219b2ee8SDavid du Colombier * called by devcons() for key device 545*219b2ee8SDavid du Colombier */ 546*219b2ee8SDavid du Colombier long 547*219b2ee8SDavid du Colombier keyread(char *a, int n, long offset) 548*219b2ee8SDavid du Colombier { 549*219b2ee8SDavid du Colombier if(n<DESKEYLEN || offset != 0) 550*219b2ee8SDavid du Colombier error(Ebadarg); 551*219b2ee8SDavid du Colombier if(!cpuserver || !iseve()) 552*219b2ee8SDavid du Colombier error(Eperm); 553*219b2ee8SDavid du Colombier memmove(a, evekey, DESKEYLEN); 554*219b2ee8SDavid du Colombier return DESKEYLEN; 555*219b2ee8SDavid du Colombier } 556*219b2ee8SDavid du Colombier 557*219b2ee8SDavid du Colombier long 558*219b2ee8SDavid du Colombier keywrite(char *a, int n) 559*219b2ee8SDavid du Colombier { 560*219b2ee8SDavid du Colombier if(n != DESKEYLEN) 561*219b2ee8SDavid du Colombier error(Ebadarg); 562*219b2ee8SDavid du Colombier if(!iseve()) 563*219b2ee8SDavid du Colombier error(Eperm); 564*219b2ee8SDavid du Colombier memmove(evekey, a, DESKEYLEN); 565*219b2ee8SDavid du Colombier return DESKEYLEN; 566*219b2ee8SDavid du Colombier } 567*219b2ee8SDavid du Colombier 568*219b2ee8SDavid du Colombier /* 569*219b2ee8SDavid du Colombier * called by devcons() for user device 570*219b2ee8SDavid du Colombier * 571*219b2ee8SDavid du Colombier * anyone can become none 572*219b2ee8SDavid du Colombier */ 573*219b2ee8SDavid du Colombier long 574*219b2ee8SDavid du Colombier userwrite(char *a, int n) 575*219b2ee8SDavid du Colombier { 576*219b2ee8SDavid du Colombier if(n >= NAMELEN) 577*219b2ee8SDavid du Colombier error(Ebadarg); 578*219b2ee8SDavid du Colombier if(strcmp(a, "none") != 0) 579*219b2ee8SDavid du Colombier error(Eperm); 580*219b2ee8SDavid du Colombier memset(u->p->user, 0, NAMELEN); 581*219b2ee8SDavid du Colombier strcpy(u->p->user, "none"); 582*219b2ee8SDavid du Colombier return n; 583*219b2ee8SDavid du Colombier } 584*219b2ee8SDavid du Colombier 585*219b2ee8SDavid du Colombier /* 586*219b2ee8SDavid du Colombier * called by devcons() for host owner/domain 587*219b2ee8SDavid du Colombier * 588*219b2ee8SDavid du Colombier * writing hostowner also sets user 589*219b2ee8SDavid du Colombier */ 590*219b2ee8SDavid du Colombier long 591*219b2ee8SDavid du Colombier hostownerwrite(char *a, int n) 592*219b2ee8SDavid du Colombier { 593*219b2ee8SDavid du Colombier char buf[NAMELEN]; 594*219b2ee8SDavid du Colombier 595*219b2ee8SDavid du Colombier if(!iseve()) 596*219b2ee8SDavid du Colombier error(Eperm); 597*219b2ee8SDavid du Colombier if(n >= NAMELEN) 598*219b2ee8SDavid du Colombier error(Ebadarg); 599*219b2ee8SDavid du Colombier memset(buf, 0, NAMELEN); 600*219b2ee8SDavid du Colombier strncpy(buf, a, n); 601*219b2ee8SDavid du Colombier if(buf[0] == 0) 602*219b2ee8SDavid du Colombier error(Ebadarg); 603*219b2ee8SDavid du Colombier memmove(eve, buf, NAMELEN); 604*219b2ee8SDavid du Colombier memmove(u->p->user, buf, NAMELEN); 605*219b2ee8SDavid du Colombier return n; 606*219b2ee8SDavid du Colombier } 607*219b2ee8SDavid du Colombier 608*219b2ee8SDavid du Colombier long 609*219b2ee8SDavid du Colombier hostdomainwrite(char *a, int n) 610*219b2ee8SDavid du Colombier { 611*219b2ee8SDavid du Colombier char buf[DOMLEN]; 612*219b2ee8SDavid du Colombier 613*219b2ee8SDavid du Colombier if(!iseve()) 614*219b2ee8SDavid du Colombier error(Eperm); 615*219b2ee8SDavid du Colombier if(n >= DOMLEN) 616*219b2ee8SDavid du Colombier error(Ebadarg); 617*219b2ee8SDavid du Colombier memset(buf, 0, DOMLEN); 618*219b2ee8SDavid du Colombier strncpy(buf, a, n); 619*219b2ee8SDavid du Colombier if(buf[0] == 0) 620*219b2ee8SDavid du Colombier error(Ebadarg); 621*219b2ee8SDavid du Colombier memmove(hostdomain, buf, DOMLEN); 622*219b2ee8SDavid du Colombier return n; 623*219b2ee8SDavid du Colombier } 624*219b2ee8SDavid du Colombier 625*219b2ee8SDavid du Colombier void 626*219b2ee8SDavid du Colombier wipekeys(void) 627*219b2ee8SDavid du Colombier { 628*219b2ee8SDavid du Colombier memset(evekey, 0, sizeof(evekey)); 629*219b2ee8SDavid du Colombier memset((void*)palloc.cmembase, 0, palloc.cmemtop - palloc.cmembase); 630*219b2ee8SDavid du Colombier } 631