/* * reply with ticket and authenticator */ int tickauthreply(Ticketreq *tr, char *hkey) { Ticket t; Authenticator a; char buf[TICKETLEN+AUTHENTLEN+1]; memset(&t, 0, sizeof(t)); memmove(t.chal, tr->chal, CHALLEN); safecpy(t.cuid, tr->uid, sizeof t.cuid); safecpy(t.suid, tr->uid, sizeof t.suid); mkkey(t.key); buf[0] = AuthOK; t.num = AuthTs; convT2M(&t, buf+1, hkey); memmove(a.chal, t.chal, CHALLEN); a.num = AuthAc; a.id = 0; convA2M(&a, buf+TICKETLEN+1, t.key); if(write(1, buf, TICKETLEN+AUTHENTLEN+1) < 0) return -1; return 0; }
int authorize(Chan *cp, Oldfcall *in, Oldfcall *ou) { Ticket t; Authenticator a; int x; uint32_t bit; if (cp == cons.srvchan) /* local channel already safe */ return 1; if(wstatallow) /* set to allow entry during boot */ return 1; if(strcmp(in->uname, "none") == 0) return allownone || cp->authed; if(in->type == Toattach9p1) return 0; if(!didread) return 0; /* decrypt and unpack ticket */ convM2T(in->ticket, &t, nvr.machkey); if(t.num != AuthTs){ print("bad AuthTs num\n"); return 0; } /* decrypt and unpack authenticator */ convM2A(in->auth, &a, t.key); if(a.num != AuthAc){ print("bad AuthAc num\n"); return 0; } /* challenges must match */ if(memcmp(a.chal, cp->chal, sizeof(a.chal)) != 0){ print("bad challenge\n"); return 0; } /* * the id must be in a valid range. the range is specified by a * lower bount (idoffset) and a bit vector (idvec) where a * bit set to 1 means unusable */ lock(&cp->idlock); x = a.id - cp->idoffset; bit = 1<<x; if(x < 0 || x > 31 || (bit&cp->idvec)){ unlock(&cp->idlock); return 0; } cp->idvec |= bit; /* normalize the vector */ while(cp->idvec&0xffff0001){ cp->idvec >>= 1; cp->idoffset++; } unlock(&cp->idlock); /* ticket name and attach name must match */ if(memcmp(in->uname, t.cuid, sizeof(in->uname)) != 0){ print("names don't match\n"); return 0; } /* copy translated name into input record */ memmove(in->uname, t.suid, sizeof(in->uname)); /* craft a reply */ a.num = AuthAs; memmove(a.chal, cp->rchal, CHALLEN); convA2M(&a, ou->rauth, t.key); cp->authed = 1; return 1; }
AuthInfo* p9any(int fd) { char buf[1024], buf2[1024], cchal[CHALLEN], *bbuf, *p, *dom, *u; char *pass; char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN]; char authkey[DESKEYLEN]; Authenticator auth; int afd, i, n, v2; Ticketreq tr; Ticket t; AuthInfo *ai; if((afd = open("/mnt/factotum/ctl", ORDWR)) >= 0) return p9anyfactotum(fd, afd); if(readstr(fd, buf, sizeof buf) < 0) fatal(1, "cannot read p9any negotiation"); bbuf = buf; v2 = 0; if(strncmp(buf, "v.2 ", 4) == 0){ v2 = 1; bbuf += 4; } if((p = strchr(bbuf, ' '))) *p = 0; p = bbuf; if((dom = strchr(p, '@')) == nil) fatal(1, "bad p9any domain"); *dom++ = 0; if(strcmp(p, "p9sk1") != 0) fatal(1, "server did not offer p9sk1"); sprint(buf2, "%s %s", p, dom); if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1) fatal(1, "cannot write user/domain choice in p9any"); if(v2){ if(readstr(fd, buf, sizeof buf) != 3) fatal(1, "cannot read OK in p9any"); if(memcmp(buf, "OK\0", 3) != 0) fatal(1, "did not get OK in p9any"); } for(i=0; i<CHALLEN; i++) cchal[i] = fastrand(); if(write(fd, cchal, 8) != 8) fatal(1, "cannot write p9sk1 challenge"); if(readn(fd, trbuf, TICKREQLEN) != TICKREQLEN) fatal(1, "cannot read ticket request in p9sk1"); convM2TR(trbuf, &tr); u = user; pass = findkey(&u, tr.authdom); if(pass == nil) again: pass = getkey(u, tr.authdom); if(pass == nil) fatal(1, "no password"); passtokey(authkey, pass); memset(pass, 0, strlen(pass)); tr.type = AuthTreq; strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, u); strecpy(tr.uid, tr.uid+sizeof tr.uid, u); convTR2M(&tr, trbuf); if(gettickets(&tr, authkey, trbuf, tbuf) < 0) fatal(1, "cannot get auth tickets in p9sk1"); convM2T(tbuf, &t, authkey); if(t.num != AuthTc){ print("?password mismatch with auth server\n"); goto again; } memmove(tbuf, tbuf+TICKETLEN, TICKETLEN); auth.num = AuthAc; memmove(auth.chal, tr.chal, CHALLEN); auth.id = 0; convA2M(&auth, tbuf+TICKETLEN, t.key); if(write(fd, tbuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN) fatal(1, "cannot send ticket and authenticator back in p9sk1"); if((n=readn(fd, tbuf, AUTHENTLEN)) != AUTHENTLEN || memcmp(tbuf, "cpu:", 4) == 0){ if(n <= 4) fatal(1, "cannot read authenticator in p9sk1"); /* * didn't send back authenticator: * sent back fatal error message. */ memmove(buf, tbuf, n); i = readn(fd, buf+n, sizeof buf-n-1); if(i > 0) n += i; buf[n] = 0; werrstr(""); fatal(0, "server says: %s", buf); } convM2A(tbuf, &auth, t.key); if(auth.num != AuthAs || memcmp(auth.chal, cchal, CHALLEN) != 0 || auth.id != 0){ print("?you and auth server agree about password.\n"); print("?server is confused.\n"); fatal(0, "server lies got %llux.%d want %llux.%d", *(int64_t*)auth.chal, auth.id, *(int64_t*)cchal, 0); } //print("i am %s there.\n", t.suid); ai = mallocz(sizeof(AuthInfo), 1); ai->secret = mallocz(8, 1); des56to64((uint8_t*)t.key, ai->secret); ai->nsecret = 8; ai->suid = strdup(t.suid); ai->cuid = strdup(t.cuid); memset(authkey, 0, sizeof authkey); return ai; }