From: Roy Marples Date: Tue, 2 Jun 2020 02:01:37 +0000 (+0100) Subject: auth: Only accept RECONFIGURE messages from LL hosts X-Git-Tag: v9.1.1~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=587d4465a93de2c24d85face4cee7c64906daf52;p=thirdparty%2Fdhcpcd.git auth: Only accept RECONFIGURE messages from LL hosts This has to be authentiated, and there is a chance we cannot know the token if IP address sharing. The initial messages are send via LL anyway, so the peer address the server should record is the LL. While here, drop the lease at exit if we accepted a reconfigure token. The token may not be in all the replies from the server and we always save the last reply. XXX Save the token in another file? --- diff --git a/src/dhcp.c b/src/dhcp.c index 4970cc7a..d3867741 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -2747,6 +2747,18 @@ dhcp_drop(struct interface *ifp, const char *reason) #endif } } +#ifdef AUTH + else if (state->auth.reconf != NULL) { + /* + * Drop the lease as the token may only be present + * in the initial reply message and not subsequent + * renewals. + * If dhcpcd is restarted, the token is lost. + * XXX persist this in another file? + */ + dhcp_unlink(ifp->ctx, state->leasefile); + } +#endif eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp); #ifdef AUTH diff --git a/src/dhcp6.c b/src/dhcp6.c index e6e12e30..1c65ed0c 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -3319,7 +3319,7 @@ dhcp6_recvif(struct interface *ifp, const char *sfrom, loginfox("%s: accepted reconfigure key", ifp->name); } else if (ifo->auth.options & DHCPCD_AUTH_SEND) { if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) { - logerr("%s: no authentication from %s", + logerrx("%s: no authentication from %s", ifp->name, sfrom); return; } @@ -3595,15 +3595,12 @@ dhcp6_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, struct ipv6_addr *ia) } if (r->type == DHCP6_RECONFIGURE) { - logdebugx("%s: RECONFIGURE6 recv from %s," - " sending to all interfaces", - ifp->name, sfrom); - TAILQ_FOREACH(ifp, ctx->ifaces, next) { - state = D6_CSTATE(ifp); - if (state != NULL && state->send != NULL) - dhcp6_recvif(ifp, sfrom, r, len); + if (!IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr)) { + logerrx("%s: RECONFIGURE6 recv from %s, not LL", + ifp->name, sfrom); + return; } - return; + goto recvif; } state = D6_CSTATE(ifp); @@ -3679,6 +3676,7 @@ dhcp6_recvmsg(struct dhcpcd_ctx *ctx, struct msghdr *msg, struct ipv6_addr *ia) len = (size_t)tlen; #endif +recvif: dhcp6_recvif(ifp, sfrom, r, len); } @@ -4041,6 +4039,19 @@ dhcp6_freedrop(struct interface *ifp, int drop, const char *reason) } dhcp_unlink(ifp->ctx, state->leasefile); } +#ifdef AUTH + else if (state->auth.reconf != NULL) { + /* + * Drop the lease as the token may only be present + * in the initial reply message and not subsequent + * renewals. + * If dhcpcd is restarted, the token is lost. + * XXX persist this in another file? + */ + dhcp_unlink(ifp->ctx, state->leasefile); + } +#endif + dhcp6_freedrop_addrs(ifp, drop, NULL); free(state->old); state->old = state->new;