Fix dhcp-match-name to match hostname, not complete FQDN.

Also do name matching for DHCPv6.
This commit is contained in:
Simon Kelley
2018-10-05 23:35:54 +01:00
parent ee1df06aab
commit 0fdf3c1f61
2 changed files with 60 additions and 33 deletions

View File

@@ -700,15 +700,48 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
client_hostname = daemon->dhcp_buff; client_hostname = daemon->dhcp_buff;
} }
if (client_hostname) if (client_hostname && option_bool(OPT_LOG_OPTS))
{
struct dhcp_match_name *m;
size_t nl = strlen(client_hostname);
if (option_bool(OPT_LOG_OPTS))
my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname); my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
if (have_config(config, CONFIG_NAME))
{
hostname = config->hostname;
domain = config->domain;
hostname_auth = 1;
/* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
offer_hostname = hostname;
}
else if (client_hostname)
{
struct dhcp_match_name *m;
size_t nl;
domain = strip_hostname(client_hostname);
if ((nl = strlen(client_hostname)) != 0)
{
hostname = client_hostname;
if (!config)
{
/* Search again now we have a hostname.
Only accept configs without CLID and HWADDR here, (they won't match)
to avoid impersonation by name. */
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
mess->chaddr, mess->hlen,
mess->htype, hostname);
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
{
config = new;
/* set "known" tag for known hosts */
known_id.net = "known";
known_id.next = netid;
netid = &known_id;
}
}
for (m = daemon->dhcp_name_match; m; m = m->next) for (m = daemon->dhcp_name_match; m; m = m->next)
{ {
size_t ml = strlen(m->name); size_t ml = strlen(m->name);
@@ -733,41 +766,6 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
client_hostname[ml] = save; client_hostname[ml] = save;
} }
} }
if (have_config(config, CONFIG_NAME))
{
hostname = config->hostname;
domain = config->domain;
hostname_auth = 1;
/* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
offer_hostname = hostname;
}
else if (client_hostname)
{
domain = strip_hostname(client_hostname);
if (strlen(client_hostname) != 0)
{
hostname = client_hostname;
if (!config)
{
/* Search again now we have a hostname.
Only accept configs without CLID and HWADDR here, (they won't match)
to avoid impersonation by name. */
struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
mess->chaddr, mess->hlen,
mess->htype, hostname);
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
{
config = new;
/* set "known" tag for known hosts */
known_id.net = "known";
known_id.next = netid;
netid = &known_id;
}
}
}
} }
if (config) if (config)

View File

@@ -496,11 +496,16 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
} }
else if (state->client_hostname) else if (state->client_hostname)
{ {
struct dhcp_match_name *m;
size_t nl;
state->domain = strip_hostname(state->client_hostname); state->domain = strip_hostname(state->client_hostname);
nl = strlen(state->client_hostname);
if (strlen(state->client_hostname) != 0) if (strlen(state->client_hostname) != 0)
{ {
state->hostname = state->client_hostname; state->hostname = state->client_hostname;
if (!config) if (!config)
{ {
/* Search again now we have a hostname. /* Search again now we have a hostname.
@@ -510,6 +515,30 @@ static int dhcp6_no_relay(struct state *state, int msg_type, void *inbuff, size_
if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr) if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
config = new; config = new;
} }
for (m = daemon->dhcp_name_match; m; m = m->next)
{
size_t ml = strlen(m->name);
char save = 0;
if (nl < ml)
continue;
if (nl > ml)
{
save = state->client_hostname[ml];
state->client_hostname[ml] = 0;
}
if (hostname_isequal(state->client_hostname, m->name) &&
(save == 0 || m->wildcard))
{
m->netid->next = state->tags;
state->tags = m->netid;
}
if (save != 0)
state->client_hostname[ml] = save;
}
} }
} }
} }