mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
Merge pull request #18216 from yuwata/dhcp-user-class-length
dhcp: length of each user class field must be positive
This commit is contained in:
commit
09db85080a
@ -38,11 +38,14 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
|
||||
size_t total = 0;
|
||||
char **s;
|
||||
|
||||
if (strv_isempty((char **) optval))
|
||||
return -EINVAL;
|
||||
|
||||
STRV_FOREACH(s, (char **) optval) {
|
||||
size_t len = strlen(*s);
|
||||
|
||||
if (len > 255)
|
||||
return -ENAMETOOLONG;
|
||||
if (len > 255 || len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
total += 1 + len;
|
||||
}
|
||||
@ -51,14 +54,13 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
|
||||
return -ENOBUFS;
|
||||
|
||||
options[*offset] = code;
|
||||
options[*offset + 1] = total;
|
||||
options[*offset + 1] = total;
|
||||
*offset += 2;
|
||||
|
||||
STRV_FOREACH(s, (char **) optval) {
|
||||
size_t len = strlen(*s);
|
||||
|
||||
options[*offset] = len;
|
||||
|
||||
memcpy(&options[*offset + 1], *s, len);
|
||||
*offset += 1 + len;
|
||||
}
|
||||
|
@ -99,8 +99,8 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
|
||||
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
|
||||
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
|
||||
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
|
||||
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class);
|
||||
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **user_class);
|
||||
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class);
|
||||
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const *user_class);
|
||||
int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options);
|
||||
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
|
||||
size_t *optlen, uint8_t **optvalue);
|
||||
|
@ -200,19 +200,22 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class) {
|
||||
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class) {
|
||||
_cleanup_free_ uint8_t *p = NULL;
|
||||
size_t total = 0, offset = 0;
|
||||
char **s;
|
||||
char * const *s;
|
||||
|
||||
assert_return(buf && *buf && buflen && user_class, -EINVAL);
|
||||
assert(buf);
|
||||
assert(*buf);
|
||||
assert(buflen);
|
||||
assert(!strv_isempty(user_class));
|
||||
|
||||
STRV_FOREACH(s, user_class) {
|
||||
size_t len = strlen(*s);
|
||||
uint8_t *q;
|
||||
|
||||
if (len > 0xffff)
|
||||
return -ENAMETOOLONG;
|
||||
if (len > 0xffff || len == 0)
|
||||
return -EINVAL;
|
||||
q = realloc(p, total + len + 2);
|
||||
if (!q)
|
||||
return -ENOMEM;
|
||||
@ -229,16 +232,16 @@ int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_cl
|
||||
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p);
|
||||
}
|
||||
|
||||
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **vendor_class) {
|
||||
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const *vendor_class) {
|
||||
_cleanup_free_ uint8_t *p = NULL;
|
||||
uint32_t enterprise_identifier;
|
||||
size_t total, offset;
|
||||
char **s;
|
||||
char * const *s;
|
||||
|
||||
assert(buf);
|
||||
assert(*buf);
|
||||
assert(buflen);
|
||||
assert(vendor_class);
|
||||
assert(!strv_isempty(vendor_class));
|
||||
|
||||
enterprise_identifier = htobe32(SYSTEMD_PEN);
|
||||
|
||||
@ -253,6 +256,9 @@ int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **vendo
|
||||
size_t len = strlen(*s);
|
||||
uint8_t *q;
|
||||
|
||||
if (len > UINT16_MAX || len == 0)
|
||||
return -EINVAL;
|
||||
|
||||
q = realloc(p, total + len + 2);
|
||||
if (!q)
|
||||
return -ENOMEM;
|
||||
|
@ -274,7 +274,6 @@ int sd_dhcp_client_set_request_address(
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_ifindex(sd_dhcp_client *client, int ifindex) {
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED), -EBUSY);
|
||||
assert_return(ifindex > 0, -EINVAL);
|
||||
@ -348,13 +347,14 @@ int sd_dhcp_client_get_client_id(
|
||||
assert_return(data, -EINVAL);
|
||||
assert_return(data_len, -EINVAL);
|
||||
|
||||
*type = 0;
|
||||
*data = NULL;
|
||||
*data_len = 0;
|
||||
if (client->client_id_len) {
|
||||
*type = client->client_id.type;
|
||||
*data = client->client_id.raw.data;
|
||||
*data_len = client->client_id_len - sizeof(client->client_id.type);
|
||||
} else {
|
||||
*type = 0;
|
||||
*data = NULL;
|
||||
*data_len = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -573,22 +573,26 @@ int sd_dhcp_client_set_mud_url(
|
||||
|
||||
int sd_dhcp_client_set_user_class(
|
||||
sd_dhcp_client *client,
|
||||
const char* const* user_class) {
|
||||
char * const *user_class) {
|
||||
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
char **p;
|
||||
char * const *p;
|
||||
char **s = NULL;
|
||||
|
||||
STRV_FOREACH(p, (char **) user_class)
|
||||
if (strlen(*p) > 255)
|
||||
return -ENAMETOOLONG;
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(!strv_isempty(user_class), -EINVAL);
|
||||
|
||||
s = strv_copy((char **) user_class);
|
||||
STRV_FOREACH(p, user_class) {
|
||||
size_t n = strlen(*p);
|
||||
|
||||
if (n > 255 || n == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s = strv_copy(user_class);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
client->user_class = TAKE_PTR(s);
|
||||
|
||||
return 0;
|
||||
return strv_free_and_replace(client->user_class, s);
|
||||
}
|
||||
|
||||
int sd_dhcp_client_set_client_port(
|
||||
|
@ -157,7 +157,6 @@ int sd_dhcp6_client_set_callback(
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_ifindex(sd_dhcp6_client *client, int ifindex) {
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(ifindex > 0, -EINVAL);
|
||||
assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY);
|
||||
@ -351,6 +350,7 @@ int sd_dhcp6_client_duid_as_string(
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(client->duid_len > 0, -ENODATA);
|
||||
assert_return(duid, -EINVAL);
|
||||
|
||||
v = dhcp6_duid_type_to_string(be16toh(client->duid.type));
|
||||
if (v) {
|
||||
@ -454,7 +454,6 @@ int sd_dhcp6_client_set_request_option(sd_dhcp6_client *client, uint16_t option)
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mudurl) {
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
|
||||
assert_return(mudurl, -EINVAL);
|
||||
@ -464,47 +463,48 @@ int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mud
|
||||
return free_and_strdup(&client->mudurl, mudurl);
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_class) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
char **p;
|
||||
int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char * const *user_class) {
|
||||
char * const *p;
|
||||
char **s;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
|
||||
assert_return(!strv_isempty(user_class), -EINVAL);
|
||||
|
||||
assert_return(user_class, -EINVAL);
|
||||
STRV_FOREACH(p, user_class) {
|
||||
size_t len = strlen(*p);
|
||||
|
||||
STRV_FOREACH(p, user_class)
|
||||
if (strlen(*p) > UINT16_MAX)
|
||||
return -ENAMETOOLONG;
|
||||
if (len > UINT16_MAX || len == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s = strv_copy(user_class);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
client->user_class = TAKE_PTR(s);
|
||||
|
||||
return 0;
|
||||
return strv_free_and_replace(client->user_class, s);
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_set_request_vendor_class(sd_dhcp6_client *client, char **vendor_class) {
|
||||
_cleanup_strv_free_ char **s = NULL;
|
||||
char **p;
|
||||
int sd_dhcp6_client_set_request_vendor_class(sd_dhcp6_client *client, char * const *vendor_class) {
|
||||
char * const *p;
|
||||
char **s;
|
||||
|
||||
assert_return(client, -EINVAL);
|
||||
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
|
||||
assert_return(vendor_class, -EINVAL);
|
||||
assert_return(!strv_isempty(vendor_class), -EINVAL);
|
||||
|
||||
STRV_FOREACH(p, vendor_class)
|
||||
if (strlen(*p) > UINT8_MAX)
|
||||
return -ENAMETOOLONG;
|
||||
STRV_FOREACH(p, vendor_class) {
|
||||
size_t len = strlen(*p);
|
||||
|
||||
if (len > UINT16_MAX || len == 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s = strv_copy(vendor_class);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
client->vendor_class = TAKE_PTR(s);
|
||||
|
||||
return 0;
|
||||
return strv_free_and_replace(client->vendor_class, s);
|
||||
}
|
||||
|
||||
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {
|
||||
|
@ -507,7 +507,7 @@ int config_parse_iaid(const char *unit,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_dhcp_user_class(
|
||||
int config_parse_dhcp_user_or_vendor_class(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
@ -525,6 +525,7 @@ int config_parse_dhcp_user_class(
|
||||
assert(l);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
assert(IN_SET(ltype, AF_INET, AF_INET6));
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*l = strv_free(*l);
|
||||
@ -533,6 +534,7 @@ int config_parse_dhcp_user_class(
|
||||
|
||||
for (const char *p = rvalue;;) {
|
||||
_cleanup_free_ char *w = NULL;
|
||||
size_t len;
|
||||
|
||||
r = extract_first_word(&p, &w, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
|
||||
if (r == -ENOMEM)
|
||||
@ -545,76 +547,24 @@ int config_parse_dhcp_user_class(
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
len = strlen(w);
|
||||
if (ltype == AF_INET) {
|
||||
if (strlen(w) > UINT8_MAX) {
|
||||
if (len > UINT8_MAX || len == 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"%s length is not in the range 1-255, ignoring.", w);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (strlen(w) > UINT16_MAX) {
|
||||
if (len > UINT16_MAX || len == 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"%s length is not in the range 1-65535, ignoring.", w);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
r = strv_push(l, w);
|
||||
r = strv_consume(l, TAKE_PTR(w));
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
w = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int config_parse_dhcp_vendor_class(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
const char *section,
|
||||
unsigned section_line,
|
||||
const char *lvalue,
|
||||
int ltype,
|
||||
const char *rvalue,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
char ***l = data;
|
||||
int r;
|
||||
|
||||
assert(l);
|
||||
assert(lvalue);
|
||||
assert(rvalue);
|
||||
|
||||
if (isempty(rvalue)) {
|
||||
*l = strv_free(*l);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (const char *p = rvalue;;) {
|
||||
_cleanup_free_ char *w = NULL;
|
||||
|
||||
r = extract_first_word(&p, &w, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
|
||||
if (r == -ENOMEM)
|
||||
return log_oom();
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||
"Failed to split vendor classes option, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
if (r == 0)
|
||||
return 0;
|
||||
|
||||
if (strlen(w) > UINT8_MAX) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0,
|
||||
"%s length is not in the range 1-255, ignoring.", w);
|
||||
continue;
|
||||
}
|
||||
|
||||
r = strv_push(l, w);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
w = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,7 +66,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_domains);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_use_ntp);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_iaid);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_section_route_table);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_class);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_vendor_class);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_user_or_vendor_class);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_send_option);
|
||||
CONFIG_PARSER_PROTOTYPE(config_parse_dhcp_request_options);
|
||||
|
@ -1417,7 +1417,7 @@ int dhcp4_configure(Link *link) {
|
||||
}
|
||||
|
||||
if (link->network->dhcp_user_class) {
|
||||
r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
|
||||
r = sd_dhcp_client_set_user_class(link->dhcp_client, link->network->dhcp_user_class);
|
||||
if (r < 0)
|
||||
return log_link_warning_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
|
||||
}
|
||||
|
@ -204,7 +204,7 @@ DHCPv4.RequestBroadcast, config_parse_bool,
|
||||
DHCPv4.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCPv4.MUDURL, config_parse_dhcp_mud_url, 0, 0
|
||||
DHCPv4.MaxAttempts, config_parse_dhcp_max_attempts, 0, 0
|
||||
DHCPv4.UserClass, config_parse_dhcp_user_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
DHCPv4.UserClass, config_parse_dhcp_user_or_vendor_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
DHCPv4.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid)
|
||||
DHCPv4.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
|
||||
DHCPv4.RouteMetric, config_parse_dhcp_route_metric, 0, 0
|
||||
@ -227,8 +227,8 @@ DHCPv6.UseNTP, config_parse_dhcp_use_ntp,
|
||||
DHCPv6.RapidCommit, config_parse_bool, 0, offsetof(Network, dhcp6_rapid_commit)
|
||||
DHCPv6.MUDURL, config_parse_dhcp6_mud_url, 0, 0
|
||||
DHCPv6.RequestOptions, config_parse_dhcp_request_options, AF_INET6, 0
|
||||
DHCPv6.UserClass, config_parse_dhcp_user_class, AF_INET6, offsetof(Network, dhcp6_user_class)
|
||||
DHCPv6.VendorClass, config_parse_dhcp_vendor_class, 0, offsetof(Network, dhcp6_vendor_class)
|
||||
DHCPv6.UserClass, config_parse_dhcp_user_or_vendor_class, AF_INET6, offsetof(Network, dhcp6_user_class)
|
||||
DHCPv6.VendorClass, config_parse_dhcp_user_or_vendor_class, AF_INET6, offsetof(Network, dhcp6_vendor_class)
|
||||
DHCPv6.SendVendorOption, config_parse_dhcp_send_option, AF_INET6, offsetof(Network, dhcp6_client_send_vendor_options)
|
||||
DHCPv6.ForceDHCPv6PDOtherInformation, config_parse_bool, 0, offsetof(Network, dhcp6_force_pd_other_information)
|
||||
DHCPv6.PrefixDelegationHint, config_parse_dhcp6_pd_hint, 0, 0
|
||||
@ -467,7 +467,7 @@ DHCP.Hostname, config_parse_hostname,
|
||||
DHCP.RequestBroadcast, config_parse_bool, 0, offsetof(Network, dhcp_broadcast)
|
||||
DHCP.CriticalConnection, config_parse_tristate, 0, offsetof(Network, dhcp_critical)
|
||||
DHCP.VendorClassIdentifier, config_parse_string, 0, offsetof(Network, dhcp_vendor_class_identifier)
|
||||
DHCP.UserClass, config_parse_dhcp_user_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
DHCP.UserClass, config_parse_dhcp_user_or_vendor_class, AF_INET, offsetof(Network, dhcp_user_class)
|
||||
DHCP.DUIDType, config_parse_duid_type, 0, offsetof(Network, duid)
|
||||
DHCP.DUIDRawData, config_parse_duid_rawdata, 0, offsetof(Network, duid)
|
||||
DHCP.RouteMetric, config_parse_dhcp_route_metric, 0, 0
|
||||
|
@ -181,7 +181,7 @@ int sd_dhcp_client_set_mud_url(
|
||||
const char *mudurl);
|
||||
int sd_dhcp_client_set_user_class(
|
||||
sd_dhcp_client *client,
|
||||
const char* const *user_class);
|
||||
char * const *user_class);
|
||||
int sd_dhcp_client_get_lease(
|
||||
sd_dhcp_client *client,
|
||||
sd_dhcp_lease **ret);
|
||||
|
@ -133,10 +133,10 @@ int sd_dhcp6_client_set_request_mud_url(
|
||||
const char *mudurl);
|
||||
int sd_dhcp6_client_set_request_user_class(
|
||||
sd_dhcp6_client *client,
|
||||
char** user_class);
|
||||
char * const *user_class);
|
||||
int sd_dhcp6_client_set_request_vendor_class(
|
||||
sd_dhcp6_client *client,
|
||||
char** vendor_class);
|
||||
char * const *vendor_class);
|
||||
int sd_dhcp6_client_set_prefix_delegation_hint(
|
||||
sd_dhcp6_client *client,
|
||||
uint8_t prefixlen,
|
||||
|
Loading…
Reference in New Issue
Block a user