@@ 150,7 150,6 @@ sysfsession(ulong *arg)
poperror();
if(convM2S(buf, &f, n) == 0){
unlock(&s->send);
-print("error converting %d bytes %ux %ux %ux\n", n, buf[0], buf[1], buf[2]);
error(Emountrpc);
}
switch(f.type){
@@ 164,7 163,6 @@ print("error converting %d bytes %ux %ux %ux\n", n, buf[0], buf[1], buf[2]);
error(f.ename);
default:
unlock(&s->send);
-print("error using %d bytes %ux %ux %ux\n", n, buf[0], buf[1], buf[2]);
error(Emountrpc);
}
}
@@ 363,8 361,8 @@ authreply(Session *s, ulong id, Fcall *f)
*
* The protocol is
* 1) read ticket request from #c/authenticate
- * 2) write ticket to #c/authenticate. if it matchs the challenge the
- * user is changed to the suid field of the ticket
+ * 2) write ticket+authenticator to #c/authenticate. if it matches
+ * the challenge the user is changed to the suid field of the ticket
* 3) read authenticator (to confirm this is the server advertised)
*/
long
@@ 382,6 380,7 @@ authread(Chan *c, char *a, int n)
error(Ebadarg);
c->aux = newcrypt();
cp = c->aux;
+
memset(&tr, 0, sizeof(tr));
tr.type = AuthTreq;
strcpy(tr.hostid, eve);
@@ 399,10 398,13 @@ authread(Chan *c, char *a, int n)
if(n != AUTHENTLEN)
error(Ebadarg);
cp = c->aux;
+
cp->a.num = AuthAs;
memmove(cp->a.chal, cp->t.chal, CHALLEN);
cp->a.id = 0;
- convA2M(&cp->a, a, cp->t.key);
+ convA2M(&cp->a, cp->tbuf, cp->t.key);
+ memmove(a, cp->tbuf, AUTHENTLEN);
+
freecrypt(cp);
c->aux = 0;
}
@@ 414,14 416,22 @@ authwrite(Chan *c, char *a, int n)
{
Crypt *cp;
- if(n != TICKETLEN)
+ if(n != TICKETLEN+AUTHENTLEN)
error(Ebadarg);
if(c->aux == 0)
error(Ebadarg);
cp = c->aux;
- convM2T(a, &cp->t, evekey);
+
+ memmove(cp->tbuf, a, TICKETLEN);
+ convM2T(cp->tbuf, &cp->t, evekey);
if(cp->t.num != AuthTs || memcmp(cp->a.chal, cp->t.chal, CHALLEN))
error(Eperm);
+
+ memmove(cp->tbuf, a+TICKETLEN, AUTHENTLEN);
+ convM2A(cp->tbuf, &cp->a, cp->t.key);
+ if(cp->a.num != AuthAc || memcmp(cp->a.chal, cp->t.chal, CHALLEN))
+ error(Eperm);
+
memmove(u->p->user, cp->t.suid, NAMELEN);
return n;
}
@@ 441,14 451,64 @@ authcheck(Chan *c, char *a, int n)
if(c->aux == 0)
c->aux = newcrypt();
cp = c->aux;
- convM2T(a, &cp->t, evekey);
+
+ memmove(cp->tbuf, a, TICKETLEN);
+ convM2T(cp->tbuf, &cp->t, evekey);
if(cp->t.num != AuthTc)
error(Ebadarg);
if(strcmp(u->p->user, cp->t.cuid))
error(cp->t.cuid);
- convM2A(a+TICKETLEN, &cp->a, cp->t.key);
+
+ memmove(cp->tbuf, a+TICKETLEN, AUTHENTLEN);
+ convM2A(cp->tbuf, &cp->a, cp->t.key);
if(cp->a.num != AuthAs || memcmp(cp->t.chal, cp->a.chal, CHALLEN))
error(Eperm);
+
+ return n;
+}
+
+/*
+ * called by devcons() for #c/authenticator
+ *
+ * a read after a write of a ticket returns an authenticator
+ * for that ticket.
+ */
+long
+authentwrite(Chan *c, char *a, int n)
+{
+ Crypt *cp;
+
+ if(n != TICKETLEN)
+ error(Ebadarg);
+ if(c->aux == 0)
+ c->aux = newcrypt();
+ cp = c->aux;
+
+ memmove(cp->tbuf, a, TICKETLEN);
+ convM2T(cp->tbuf, &cp->t, evekey);
+ if(cp->t.num != AuthTc || strcmp(cp->t.cuid, u->p->user)){
+ freecrypt(cp);
+ c->aux = 0;
+ error(Ebadarg);
+ }
+
+ return n;
+}
+long
+authentread(Chan *c, char *a, int n)
+{
+ Crypt *cp;
+
+ cp = c->aux;
+ if(cp == 0)
+ error("authenticator read must follow a write");
+
+ cp->a.num = AuthAc;
+ memmove(cp->a.chal, cp->t.chal, CHALLEN);
+ cp->a.id = 0;
+ convA2M(&cp->a, cp->tbuf, cp->t.key);
+ memmove(a, cp->tbuf, AUTHENTLEN);
+
return n;
}
@@ 323,6 323,7 @@ enum{
Qdir,
Qauth,
Qauthcheck,
+ Qauthent,
Qclock,
Qcons,
Qconsctl,
@@ 350,6 351,7 @@ enum{
Dirtab consdir[]={
"authenticate", {Qauth}, 0, 0666,
"authcheck", {Qauthcheck}, 0, 0666,
+ "authenticator", {Qauthent}, 0, 0666,
"clock", {Qclock}, 2*NUMSIZE, 0444,
"cons", {Qcons}, 0, 0660,
"consctl", {Qconsctl}, 0, 0220,
@@ 481,9 483,12 @@ consclose(Chan *c)
raw = 0;
unlock(&ctl);
}
+ break;
case Qauth:
case Qauthcheck:
+ case Qauthent:
authclose(c);
+ break;
}
}
@@ 600,6 605,9 @@ consread(Chan *c, void *buf, long n, ulong offset)
case Qauth:
return authread(c, cbuf, n);
+ case Qauthent:
+ return authentread(c, cbuf, n);
+
case Qhostowner:
return readstr(offset, buf, n, eve);
@@ 805,6 813,9 @@ conswrite(Chan *c, void *va, long n, ulong offset)
case Qauthcheck:
return authcheck(c, a, n);
+ case Qauthent:
+ return authentwrite(c, a, n);
+
case Qnull:
break;
@@ 4,6 4,8 @@ int anyready(void);
Image* attachimage(int, Chan*, ulong, ulong);
long authcheck(Chan*, char*, int);
void authclose(Chan*);
+long authentread(Chan*, char*, int);
+long authentwrite(Chan*, char*, int);
long authread(Chan*, char*, int);
ulong authrequest(Session*, Fcall*);
void authreply(Session*, ulong, Fcall*);