mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-01-18 05:10:32 +01:00
dhcp: cleanup handling of ipv4.dhcp-client-id and avoid assertion failure
The internal client asserts that the length of the client ID is not more
than MAX_CLIENT_ID_LEN. Avoid that assert by truncating the string.
Also add new nm_dhcp_client_set_client_id_*() setters, that either
set the ID based on a string (in our common dhclient specific
format), or based on the binary data (as obtained from systemd client).
Also, add checks and assertions that the client ID which is
set via nm_dhcp_client_set_client_id() is always of length
of at least 2 (as required by rfc2132, section-9.14).
(cherry picked from commit 686afe531a)
This commit is contained in:
parent
207eb3266f
commit
41a89aeeba
8 changed files with 88 additions and 28 deletions
|
|
@ -191,7 +191,7 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (priv->dhcp_client_id && !strlen (priv->dhcp_client_id)) {
|
||||
if (priv->dhcp_client_id && !priv->dhcp_client_id[0]) {
|
||||
g_set_error_literal (error,
|
||||
NM_CONNECTION_ERROR,
|
||||
NM_CONNECTION_ERROR_INVALID_PROPERTY,
|
||||
|
|
|
|||
|
|
@ -186,19 +186,69 @@ nm_dhcp_client_get_client_id (NMDhcpClient *self)
|
|||
return NM_DHCP_CLIENT_GET_PRIVATE (self)->client_id;
|
||||
}
|
||||
|
||||
static void
|
||||
_set_client_id (NMDhcpClient *self, GBytes *client_id, gboolean take)
|
||||
{
|
||||
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
|
||||
|
||||
nm_assert (!client_id || g_bytes_get_size (client_id) >= 2);
|
||||
|
||||
if ( priv->client_id == client_id
|
||||
|| ( priv->client_id
|
||||
&& g_bytes_equal (priv->client_id, client_id))) {
|
||||
if (take && client_id)
|
||||
g_bytes_unref (client_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->client_id)
|
||||
g_bytes_unref (priv->client_id);
|
||||
priv->client_id = client_id;
|
||||
if (!take && client_id)
|
||||
g_bytes_ref (client_id);
|
||||
}
|
||||
|
||||
void
|
||||
nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id)
|
||||
{
|
||||
NMDhcpClientPrivate *priv;
|
||||
g_return_if_fail (NM_IS_DHCP_CLIENT (self));
|
||||
g_return_if_fail (!client_id || g_bytes_get_size (client_id) >= 2);
|
||||
|
||||
_set_client_id (self, client_id, FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
nm_dhcp_client_set_client_id_bin (NMDhcpClient *self,
|
||||
guint8 type,
|
||||
const guint8 *client_id,
|
||||
gsize len)
|
||||
{
|
||||
guint8 *buf;
|
||||
GBytes *b;
|
||||
|
||||
g_return_if_fail (NM_IS_DHCP_CLIENT (self));
|
||||
g_return_if_fail (client_id);
|
||||
g_return_if_fail (len > 0);
|
||||
|
||||
priv = NM_DHCP_CLIENT_GET_PRIVATE (self);
|
||||
buf = g_malloc (len + 1);
|
||||
buf[0] = type;
|
||||
memcpy (buf + 1, client_id, len);
|
||||
b = g_bytes_new_take (buf, len + 1);
|
||||
_set_client_id (self, b, TRUE);
|
||||
}
|
||||
|
||||
if (priv->client_id && client_id && g_bytes_equal (priv->client_id, client_id))
|
||||
return;
|
||||
g_clear_pointer (&priv->client_id, g_bytes_unref);
|
||||
priv->client_id = client_id ? g_bytes_ref (client_id) : NULL;
|
||||
void
|
||||
nm_dhcp_client_set_client_id_str (NMDhcpClient *self,
|
||||
const char *dhcp_client_id)
|
||||
{
|
||||
g_return_if_fail (NM_IS_DHCP_CLIENT (self));
|
||||
g_return_if_fail (!dhcp_client_id || dhcp_client_id[0]);
|
||||
|
||||
_set_client_id (self,
|
||||
dhcp_client_id
|
||||
? nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id)
|
||||
: NULL,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
const char *
|
||||
|
|
@ -448,7 +498,6 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self,
|
|||
const char *last_ip4_address)
|
||||
{
|
||||
NMDhcpClientPrivate *priv;
|
||||
gs_unref_bytes GBytes *tmp = NULL;
|
||||
|
||||
g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE);
|
||||
|
||||
|
|
@ -462,9 +511,7 @@ nm_dhcp_client_start_ip4 (NMDhcpClient *self,
|
|||
else
|
||||
_LOGI ("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
|
||||
|
||||
if (dhcp_client_id)
|
||||
tmp = nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id);
|
||||
nm_dhcp_client_set_client_id (self, tmp);
|
||||
nm_dhcp_client_set_client_id_str (self, dhcp_client_id);
|
||||
|
||||
g_clear_pointer (&priv->hostname, g_free);
|
||||
priv->hostname = g_strdup (hostname);
|
||||
|
|
|
|||
|
|
@ -173,7 +173,14 @@ gboolean nm_dhcp_client_handle_event (gpointer unused,
|
|||
const char *reason,
|
||||
NMDhcpClient *self);
|
||||
|
||||
void nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id);
|
||||
void nm_dhcp_client_set_client_id (NMDhcpClient *self,
|
||||
GBytes *client_id);
|
||||
void nm_dhcp_client_set_client_id_bin (NMDhcpClient *self,
|
||||
guint8 type,
|
||||
const guint8 *client_id,
|
||||
gsize len);
|
||||
void nm_dhcp_client_set_client_id_str (NMDhcpClient *self,
|
||||
const char *dhcp_client_id);
|
||||
|
||||
/*****************************************************************************
|
||||
* Client data
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ read_client_id (const char *str)
|
|||
gs_free char *s = NULL;
|
||||
char *p;
|
||||
|
||||
g_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG)));
|
||||
nm_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG)));
|
||||
|
||||
str += NM_STRLEN (CLIENTID_TAG);
|
||||
while (g_ascii_isspace (*str))
|
||||
|
|
@ -198,6 +198,9 @@ read_client_id (const char *str)
|
|||
if (s[strlen (s) - 1] == ';')
|
||||
s[strlen (s) - 1] = '\0';
|
||||
|
||||
if (!s[0])
|
||||
return NULL;
|
||||
|
||||
return nm_dhcp_utils_client_id_string_to_bytes (s);
|
||||
}
|
||||
|
||||
|
|
@ -329,8 +332,7 @@ nm_dhcp_dhclient_create_config (const char *interface,
|
|||
continue;
|
||||
|
||||
/* Otherwise capture and return the existing client id */
|
||||
if (out_new_client_id)
|
||||
*out_new_client_id = read_client_id (p);
|
||||
NM_SET_OUT (out_new_client_id, read_client_id (p));
|
||||
}
|
||||
|
||||
/* Override config file hostname and use one from the connection */
|
||||
|
|
|
|||
|
|
@ -489,19 +489,13 @@ _save_client_id (NMDhcpSystemd *self,
|
|||
const uint8_t *client_id,
|
||||
size_t len)
|
||||
{
|
||||
gs_unref_bytes GBytes *b = NULL;
|
||||
gs_free char *buf = NULL;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (client_id != NULL);
|
||||
g_return_if_fail (len > 0);
|
||||
|
||||
if (!nm_dhcp_client_get_client_id (NM_DHCP_CLIENT (self))) {
|
||||
buf = g_malloc (len + 1);
|
||||
buf[0] = type;
|
||||
memcpy (buf + 1, client_id, len);
|
||||
b = g_bytes_new (buf, len + 1);
|
||||
nm_dhcp_client_set_client_id (NM_DHCP_CLIENT (self), b);
|
||||
nm_dhcp_client_set_client_id_bin (NM_DHCP_CLIENT (self),
|
||||
type, client_id, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -543,7 +537,7 @@ bound4_handle (NMDhcpSystemd *self)
|
|||
add_requests_to_options (options, dhcp4_requests);
|
||||
dhcp_lease_save (lease, priv->lease_file);
|
||||
|
||||
sd_dhcp_client_get_client_id(priv->client4, &type, &client_id, &client_id_len);
|
||||
sd_dhcp_client_get_client_id (priv->client4, &type, &client_id, &client_id_len);
|
||||
if (client_id)
|
||||
_save_client_id (self, type, client_id, client_id_len);
|
||||
|
||||
|
|
@ -691,14 +685,14 @@ ip4_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const char *last
|
|||
override_client_id = nm_dhcp_client_get_client_id (client);
|
||||
if (override_client_id) {
|
||||
client_id = g_bytes_get_data (override_client_id, &client_id_len);
|
||||
g_assert (client_id && client_id_len);
|
||||
nm_assert (client_id && client_id_len >= 2);
|
||||
sd_dhcp_client_set_client_id (priv->client4,
|
||||
client_id[0],
|
||||
client_id + 1,
|
||||
client_id_len - 1);
|
||||
NM_MIN (client_id_len - 1, _NM_SD_MAX_CLIENT_ID_LEN));
|
||||
} else if (lease) {
|
||||
r = sd_dhcp_lease_get_client_id (lease, (const void **) &client_id, &client_id_len);
|
||||
if (r == 0 && client_id_len) {
|
||||
if (r == 0 && client_id_len >= 2) {
|
||||
sd_dhcp_client_set_client_id (priv->client4,
|
||||
client_id[0],
|
||||
client_id + 1,
|
||||
|
|
|
|||
|
|
@ -750,8 +750,15 @@ nm_dhcp_utils_client_id_string_to_bytes (const char *client_id)
|
|||
g_return_val_if_fail (client_id && client_id[0], NULL);
|
||||
|
||||
/* Try as hex encoded */
|
||||
if (strchr (client_id, ':'))
|
||||
if (strchr (client_id, ':')) {
|
||||
bytes = nm_utils_hexstr2bin (client_id);
|
||||
|
||||
/* the result must be at least two bytes long,
|
||||
* because @client_id contains a delimiter
|
||||
* but nm_utils_hexstr2bin() does not allow
|
||||
* leading nor trailing delimiters. */
|
||||
nm_assert (!bytes || g_bytes_get_size (bytes) >= 2);
|
||||
}
|
||||
if (!bytes) {
|
||||
/* Fall back to string */
|
||||
len = strlen (client_id);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#error "nm-utils-private.h" must not be used outside of libnm-core/. Do you want "nm-core-internal.h"?
|
||||
#endif
|
||||
|
||||
#define _NM_SD_MAX_CLIENT_ID_LEN (sizeof (guint32) + 128)
|
||||
|
||||
/* core */
|
||||
typedef struct _NMExportedObject NMExportedObject;
|
||||
typedef struct _NMActiveConnection NMActiveConnection;
|
||||
|
|
|
|||
|
|
@ -311,6 +311,7 @@ int sd_dhcp_client_set_client_id(
|
|||
assert_return(client, -EINVAL);
|
||||
assert_return(data, -EINVAL);
|
||||
assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL);
|
||||
G_STATIC_ASSERT_EXPR (_NM_SD_MAX_CLIENT_ID_LEN == MAX_CLIENT_ID_LEN);
|
||||
|
||||
switch (type) {
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue