ifnet: fix parsing dhcp configuration

- fix memleaks if the script contains duplicate lines
- only accept either dhclient or dhcpcd syntax, depending
  on the file
- be more strikt in parsing:
  - don't use strstr() when parsing dhcpcd.conf. It wrongly
    accepts "# send dhcp-client-identifier".
  - enfore that keyword are terminated by space. Would no longer
    accept "hostnameHOSTNAME"
- be less strict in parsing:
  - accept any number of spaces between "send" and "host-name"/
    "dhcp-client-identifier"

https://bugzilla.gnome.org/show_bug.cgi?id=738125

Signed-off-by: Thomas Haller <thaller@redhat.com>
This commit is contained in:
Thomas Haller
2014-10-08 11:09:13 +02:00
parent b6cf21543e
commit f77297ec85

View File

@@ -24,6 +24,7 @@
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
#include <nm-utils.h> #include <nm-utils.h>
#include <NetworkManagerUtils.h>
#include <nm-system-config-interface.h> #include <nm-system-config-interface.h>
#include <nm-logging.h> #include <nm-logging.h>
#include <nm-config.h> #include <nm-config.h>
@@ -760,30 +761,49 @@ is_managed (const char *conn_name)
return TRUE; return TRUE;
} }
static char *
_has_prefix_impl (char *str, const char *prefix, gsize prefix_len)
{
if (!g_str_has_prefix (str, prefix))
return NULL;
str += prefix_len;
if (!g_ascii_isspace (str[0]))
return NULL;
do {
str++;
} while (g_ascii_isspace (str[0]));
return str;
}
#define _has_prefix(STR, PREFIX) _has_prefix_impl (STR, PREFIX, STRLEN (PREFIX))
void void
get_dhcp_hostname_and_client_id (char **hostname, char **client_id) get_dhcp_hostname_and_client_id (char **hostname, char **client_id)
{ {
const char *dhcp_client; const char *dhcp_client;
const gchar *dhcpcd_conf = SYSCONFDIR "/dhcpcd.conf"; const gchar *dhcpcd_conf = SYSCONFDIR "/dhcpcd.conf";
const gchar *dhclient_conf = SYSCONFDIR "/dhcp/dhclient.conf"; const gchar *dhclient_conf = SYSCONFDIR "/dhcp/dhclient.conf";
gchar *line = NULL, *tmp = NULL, *contents = NULL; gchar *line = NULL, *tmp = NULL, *contents = NULL, *tmp1;
gchar **all_lines; gchar **all_lines;
guint line_num, i; guint line_num, i;
gboolean use_dhclient = FALSE;
*hostname = NULL; *hostname = NULL;
*client_id = NULL; *client_id = NULL;
dhcp_client = nm_config_get_dhcp_client (nm_config_get ()); dhcp_client = nm_config_get_dhcp_client (nm_config_get ());
if (dhcp_client) { if (dhcp_client) {
if (!strcmp (dhcp_client, "dhclient")) if (!strcmp (dhcp_client, "dhclient")) {
g_file_get_contents (dhclient_conf, &contents, NULL, g_file_get_contents (dhclient_conf, &contents, NULL,
NULL); NULL);
else if (!strcmp (dhcp_client, "dhcpcd")) use_dhclient = TRUE;
} else if (!strcmp (dhcp_client, "dhcpcd"))
g_file_get_contents (dhcpcd_conf, &contents, NULL, g_file_get_contents (dhcpcd_conf, &contents, NULL,
NULL); NULL);
} else { } else {
if (g_file_test (dhclient_conf, G_FILE_TEST_IS_REGULAR)) if (g_file_test (dhclient_conf, G_FILE_TEST_IS_REGULAR)) {
g_file_get_contents (dhclient_conf, &contents, NULL, g_file_get_contents (dhclient_conf, &contents, NULL,
NULL); NULL);
use_dhclient = TRUE;
}
else if (g_file_test (dhcpcd_conf, G_FILE_TEST_IS_REGULAR)) else if (g_file_test (dhcpcd_conf, G_FILE_TEST_IS_REGULAR))
g_file_get_contents (dhcpcd_conf, &contents, NULL, g_file_get_contents (dhcpcd_conf, &contents, NULL,
NULL); NULL);
@@ -794,44 +814,46 @@ get_dhcp_hostname_and_client_id (char **hostname, char **client_id)
line_num = g_strv_length (all_lines); line_num = g_strv_length (all_lines);
for (i = 0; i < line_num; i++) { for (i = 0; i < line_num; i++) {
line = all_lines[i]; line = all_lines[i];
// dhcpcd.conf
g_strstrip (line); g_strstrip (line);
if (g_str_has_prefix (line, "hostname")) { if (line[0] == '#' || line[0] == '\0')
tmp = line + strlen ("hostname"); continue;
g_strstrip (tmp); if (!use_dhclient) {
if (tmp[0] != '\0') // dhcpcd.conf
if ((tmp = _has_prefix (line, "hostname"))) {
if (tmp[0] != '\0') {
g_free (*hostname);
*hostname = g_strdup (tmp); *hostname = g_strdup (tmp);
else } else
nm_log_info (LOGD_SETTINGS, "dhcpcd hostname not defined, ignoring"); nm_log_info (LOGD_SETTINGS, "dhcpcd hostname not defined, ignoring");
} else if (g_str_has_prefix (line, "clientid")) { } else if ((tmp = _has_prefix (line, "clientid"))) {
tmp = line + strlen ("clientid"); if (tmp[0] != '\0') {
g_strstrip (tmp); g_free (*client_id);
if (tmp[0] != '\0')
*client_id = g_strdup (tmp); *client_id = g_strdup (tmp);
else } else
nm_log_info (LOGD_SETTINGS, "dhcpcd clientid not defined, ignoring"); nm_log_info (LOGD_SETTINGS, "dhcpcd clientid not defined, ignoring");
} }
} else {
// dhclient.conf // dhclient.conf
else if ((tmp = strstr (line, "send host-name")) != NULL) { if ((tmp1 = _has_prefix (line, "send"))) {
tmp += strlen ("send host-name"); if ((tmp = _has_prefix (tmp1, "host-name"))) {
g_strstrip (tmp);
strip_string (tmp, ';'); strip_string (tmp, ';');
strip_string (tmp, '"'); strip_string (tmp, '"');
if (tmp[0] != '\0') if (tmp[0] != '\0') {
g_free (*hostname);
*hostname = g_strdup (tmp); *hostname = g_strdup (tmp);
else } else
nm_log_info (LOGD_SETTINGS, "dhclient hostname not defined, ignoring"); nm_log_info (LOGD_SETTINGS, "dhclient hostname not defined, ignoring");
} else if ((tmp = strstr (line, "send dhcp-client-identifier")) } else if ((tmp = _has_prefix (tmp1, "dhcp-client-identifier"))) {
!= NULL) {
tmp += strlen ("send dhcp-client-identifier");
g_strstrip (tmp);
strip_string (tmp, ';'); strip_string (tmp, ';');
if (tmp[0] != '\0') if (tmp[0] != '\0') {
g_free (*client_id);
*client_id = g_strdup (tmp); *client_id = g_strdup (tmp);
else } else
nm_log_info (LOGD_SETTINGS, "dhclient clientid not defined, ignoring"); nm_log_info (LOGD_SETTINGS, "dhclient clientid not defined, ignoring");
} }
} }
}
}
g_strfreev (all_lines); g_strfreev (all_lines);
g_free (contents); g_free (contents);
} }