From 56d6cf9ccc1ae673bf7cc3d207841dee731b9860 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Mon, 10 Mar 2014 15:28:49 +0000 Subject: [PATCH] Fix a crash when accepting a reconfigure key. Check if a reconfigure message before checking state so reconfigure works. --- auth.c | 5 +++++ dhcp.c | 16 ++++++++++++---- dhcp6.c | 36 ++++++++++++++++++++++++++---------- 3 files changed, 43 insertions(+), 14 deletions(-) diff --git a/auth.c b/auth.c index 12757504..e877be66 100644 --- a/auth.c +++ b/auth.c @@ -231,6 +231,11 @@ dhcp_auth_validate(struct authstate *state, const struct auth *auth, } if (state->reconf == NULL) errno = ENOENT; + /* Free the old token so we log acceptance */ + if (state->token) { + free(state->token); + state->token = NULL; + } /* Nothing to validate, just accepting the key */ return state->reconf; case 2: diff --git a/dhcp.c b/dhcp.c index c64b6ae7..83523a87 100644 --- a/dhcp.c +++ b/dhcp.c @@ -1061,8 +1061,12 @@ read_lease(struct interface *ifp) free(dhcp); return NULL; } - syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, - ifp->name, state->auth.token->secretid); + if (state->auth.token) + syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, + ifp->name, state->auth.token->secretid); + else + syslog(LOG_DEBUG, "%s: accepted reconfigure key", + ifp->name); } return dhcp; @@ -2197,8 +2201,12 @@ dhcp_handledhcp(struct interface *iface, struct dhcp_message **dhcpp, iface, dhcp, from, 0); return; } - syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, - iface->name, state->auth.token->secretid); + if (state->auth.token) + syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, + iface->name, state->auth.token->secretid); + else + syslog(LOG_DEBUG, "%s: accepted reconfigure key", + iface->name); } else if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) { log_dhcp1(LOG_ERR, "no authentication", iface, dhcp, from, 0); return; diff --git a/dhcp6.c b/dhcp6.c index 8df9392c..c429a5c0 100644 --- a/dhcp6.c +++ b/dhcp6.c @@ -1460,14 +1460,14 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l, const struct if_options *ifo; const struct dhcp6_option *o; const uint8_t *p; - int i; + int i, e; uint32_t u32, renew, rebind; uint8_t iaid[4]; size_t ol; struct ipv6_addr *ap, *nap; ifo = ifp->options; - i = 0; + i = e = 0; state = D6_STATE(ifp); TAILQ_FOREACH(ap, &state->addrs, next) { ap->flags |= IPV6_AF_STALE; @@ -1500,8 +1500,10 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l, ol -= sizeof(u32); } else renew = rebind = 0; /* appease gcc */ - if (dhcp6_checkstatusok(ifp, NULL, p, ol) == -1) + if (dhcp6_checkstatusok(ifp, NULL, p, ol) == -1) { + e = 1; continue; + } if (ifo->ia_type == D6_OPTION_IA_PD) { if (dhcp6_findpd(ifp, iaid, p, ol) == 0) { syslog(LOG_WARNING, @@ -1544,6 +1546,8 @@ dhcp6_findia(struct interface *ifp, const uint8_t *d, size_t l, free(ap); } } + if (i == 0 && e) + return -1; return i; } @@ -1659,8 +1663,12 @@ dhcp6_readlease(struct interface *ifp) ifp->name); goto ex; } - syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, - ifp->name, state->auth.token->secretid); + if (state->auth.token) + syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, + ifp->name, state->auth.token->secretid); + else + syslog(LOG_DEBUG, "%s: accepted reconfigure key", + ifp->name); } else if (ifp->options->auth.options & DHCPCD_AUTH_REQUIRE) { syslog(LOG_ERR, "%s: authentication now required", ifp->name); goto ex; @@ -2055,10 +2063,13 @@ dhcp6_handledata(void *arg) ifp->name); return; } + + r = (struct dhcp6_message *)ctx->rcvhdr.msg_iov[0].iov_base; + /* We're already bound and this message is for another machine */ /* XXX DELEGATED? */ - if (state->state == DH6S_BOUND || - state->state == DH6S_INFORMED) + if (r->type != DHCP6_RECONFIGURE && + (state->state == DH6S_BOUND || state->state == DH6S_INFORMED)) return; r = (struct dhcp6_message *)ctx->rcvhdr.msg_iov[0].iov_base; @@ -2121,8 +2132,12 @@ dhcp6_handledata(void *arg) ifp->name, ctx->sfrom); return; } - syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, - ifp->name, state->auth.token->secretid); + if (state->auth.token) + syslog(LOG_DEBUG, "%s: validated using 0x%08" PRIu32, + ifp->name, state->auth.token->secretid); + else + syslog(LOG_DEBUG, "%s: accepted reconfigure key", + ifp->name); } else if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) { syslog(LOG_ERR, "%s: no authentication from %s", ifp->name, ctx->sfrom); @@ -2157,7 +2172,8 @@ dhcp6_handledata(void *arg) if (error == 1) goto recv; if (error == -1 || - dhcp6_validatelease(ifp, r, len, ctx->sfrom) == -1){ + dhcp6_validatelease(ifp, r, len, ctx->sfrom) == -1) + { dhcp6_startdiscover(ifp); return; } -- 2.47.3