From a3a51b841498d33104c3252c5f8432535d6120a5 Mon Sep 17 00:00:00 2001 From: Max Lv Date: Tue, 6 Sep 2016 09:01:51 +0800 Subject: [PATCH] Refine hostname validation --- src/netutils.c | 41 +++++++++++++++++++++++++++++++---------- src/netutils.h | 2 +- src/server.c | 4 ++-- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/netutils.c b/src/netutils.c index bd4fbe68..c5db8967 100644 --- a/src/netutils.c +++ b/src/netutils.c @@ -54,6 +54,9 @@ extern int verbose; +static const char valid_label_bytes[] = +"-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"; + #if defined(MODULE_LOCAL) extern int keep_resolving; #endif @@ -252,20 +255,38 @@ int sockaddr_cmp_addr(struct sockaddr_storage *addr1, } } -int validate_domain_name(const char *hostname, const int len) +int validate_hostname(const char *hostname, const int hostname_len) { - int i; - for (i = 0; i < len; i++) - { - char c = hostname[i]; + if (hostname == NULL) + return 0; + + if (hostname_len < 1 || hostname_len > 255) + return 0; + + if (hostname[0] == '.') + return 0; + + const char *label = hostname; + while (label < hostname + hostname_len) { + size_t label_len = hostname_len - (label - hostname); + char *next_dot = strchr(label, '.'); + if (next_dot != NULL) + label_len = next_dot - label; - int is_hyphen = c == 0x2D; - int is_stop = c == 0x2E; - int is_digit = c >= 0x30 && c <= 0x39; - int is_letter = (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); + if (label + label_len > hostname + hostname_len) + return 0; + + if (label_len > 63 || label_len < 1) + return 0; - if (!is_hyphen && !is_stop && !is_digit && !is_letter) + if (label[0] == '-' || label[label_len - 1] == '-') return 0; + + if (strspn(label, valid_label_bytes) < label_len) + return 0; + + label += label_len + 1; } + return 1; } diff --git a/src/netutils.h b/src/netutils.h index aed08781..e9bc3947 100644 --- a/src/netutils.h +++ b/src/netutils.h @@ -93,6 +93,6 @@ int sockaddr_cmp(struct sockaddr_storage *addr1, int sockaddr_cmp_addr(struct sockaddr_storage *addr1, struct sockaddr_storage *addr2, socklen_t len); -int validate_domain_name(const char *hostname, const int len); +int validate_hostname(const char *hostname, const int hostname_len); #endif diff --git a/src/server.c b/src/server.c index f4cf53df..e9f33f94 100644 --- a/src/server.c +++ b/src/server.c @@ -781,8 +781,8 @@ static void server_recv_cb(EV_P_ ev_io *w, int revents) close_and_free_server(EV_A_ server); return; } - if (!validate_domain_name(host, name_len)) { - LOGE("invalid domain name"); + if (!validate_hostname(host, name_len)) { + LOGE("invalid host name"); report_addr(server->fd); close_and_free_server(EV_A_ server); return;