shithub: riscv

Download patch

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);
 }