ref: 5fc2f6af6c9d938dca7dd4b8df061d9eeb87ec75
parent: 5a0c34e9fbe074df1d7090e31ab38a3a37675949
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jan 25 20:26:42 EST 2015
wpa: cleanup, pad eap-ttls/pap password, zero passwords and key material after use
--- a/sys/src/cmd/aux/wpa.c
+++ b/sys/src/cmd/aux/wpa.c
@@ -446,14 +446,22 @@
factotumctl(char *fmt, ...)
{
va_list list;
- int r, fd;
+ int fd, r, n;
+ char *s;
- if((fd = open("/mnt/factotum/ctl", OWRITE)) < 0)
- return -1;
- va_start(list, fmt);
- r = vfprint(fd, fmt, list);
- va_end(list);
- close(fd);
+ r = -1;
+ if((fd = open("/mnt/factotum/ctl", OWRITE)) >= 0){
+ va_start(list, fmt);
+ s = vsmprint(fmt, list);
+ va_end(list);
+ if(s != nil){
+ n = strlen(s);
+ r = write(fd, s, n);
+ memset(s, 0, n);
+ free(s);
+ }
+ close(fd);
+ }
return r;
}
@@ -462,7 +470,7 @@
{
if(getessid() == nil)
return -1;
- return factotumctl("key proto=wpapsk role=client essid=%q !password=%.32H\n", essid, pmk);
+ return factotumctl("key proto=wpapsk role=client essid=%q !password=%.*H\n", essid, PMKlen, pmk);
}
int
@@ -842,9 +850,10 @@
tls->sessionKeylen = 128;
tls->sessionKey = emalloc(tls->sessionKeylen);
}
- if((fd = tlsClient(fd, tls)) < 0)
+ fd = tlsClient(fd, tls);
+ if(fd < 0)
sysfatal("tlsClient: %r");
- if(label != nil){
+ if(label != nil && tls->sessionKey != nil){
/*
* PMK is derived from MSK by taking the first 256 bits.
* we store the PMK into factotum with setpmk() associated
@@ -852,7 +861,14 @@
*/
if(setpmk(tls->sessionKey) < 0)
sysfatal("setpmk: %r");
+
+ /* destroy session key */
+ memset(tls->sessionKey, 0, tls->sessionKeylen);
}
+ free(tls->cert); /* TODO: check cert */
+ free(tls->sessionID);
+ free(tls->sessionKey);
+ free(tls);
return fd;
}
@@ -874,12 +890,16 @@
eapreset(conn);
if(code == 4 || debug)
fprint(2, "%s: eap code %s\n", argv0, code == 3 ? "Success" : "NAK");
+ return;
default:
+ unhandled:
+ if(debug)
+ fprint(2, "unhandled: %.*H\n", datalen < 0 ? 0 : datalen, data);
return;
}
-
if(datalen < 1)
- return;
+ goto unhandled;
+
tp = data[0];
switch(tp){
case 1: /* Identity */
@@ -887,15 +907,15 @@
datalen = 1+strlen(user);
memmove(data+1, user, datalen-1);
eapresp(conn, 2, id, data, datalen);
- break;
+ return;
case 2:
fprint(2, "%s: eap error: %.*s\n", argv0, datalen-1, (char*)data+1);
- break;
+ return;
case 33: /* EAP Extensions (AVP) */
if(debug)
fprint(2, "eap extension: %.*H\n", datalen, data);
eapresp(conn, 2, id, data, datalen);
- break;
+ return;
case 26: /* MS-CHAP-V2 */
data++;
datalen--;
@@ -936,6 +956,7 @@
*(--data) = tp, len++;
eapresp(conn, 2, id, data, len);
+ return;
}
break;
@@ -947,7 +968,7 @@
datalen < 4 ? 0 : datalen-4, (char*)data+4);
*(--data) = tp;
eapresp(conn, 2, id, data, 2);
- break;
+ return;
}
break;
@@ -992,8 +1013,7 @@
if((pid = rfork(RFPROC|RFMEM)) == -1)
sysfatal("fork: %r");
if(pid == 0){
- pid = getpid();
- tunn->readerpid = pid;
+ tunn->readerpid = getpid();
tlsreader(tunn, conn);
if(conn->tunn == tunn)
conn->tunn = nil;
@@ -1001,7 +1021,7 @@
free(tunn);
exits(nil);
}
- break;
+ return;
}
if(tunn == nil)
break;
@@ -1014,10 +1034,8 @@
data += 4;
}
data++;
- if(datalen <= 0)
- break;
- if(write(tunn->fd, data, datalen) != datalen)
- break;
+ if(datalen > 0)
+ write(tunn->fd, data, datalen);
if(frag || (tp == 25 && data[0] == 20)){ /* ack change cipher spec */
data -= 2;
data[0] = tp;
@@ -1024,33 +1042,30 @@
data[1] = 0;
eapresp(conn, 2, id, data, 2);
}
- break;
+ return;
}
+ goto unhandled;
}
int
-avp(uchar *p, int code, void *val, int len)
+avp(uchar *p, int n, int code, void *val, int len, int pad)
{
- int n;
-
- n = 4 + 4 + len;
-
- *p++ = code >> 24;
- *p++ = code >> 16;
- *p++ = code >> 8;
- *p++ = code;
- *p++ = 2;
-
- *p++ = n >> 16;
- *p++ = n >> 8;
- *p++ = n;
-
- memmove(p, val, len);
- p += len;
-
- n = (n + 3) & ~3;
- memset(p, 0, n - len);
-
+ len += 8;
+ if(len > n){
+ len = n - 8;
+ pad = 0;
+ }
+ p[0] = code >> 24;
+ p[1] = code >> 16;
+ p[2] = code >> 8;
+ p[3] = code;
+ p[4] = 2;
+ p[5] = len >> 16;
+ p[6] = len >> 8;
+ p[7] = len;
+ memmove(p+8, val, len-8);
+ n = (len + pad) & ~pad;
+ memset(p + len, 0, n - len);
return n;
}
@@ -1070,21 +1085,19 @@
int n;
fd = tlswrap(fd, "ttls keying material");
-
- /* we should really do challenge response here */
if((up = auth_getuserpasswd(nil, "proto=pass service=wpa essid=%q", essid)) == nil)
- sysfatal("ttlsclient %d: no user/pass for essid=%q", getpid(), essid);
-
- n = avp(buf, AvpUserName, up->user, strlen(up->user));
- n += avp(buf+n, AvpUserPass, up->passwd, strlen(up->passwd));
+ sysfatal("auth_getuserpasswd: %r");
+ n = avp(buf, sizeof(buf), AvpUserName, up->user, strlen(up->user), 3);
+ n += avp(buf+n, sizeof(buf)-n, AvpUserPass, up->passwd, strlen(up->passwd), 15);
freeup(up);
- if(write(fd, buf, n) != n)
- sysfatal("ttlsclient write: %r");
+ write(fd, buf, n);
+ memset(buf, 0, n);
}
void
peapwrite(Eapconn *conn, uchar *data, int len)
{
+ assert(len >= 4);
fdwrite(conn, data + 4, len - 4);
}