From: Roy Marples Date: Sun, 29 Apr 2018 20:38:58 +0000 (+0100) Subject: auth: allow different tokens for send and receive X-Git-Tag: v7.0.4~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=32945b618c1456aa23755d0a540495309dcfc41c;p=thirdparty%2Fdhcpcd.git 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. --- diff --git a/src/auth.c b/src/auth.c index 93e8b774..a272e93d 100644 --- a/src/auth.c +++ b/src/auth.c @@ -191,7 +191,7 @@ dhcp_auth_validate(struct authstate *state, const struct auth *auth, * 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 @@ dhcp_auth_validate(struct authstate *state, const struct auth *auth, return NULL; } memcpy(&secretid, d, sizeof(secretid)); + secretid = ntohl(secretid); d += sizeof(secretid); dlen -= sizeof(secretid); break; @@ -214,6 +215,7 @@ dhcp_auth_validate(struct authstate *state, const struct auth *auth, dlen -= realm_len; } memcpy(&secretid, d, sizeof(secretid)); + secretid = ntohl(secretid); d += sizeof(secretid); dlen -= sizeof(secretid); break; @@ -283,7 +285,6 @@ dhcp_auth_validate(struct authstate *state, const struct auth *auth, } /* 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 @@ dhcp_auth_encode(struct auth *auth, const struct token *t, 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; diff --git a/src/auth.h b/src/auth.h index ac35ba76..f65d62c3 100644 --- a/src/auth.h +++ b/src/auth.h @@ -71,6 +71,8 @@ struct auth { uint64_t last_replay; uint8_t last_replay_set; struct token_head tokens; + uint32_t token_snd_secretid; + uint32_t token_rcv_secretid; #endif }; diff --git a/src/dhcpcd.conf.5.in b/src/dhcpcd.conf.5.in index f1a8a8d7..3a614714 100644 --- a/src/dhcpcd.conf.5.in +++ b/src/dhcpcd.conf.5.in @@ -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 @@ Example: .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 @@ References an option from the global definition. .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 diff --git a/src/if-options.c b/src/if-options.c index 4eb6e6ea..5943e700 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -1913,12 +1913,32 @@ err_sla: } 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) {