Import dhcpcd-6.4.6 with the following changes:
* Detect removal of IPv6 routes * Don't add link-local addresses to POINTOPOINT interfaces * Don't discard expired DHCPv6 leases when dumping them * If a DHCPv6 lease has no timers, expire it right away * Report delegated addresses * Call dhcpcd-run-hooks correctly when delegated prefixes already exist * Fix a memory error when ia_* config exists but IPv6 is disabled * Ensure servername and bootfile are safely exported * Sanitise the following characters using svis(3) with VIS_CTYLE and VIS_OCTAL: | ^ & ; < > ( ) $ ` \ " ' <tab> <newline> This allows a non buggy unvis(1) to decode it 100% and stays compatible with how dhcpcd used to handle encoding on most platforms. For systems that supply svis(3) there is a code reduction, for systems that do not, a slight code increase. This change mitigates systems affected by bash CVE-2014-6271 and CVE-2014-7169.
This commit is contained in:
parent
566336d596
commit
83f33c897c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: config.h,v 1.1.1.26 2014/06/14 20:51:06 roy Exp $ */
|
||||
/* $NetBSD: config.h,v 1.1.1.27 2014/09/27 01:14:55 roy Exp $ */
|
||||
|
||||
/* netbsd */
|
||||
#define SYSCONFDIR "/etc"
|
||||
|
@ -7,6 +7,7 @@
|
|||
#define LIBEXECDIR "/libexec"
|
||||
#define DBDIR "/var/db"
|
||||
#define RUNDIR "/var/run"
|
||||
#define HAVE_VIS_H
|
||||
#define HAVE_SPAWN_H
|
||||
#define HAVE_MD5_H
|
||||
#define SHA2_H <sha2.h>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: defs.h,v 1.1.1.43 2014/09/18 20:43:58 roy Exp $ */
|
||||
/* $NetBSD: defs.h,v 1.1.1.44 2014/09/27 01:14:55 roy Exp $ */
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
|
@ -30,7 +30,7 @@
|
|||
#define CONFIG_H
|
||||
|
||||
#define PACKAGE "dhcpcd"
|
||||
#define VERSION "6.4.5"
|
||||
#define VERSION "6.4.6"
|
||||
|
||||
#ifndef CONFIG
|
||||
# define CONFIG SYSCONFDIR "/" PACKAGE ".conf"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: dhcp-common.c,v 1.1.1.8 2014/09/16 22:23:18 roy Exp $");
|
||||
__RCSID("$NetBSD: dhcp-common.c,v 1.1.1.9 2014/09/27 01:14:51 roy Exp $");
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
|
@ -39,6 +39,11 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_VIS_H
|
||||
#include <vis.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "dhcp-common.h"
|
||||
#include "dhcp.h"
|
||||
|
@ -294,14 +299,28 @@ decode_rfc3397(char *out, size_t len, const uint8_t *p, size_t pl)
|
|||
return (ssize_t)count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Escape these characters to avoid any nastiness passing to a POSIX shell.
|
||||
* See IEEE Std 1003.1, 2004 Shell Command Language, 2.2 Quoting
|
||||
* space is not escaped.
|
||||
*/
|
||||
#define ESCAPE_CHARS "|&;<>()$`\\\"'\t\n"
|
||||
|
||||
/*
|
||||
* Prints a chunk of data to a string.
|
||||
* Escapes some characters defnined above to try and avoid any loopholes
|
||||
* in the shell we're passing to.
|
||||
* Any non visible characters are escaped as an octal number.
|
||||
*/
|
||||
ssize_t
|
||||
print_string(char *s, size_t len, const uint8_t *data, size_t dl)
|
||||
{
|
||||
uint8_t c;
|
||||
const uint8_t *e, *p;
|
||||
ssize_t bytes = 0;
|
||||
ssize_t r;
|
||||
size_t bytes;
|
||||
char v[5], *vp, *ve;
|
||||
|
||||
bytes = 0;
|
||||
e = data + dl;
|
||||
while (data < e) {
|
||||
c = *data++;
|
||||
|
@ -313,51 +332,25 @@ print_string(char *s, size_t len, const uint8_t *data, size_t dl)
|
|||
if (p == e)
|
||||
break;
|
||||
}
|
||||
if (!isascii(c) || !isprint(c)) {
|
||||
if (s) {
|
||||
if (len < 5) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
r = snprintf(s, len, "\\%03o", c);
|
||||
len -= (size_t)r;
|
||||
bytes += r;
|
||||
s += r;
|
||||
} else
|
||||
bytes += 4;
|
||||
continue;
|
||||
}
|
||||
switch (c) {
|
||||
case '"': /* FALLTHROUGH */
|
||||
case '\'': /* FALLTHROUGH */
|
||||
case '$': /* FALLTHROUGH */
|
||||
case '`': /* FALLTHROUGH */
|
||||
case '\\': /* FALLTHROUGH */
|
||||
case '|': /* FALLTHROUGH */
|
||||
case '&':
|
||||
if (s) {
|
||||
if (len < 3) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
*s++ = '\\';
|
||||
len--;
|
||||
}
|
||||
bytes++;
|
||||
break;
|
||||
ve = svis(v, c, VIS_CSTYLE | VIS_OCTAL,
|
||||
data <= e ? *data : 0, ESCAPE_CHARS);
|
||||
if (s && len < (size_t)(ve - v) + 1) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
bytes += (size_t)(ve - v);
|
||||
if (s) {
|
||||
*s++ = (char)c;
|
||||
len--;
|
||||
vp = v;
|
||||
while (vp != ve)
|
||||
*s++ = *vp++;
|
||||
}
|
||||
bytes++;
|
||||
}
|
||||
|
||||
/* NULL */
|
||||
if (s)
|
||||
*s = '\0';
|
||||
bytes++;
|
||||
return bytes;
|
||||
return (ssize_t)bytes;
|
||||
}
|
||||
|
||||
#define ADDRSZ 4
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: dhcp6.c,v 1.1.1.15 2014/09/18 20:43:56 roy Exp $");
|
||||
__RCSID("$NetBSD: dhcp6.c,v 1.1.1.16 2014/09/27 01:14:55 roy Exp $");
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
|
@ -1171,7 +1171,7 @@ dhcp6_dadcompleted(const struct interface *ifp)
|
|||
TAILQ_FOREACH(ap, &state->addrs, next) {
|
||||
if (ap->flags & IPV6_AF_ADDED &&
|
||||
!(ap->flags & IPV6_AF_DADCOMPLETED))
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -1494,7 +1494,7 @@ dhcp6_startexpire(void *arg)
|
|||
dhcp6_freedrop_addrs(ifp, 1, NULL);
|
||||
dhcp6_delete_delegates(ifp);
|
||||
script_runreason(ifp, "EXPIRE6");
|
||||
if (ipv6nd_hasradhcp(ifp))
|
||||
if (ipv6nd_hasradhcp(ifp) || dhcp6_hasprefixdelegation(ifp))
|
||||
dhcp6_startdiscover(ifp);
|
||||
else
|
||||
syslog(LOG_WARNING,
|
||||
|
@ -2061,7 +2061,9 @@ dhcp6_readlease(struct interface *ifp)
|
|||
if (fd == -1)
|
||||
goto ex;
|
||||
|
||||
if (state->expire != ND6_INFINITE_LIFETIME) {
|
||||
if (!(ifp->ctx->options & DHCPCD_DUMPLEASE) &&
|
||||
state->expire != ND6_INFINITE_LIFETIME)
|
||||
{
|
||||
gettimeofday(&now, NULL);
|
||||
if ((time_t)state->expire < now.tv_sec - st.st_mtime) {
|
||||
syslog(LOG_DEBUG,"%s: discarding expired lease",
|
||||
|
@ -2218,6 +2220,39 @@ dhcp6_ifdelegateaddr(struct interface *ifp, struct ipv6_addr *prefix,
|
|||
return a;
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp6_script_try_run(struct interface *ifp)
|
||||
{
|
||||
struct dhcp6_state *state;
|
||||
struct ipv6_addr *ap;
|
||||
int completed;
|
||||
|
||||
state = D6_STATE(ifp);
|
||||
if (!TAILQ_FIRST(&state->addrs))
|
||||
return;
|
||||
|
||||
completed = 1;
|
||||
/* If all addresses have completed DAD run the script */
|
||||
TAILQ_FOREACH(ap, &state->addrs, next) {
|
||||
if (ap->flags & IPV6_AF_ONLINK) {
|
||||
if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
|
||||
ipv6_findaddr(ap->iface, &ap->addr))
|
||||
ap->flags |= IPV6_AF_DADCOMPLETED;
|
||||
if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
|
||||
completed = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (completed) {
|
||||
script_runreason(ifp, state->reason);
|
||||
dhcpcd_daemonise(ifp->ctx);
|
||||
} else
|
||||
syslog(LOG_DEBUG,
|
||||
"%s: waiting for DHCPv6 DAD to complete",
|
||||
ifp->name);
|
||||
}
|
||||
|
||||
static void
|
||||
dhcp6_delegate_prefix(struct interface *ifp)
|
||||
{
|
||||
|
@ -2317,6 +2352,7 @@ dhcp6_delegate_prefix(struct interface *ifp)
|
|||
if (k && !carrier_warned) {
|
||||
ifd_state = D6_STATE(ifd);
|
||||
ipv6_addaddrs(&ifd_state->addrs);
|
||||
dhcp6_script_try_run(ifd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2381,6 +2417,7 @@ dhcp6_find_delegates(struct interface *ifp)
|
|||
state->state = DH6S_DELEGATED;
|
||||
ipv6_addaddrs(&state->addrs);
|
||||
ipv6_buildroutes(ifp->ctx);
|
||||
dhcp6_script_try_run(ifp);
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
@ -2790,13 +2827,13 @@ recv:
|
|||
if (state->renew == 0) {
|
||||
if (state->expire == ND6_INFINITE_LIFETIME)
|
||||
state->renew = ND6_INFINITE_LIFETIME;
|
||||
else
|
||||
else if (state->lowpl != ND6_INFINITE_LIFETIME)
|
||||
state->renew = (uint32_t)(state->lowpl * 0.5);
|
||||
}
|
||||
if (state->rebind == 0) {
|
||||
if (state->expire == ND6_INFINITE_LIFETIME)
|
||||
state->rebind = ND6_INFINITE_LIFETIME;
|
||||
else
|
||||
else if (state->lowpl != ND6_INFINITE_LIFETIME)
|
||||
state->rebind = (uint32_t)(state->lowpl * 0.8);
|
||||
}
|
||||
break;
|
||||
|
@ -2830,7 +2867,7 @@ recv:
|
|||
if (state->rebind && state->rebind != ND6_INFINITE_LIFETIME)
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
(time_t)state->rebind, dhcp6_startrebind, ifp);
|
||||
if (state->expire && state->expire != ND6_INFINITE_LIFETIME)
|
||||
if (state->expire != ND6_INFINITE_LIFETIME)
|
||||
eloop_timeout_add_sec(ifp->ctx->eloop,
|
||||
(time_t)state->expire, dhcp6_startexpire, ifp);
|
||||
|
||||
|
@ -2846,29 +2883,12 @@ recv:
|
|||
"%s: renew in %"PRIu32" seconds,"
|
||||
" rebind in %"PRIu32" seconds",
|
||||
ifp->name, state->renew, state->rebind);
|
||||
else if (state->expire == 0)
|
||||
syslog(has_new ? LOG_INFO : LOG_DEBUG,
|
||||
"%s: will expire", ifp->name);
|
||||
ipv6_buildroutes(ifp->ctx);
|
||||
dhcp6_writelease(ifp);
|
||||
|
||||
len = 1;
|
||||
/* If all addresses have completed DAD run the script */
|
||||
TAILQ_FOREACH(ap, &state->addrs, next) {
|
||||
if (ap->flags & IPV6_AF_ONLINK) {
|
||||
if (!(ap->flags & IPV6_AF_DADCOMPLETED) &&
|
||||
ipv6_findaddr(ap->iface, &ap->addr))
|
||||
ap->flags |= IPV6_AF_DADCOMPLETED;
|
||||
if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
|
||||
len = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (len) {
|
||||
script_runreason(ifp, state->reason);
|
||||
dhcpcd_daemonise(ifp->ctx);
|
||||
} else
|
||||
syslog(LOG_DEBUG,
|
||||
"%s: waiting for DHCPv6 DAD to complete",
|
||||
ifp->name);
|
||||
dhcp6_script_try_run(ifp);
|
||||
}
|
||||
|
||||
if (ifp->ctx->options & DHCPCD_TEST ||
|
||||
|
@ -3253,6 +3273,13 @@ dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
|
|||
char *pfx;
|
||||
uint32_t en;
|
||||
const struct dhcpcd_ctx *ctx;
|
||||
const struct dhcp6_state *state;
|
||||
const struct ipv6_addr *ap;
|
||||
char *v, *val;
|
||||
|
||||
n = 0;
|
||||
if (m == NULL)
|
||||
goto delegated;
|
||||
|
||||
if (len < sizeof(*m)) {
|
||||
/* Should be impossible with guards at packet in
|
||||
|
@ -3261,7 +3288,6 @@ dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
|
|||
return -1;
|
||||
}
|
||||
|
||||
n = 0;
|
||||
ifo = ifp->options;
|
||||
ctx = ifp->ctx;
|
||||
|
||||
|
@ -3344,6 +3370,35 @@ dhcp6_env(char **env, const char *prefix, const struct interface *ifp,
|
|||
}
|
||||
free(pfx);
|
||||
|
||||
delegated:
|
||||
/* Needed for Delegated Prefixes */
|
||||
state = D6_CSTATE(ifp);
|
||||
i = 0;
|
||||
TAILQ_FOREACH(ap, &state->addrs, next) {
|
||||
if (ap->delegating_iface) {
|
||||
i += strlen(ap->saddr) + 1;
|
||||
}
|
||||
}
|
||||
if (env && i) {
|
||||
i += strlen(prefix) + strlen("_dhcp6_prefix=");
|
||||
v = val = env[n] = malloc(i);
|
||||
if (v == NULL) {
|
||||
syslog(LOG_ERR, "%s: %m", __func__);
|
||||
return -1;
|
||||
}
|
||||
v += snprintf(val, i, "%s_dhcp6_prefix=", prefix);
|
||||
TAILQ_FOREACH(ap, &state->addrs, next) {
|
||||
if (ap->delegating_iface) {
|
||||
strcpy(v, ap->saddr);
|
||||
v += strlen(ap->saddr);
|
||||
*v++ = ' ';
|
||||
}
|
||||
}
|
||||
*--v = '\0';
|
||||
}
|
||||
if (i)
|
||||
n++;
|
||||
|
||||
return (ssize_t)n;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: ipv6.c,v 1.1.1.12 2014/09/16 22:23:19 roy Exp $");
|
||||
__RCSID("$NetBSD: ipv6.c,v 1.1.1.13 2014/09/27 01:14:54 roy Exp $");
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
|
@ -999,6 +999,11 @@ ipv6_start(struct interface *ifp)
|
|||
const struct ipv6_state *state;
|
||||
const struct ipv6_addr *ap;
|
||||
|
||||
/* We can't assign a link-locak address to this,
|
||||
* the ppp process has to. */
|
||||
if (ifp->flags & IFF_POINTOPOINT)
|
||||
return 0;
|
||||
|
||||
state = IPV6_CSTATE(ifp);
|
||||
if (state) {
|
||||
TAILQ_FOREACH(ap, &state->addrs, next) {
|
||||
|
@ -1100,7 +1105,8 @@ find_route6(struct rt6_head *rts, const struct rt6 *r)
|
|||
TAILQ_FOREACH(rt, rts, next) {
|
||||
if (IN6_ARE_ADDR_EQUAL(&rt->dest, &r->dest) &&
|
||||
#if HAVE_ROUTE_METRIC
|
||||
rt->iface->metric == r->iface->metric &&
|
||||
(r->iface == NULL || rt->iface == NULL ||
|
||||
rt->iface->metric == r->iface->metric) &&
|
||||
#endif
|
||||
IN6_ARE_ADDR_EQUAL(&rt->net, &r->net))
|
||||
return rt;
|
||||
|
@ -1113,8 +1119,9 @@ desc_route(const char *cmd, const struct rt6 *rt)
|
|||
{
|
||||
char destbuf[INET6_ADDRSTRLEN];
|
||||
char gatebuf[INET6_ADDRSTRLEN];
|
||||
const char *ifname = rt->iface->name, *dest, *gate;
|
||||
const char *ifname, *dest, *gate;
|
||||
|
||||
ifname = rt->iface ? rt->iface->name : "(no iface)";
|
||||
dest = inet_ntop(AF_INET6, &rt->dest, destbuf, INET6_ADDRSTRLEN);
|
||||
gate = inet_ntop(AF_INET6, &rt->gate, gatebuf, INET6_ADDRSTRLEN);
|
||||
if (IN6_ARE_ADDR_EQUAL(&rt->gate, &in6addr_any))
|
||||
|
@ -1130,6 +1137,22 @@ desc_route(const char *cmd, const struct rt6 *rt)
|
|||
dest, ipv6_prefixlen(&rt->net), gate);
|
||||
}
|
||||
|
||||
/* If something other than dhcpcd removes a route,
|
||||
* we need to remove it from our internal table. */
|
||||
int
|
||||
ipv6_routedeleted(struct dhcpcd_ctx *ctx, const struct rt6 *rt)
|
||||
{
|
||||
struct rt6 *f;
|
||||
|
||||
f = find_route6(ctx->ipv6->routes, rt);
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
desc_route("removing", f);
|
||||
TAILQ_REMOVE(ctx->ipv6->routes, f, next);
|
||||
free(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define n_route(a) nc_route(1, a, a)
|
||||
#define c_route(a, b) nc_route(0, a, b)
|
||||
static int
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: ipv6.h,v 1.1.1.11 2014/09/18 20:43:58 roy Exp $ */
|
||||
/* $NetBSD: ipv6.h,v 1.1.1.12 2014/09/27 01:14:55 roy Exp $ */
|
||||
|
||||
/*
|
||||
* dhcpcd - DHCP client daemon
|
||||
|
@ -201,6 +201,7 @@ void ipv6_free_ll_callbacks(struct interface *);
|
|||
int ipv6_start(struct interface *);
|
||||
void ipv6_free(struct interface *);
|
||||
void ipv6_ctxfree(struct dhcpcd_ctx *);
|
||||
int ipv6_routedeleted(struct dhcpcd_ctx *, const struct rt6 *);
|
||||
int ipv6_removesubnet(struct interface *, struct ipv6_addr *);
|
||||
void ipv6_buildroutes(struct dhcpcd_ctx *);
|
||||
|
||||
|
|
Loading…
Reference in New Issue