changeset 4266:bd15cb1af330 draft

auth: allow different tokens for send and receive It was silly of me to assume that the same key would be used for both sending and receiving. Because token protocol is not digested, replace the digest argument with 0x123/0x456 where 0x123 is the sending key and 0x456 is the receiving key. Receiving key defaults to sending key, sending key defaults to zero. This should allow existing configurations to work as is.
author Roy Marples <roy@marples.name>
date Sun, 29 Apr 2018 21:38:58 +0100
parents 59d30b522937
children b5284aa7f420
files src/auth.c src/auth.h src/dhcpcd.conf.5.in src/if-options.c
diffstat 4 files changed, 50 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth.c	Sun Apr 29 21:28:15 2018 +0100
+++ b/src/auth.c	Sun Apr 29 21:38:58 2018 +0100
@@ -191,7 +191,7 @@
 	 * Rest of data is MAC. */
 	switch (protocol) {
 	case AUTH_PROTO_TOKEN:
-		secretid = 0;
+		secretid = auth->token_rcv_secretid;
 		break;
 	case AUTH_PROTO_DELAYED:
 		if (dlen < sizeof(secretid) + sizeof(hmac_code)) {
@@ -199,6 +199,7 @@
 			return NULL;
 		}
 		memcpy(&secretid, d, sizeof(secretid));
+		secretid = ntohl(secretid);
 		d += sizeof(secretid);
 		dlen -= sizeof(secretid);
 		break;
@@ -214,6 +215,7 @@
 			dlen -= realm_len;
 		}
 		memcpy(&secretid, d, sizeof(secretid));
+		secretid = ntohl(secretid);
 		d += sizeof(secretid);
 		dlen -= sizeof(secretid);
 		break;
@@ -283,7 +285,6 @@
 	}
 
 	/* Find a token for the realm and secret */
-	secretid = ntohl(secretid);
 	TAILQ_FOREACH(t, &auth->tokens, next) {
 		if (t->secretid == secretid &&
 		    t->realm_len == realm_len &&
@@ -499,11 +500,12 @@
 	uint32_t giaddr, secretid;
 	bool auth_info;
 
-	if (auth->protocol == 0 && t == NULL) {
+	/* Ignore the token argument given to us - always send using the
+	 * configured token. */
+	if (auth->protocol == AUTH_PROTO_TOKEN) {
 		TAILQ_FOREACH(t, &auth->tokens, next) {
-			if (t->secretid == 0 &&
-			    t->realm_len == 0)
-			break;
+			if (t->secretid == auth->token_snd_secretid)
+				break;
 		}
 		if (t == NULL) {
 			errno = EINVAL;
--- a/src/auth.h	Sun Apr 29 21:28:15 2018 +0100
+++ b/src/auth.h	Sun Apr 29 21:38:58 2018 +0100
@@ -71,6 +71,8 @@
 	uint64_t last_replay;
 	uint8_t last_replay_set;
 	struct token_head tokens;
+	uint32_t token_snd_secretid;
+	uint32_t token_rcv_secretid;
 #endif
 };
 
--- a/src/dhcpcd.conf.5.in	Sun Apr 29 21:28:15 2018 +0100
+++ b/src/dhcpcd.conf.5.in	Sun Apr 29 21:38:58 2018 +0100
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd February 2, 2018
+.Dd April 29, 2018
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -74,9 +74,16 @@
 .D1 # A generic 192.168.0.1 network
 .D1 profile 192.168.0.1
 .D1 static ip_address=192.168.0.98/24
-.It Ic authprotocol Ar protocol Ar algorithm Ar rdm
+.It Ic authprotocol Ar protocol Op Ar algorithm Op Ar rdm
 Authenticate DHCP messages.
 See the Supported Authentication Protocols section.
+If
+.Ar protocol
+is
+.Ar token
+then
+.Ar algorithm is
+snd_secretid/rcv_secretid so you can send and recieve different tokens.
 .It Ic authtoken Ar secretid Ar realm Ar expire Ar key
 Define a shared key for use in authentication.
 .Ar realm
@@ -863,7 +870,11 @@
 .Ss Supported Authentication Protocols
 .Bl -tag -width -indent
 .It Ic token
-Sends and expects the token with the secretid 0 and realm of "" in each message.
+Sends a plain text token the server expects and matches a token sent by
+the server.
+The tokens to not have to be the same.
+If unspecified, the token with secretid of 0 will be used in sending messages
+and validating received messages.
 .It Ic delayedrealm
 Delayed Authentication.
 .Nm dhcpcd
--- a/src/if-options.c	Sun Apr 29 21:28:15 2018 +0100
+++ b/src/if-options.c	Sun Apr 29 21:38:58 2018 +0100
@@ -1913,12 +1913,32 @@
 		}
 		if (fp)
 			*fp++ = '\0';
-		if (strcasecmp(arg, "hmacmd5") == 0 ||
-		    strcasecmp(arg, "hmac-md5") == 0)
-			ifo->auth.algorithm = AUTH_ALG_HMAC_MD5;
-		else {
-			logerrx("%s: unsupported algorithm", arg);
-			return 1;
+		if (ifo->auth.protocol == AUTH_PROTO_TOKEN) {
+			np = strchr(arg, '/');
+			if (np) {
+				if (fp == NULL || np < fp)
+					*np++ = '\0';
+				else
+					np = NULL;
+			}
+			if (parse_uint32(&ifo->auth.token_snd_secretid,
+			    arg) == -1)
+				logerrx("%s: not a number", arg);
+			else
+				ifo->auth.token_rcv_secretid =
+				    ifo->auth.token_snd_secretid;
+			if (np &&
+			    parse_uint32(&ifo->auth.token_rcv_secretid,
+			    np) == -1)
+				logerrx("%s: not a number", arg);
+		} else {
+			if (strcasecmp(arg, "hmacmd5") == 0 ||
+			    strcasecmp(arg, "hmac-md5") == 0)
+				ifo->auth.algorithm = AUTH_ALG_HMAC_MD5;
+			else {
+				logerrx("%s: unsupported algorithm", arg);
+				return 1;
+			}
 		}
 		arg = fp;
 		if (arg == NULL) {