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,42 +814,44 @@ 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
*hostname = g_strdup (tmp); if ((tmp = _has_prefix (line, "hostname"))) {
else if (tmp[0] != '\0') {
nm_log_info (LOGD_SETTINGS, "dhcpcd hostname not defined, ignoring"); g_free (*hostname);
} else if (g_str_has_prefix (line, "clientid")) { *hostname = g_strdup (tmp);
tmp = line + strlen ("clientid"); } else
g_strstrip (tmp); nm_log_info (LOGD_SETTINGS, "dhcpcd hostname not defined, ignoring");
if (tmp[0] != '\0') } else if ((tmp = _has_prefix (line, "clientid"))) {
*client_id = g_strdup (tmp); if (tmp[0] != '\0') {
else g_free (*client_id);
nm_log_info (LOGD_SETTINGS, "dhcpcd clientid not defined, ignoring"); *client_id = g_strdup (tmp);
} } else
// dhclient.conf nm_log_info (LOGD_SETTINGS, "dhcpcd clientid not defined, ignoring");
else if ((tmp = strstr (line, "send host-name")) != NULL) { }
tmp += strlen ("send host-name"); } else {
g_strstrip (tmp); // dhclient.conf
strip_string (tmp, ';'); if ((tmp1 = _has_prefix (line, "send"))) {
strip_string (tmp, '"'); if ((tmp = _has_prefix (tmp1, "host-name"))) {
if (tmp[0] != '\0') strip_string (tmp, ';');
*hostname = g_strdup (tmp); strip_string (tmp, '"');
else if (tmp[0] != '\0') {
nm_log_info (LOGD_SETTINGS, "dhclient hostname not defined, ignoring"); g_free (*hostname);
} else if ((tmp = strstr (line, "send dhcp-client-identifier")) *hostname = g_strdup (tmp);
!= NULL) { } else
tmp += strlen ("send dhcp-client-identifier"); nm_log_info (LOGD_SETTINGS, "dhclient hostname not defined, ignoring");
g_strstrip (tmp); } else if ((tmp = _has_prefix (tmp1, "dhcp-client-identifier"))) {
strip_string (tmp, ';'); strip_string (tmp, ';');
if (tmp[0] != '\0') if (tmp[0] != '\0') {
*client_id = g_strdup (tmp); g_free (*client_id);
else *client_id = g_strdup (tmp);
nm_log_info (LOGD_SETTINGS, "dhclient clientid not defined, ignoring"); } else
nm_log_info (LOGD_SETTINGS, "dhclient clientid not defined, ignoring");
}
}
} }
} }
g_strfreev (all_lines); g_strfreev (all_lines);