]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
auth: allow different tokens for send and receive
authorRoy Marples <roy@marples.name>
Sun, 29 Apr 2018 20:38:58 +0000 (21:38 +0100)
committerRoy Marples <roy@marples.name>
Sun, 29 Apr 2018 20:38:58 +0000 (21:38 +0100)
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.

src/auth.c
src/auth.h
src/dhcpcd.conf.5.in
src/if-options.c

index 93e8b774857f4edad5094eabc98077460327b1ca..a272e93d47395807a871c836fa2d30a0896e34b9 100644 (file)
@@ -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;
index ac35ba769ab2f9915d19f5e8fceb4288d0458834..f65d62c39c143dc17faab3fe5adcff9d50ce1f81 100644 (file)
@@ -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
 };
 
index f1a8a8d7d6670e95d6344dd0f3a07e2ee5bd46ee..3a6147141c00af595b14ad91f317f852e27514a0 100644 (file)
@@ -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
index 4eb6e6eaecaa98487c5892d31637b8626a7a63f5..5943e70046187893fd8adceb331beaef148c2753 100644 (file)
@@ -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) {