--- plugins/loopback.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 66 insertions(+), 4 deletions(-)
diff --git a/plugins/loopback.c b/plugins/loopback.c index 1800c49..cba923c 100644 --- a/plugins/loopback.c +++ b/plugins/loopback.c @@ -32,6 +32,7 @@ #include <sys/socket.h> #include <arpa/inet.h> #include <net/if.h> +#include <ctype.h> #include <glib.h> @@ -204,14 +205,70 @@ static const char *loopback_get_hostname(void) return system_hostname; } +/* Check routine modified from ics-dhcp 4.2.3-P2 */ +static int check_name(const char *ptr, size_t len) +{ + const char *p; + + /* + * Not empty or complete length not over 255 characters. + */ + if ((len == 0) || (len > 256)) + return -1; + + /* + * Consists of [[:alnum:]-]+ labels separated by [.] + * a [_] is against RFC but seems to be "widely used" + */ + for (p = ptr; (*p != 0) && (len-- > 0); p++) { + + if ((*p == '-') || (*p == '_')) { + /* + * Not allowed at begin or end of a label. + */ + if (((p - ptr) == 0) || (len == 0) || (p[1] == '.')) + return -1; + + } else if (*p == '.') { + /* + * Each label has to be 1-63 characters; + * we allow [.] at the end ('foo.bar.') + */ + size_t d = p - ptr; + + if ((d <= 0) || (d >= 64)) + return -1; + + ptr = p + 1; /* Jump to the next label */ + + } else if (isalnum((unsigned char)*p) == 0) { + /* + * Also numbers at the begin are fine + */ + return -1; + } + } + + return 0; +} + static int loopback_set_hostname(const char *hostname) { - int err; + const char *ptr; + int err, len; if (g_strcmp0(hostname, "<hostname>") == 0) return 0; - if (sethostname(hostname, strlen(hostname)) < 0) { + len = strlen(hostname); + + if (check_name(hostname, len) != 0) + return -EINVAL; + + if ((ptr = strstr(hostname, ".")) != NULL) + len = ptr - hostname; + + if (sethostname(hostname, len) < 0) { err = -errno; connman_error("Failed to set hostname to %s", hostname); return err; @@ -224,9 +281,14 @@ static int loopback_set_hostname(const char *hostname) static int loopback_set_domainname(const char *domainname) { - int err; + int err, len; + + len = strlen(domainname); + + if (check_name(domainname, len) != 0) + return -EINVAL; - if (setdomainname(domainname, strlen(domainname)) < 0) { + if (setdomainname(domainname, len) < 0) { err = -errno; connman_error("Failed to set domainname to %s", domainname); return err; -- 1.7.5.4 _______________________________________________ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman