From c7c5fa5dcaddf49cac4caaeac099faadea0d7574 Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Mon, 25 Mar 2013 20:49:18 +0530 Subject: [PATCH] fix for #571. Backport 8bbcdb61cf8e014294be0caf6d6e614ef778c7b4 changes from libhtp 0.5.x to Suricata's bundled libhtp. We now handle ipv6 addresses in uri and host header. --- libhtp/htp/htp_util.c | 146 +++++++++++++++++++++++++++++++----------- 1 file changed, 110 insertions(+), 36 deletions(-) diff --git a/libhtp/htp/htp_util.c b/libhtp/htp/htp_util.c index 9363001a45..b965c95609 100644 --- a/libhtp/htp/htp_util.c +++ b/libhtp/htp/htp_util.c @@ -534,22 +534,53 @@ int htp_parse_uri(bstr *input, htp_uri_t **uri) { hostname_len = pos - start; } - // Still parsing authority; is there a port provided? - m = memchr(hostname_start, ':', hostname_len); - if (m != NULL) { - size_t port_len = hostname_len - (m - hostname_start) - 1; - hostname_len = hostname_len - port_len - 1; + // Parsing authority without credentials. + if ((hostname_len > 0) && (hostname_start[0] == '[')) { + // IPv6 address. + + m = memchr(hostname_start, ']', hostname_len); + if (m == NULL) { + // Invalid IPv6 address; use the entire string as hostname. + (*uri)->hostname = bstr_memdup(hostname_start, hostname_len); + if ((*uri)->hostname == NULL) return HTP_ERROR; + } else { + (*uri)->hostname = bstr_memdup(hostname_start, m - hostname_start + 1); + if ((*uri)->hostname == NULL) return HTP_ERROR; - // Port string - (*uri)->port = bstr_memdup(m + 1, port_len); + // Is there a port? + hostname_len = hostname_len - (m - hostname_start + 1); + hostname_start = m + 1; - // We deliberately don't want to try to convert the port - // string as a number. That will be done later, during - // the normalization and validation process. - } + m = memchr(hostname_start, ':', hostname_len); + if (m != NULL) { + size_t port_len = hostname_len - (m - hostname_start) - 1; + hostname_len = hostname_len - port_len - 1; - // Hostname - (*uri)->hostname = bstr_memdup(hostname_start, hostname_len); + // Port string + (*uri)->port = bstr_memdup(m + 1, port_len); + if ((*uri)->port == NULL) return HTP_ERROR; + } + } + } else { + // Not IPv6 address. + + // Still parsing authority; is there a port provided? + m = memchr(hostname_start, ':', hostname_len); + if (m != NULL) { + size_t port_len = hostname_len - (m - hostname_start) - 1; + hostname_len = hostname_len - port_len - 1; + + // Port string + (*uri)->port = bstr_memdup(m + 1, port_len); + + // We deliberately don't want to try to convert the port + // string as a number. That will be done later, during + // the normalization and validation process. + } + + // Hostname + (*uri)->hostname = bstr_memdup(hostname_start, hostname_len); + } } // Path @@ -1594,30 +1625,73 @@ bstr *htp_normalize_hostname_inplace(bstr *hostname) { void htp_replace_hostname(htp_connp_t *connp, htp_uri_t *parsed_uri, bstr *hostname) { if (hostname == NULL) return; - int colon = bstr_chr(hostname, ':'); - if (colon == -1) { - // Hostname alone - parsed_uri->hostname = bstr_strdup(hostname); - htp_normalize_hostname_inplace(parsed_uri->hostname); - } else { - // Hostname - parsed_uri->hostname = bstr_strdup_ex(hostname, 0, colon); - // TODO Handle whitespace around hostname - htp_normalize_hostname_inplace(parsed_uri->hostname); - // Port - int port = htp_parse_positive_integer_whitespace((unsigned char *) bstr_ptr(hostname) + colon + 1, - bstr_len(hostname) - colon - 1, 10); - if (port < 0) { - // Failed to parse port - htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Invalid server port information in request"); - } else if ((port > 0) && (port < 65536)) { - // Valid port - if (port != connp->conn->local_port) { - // Port is different from the TCP port - htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Request server port number differs from the actual TCP port"); - } else { - parsed_uri->port_number = port; + char *hostname_start = bstr_ptr(hostname); + size_t hostname_len = bstr_len(hostname); + + if (hostname_len == 0) + return; + + if (hostname_start[0] == '[') { + // IPv6 address. + + char *m = memchr(hostname_start, ']', hostname_len); + if (m == NULL) { + // Invalid IPv6 address; use the entire string as hostname. + parsed_uri->hostname = bstr_memdup(hostname_start, hostname_len); + } else { + parsed_uri->hostname = bstr_memdup(hostname_start, m - hostname_start + 1); + // TODO Handle whitespace around hostname + htp_normalize_hostname_inplace(parsed_uri->hostname); + + // Is there a port? + hostname_len = hostname_len - (m - hostname_start + 1); + hostname_start = m + 1; + + m = memchr(hostname_start, ':', hostname_len); + if (m != NULL) { + size_t port_len = hostname_len - (m - hostname_start) - 1; + + int port = htp_parse_positive_integer_whitespace((unsigned char *)m + 1, port_len, 10); + if (port < 0) { + // Failed to parse port + htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Invalid server port information in request"); + } else if ((port > 0) && (port < 65536)) { + // Valid port + if (port != connp->conn->local_port) { + // Port is different from the TCP port + htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Request server port number differs from the actual TCP port"); + } else { + parsed_uri->port_number = port; + } + } + } + } + } else { + int colon = bstr_chr(hostname, ':'); + if (colon == -1) { + // Hostname alone + parsed_uri->hostname = bstr_strdup(hostname); + htp_normalize_hostname_inplace(parsed_uri->hostname); + } else { + // Hostname + parsed_uri->hostname = bstr_strdup_ex(hostname, 0, colon); + // TODO Handle whitespace around hostname + htp_normalize_hostname_inplace(parsed_uri->hostname); + + // Port + int port = htp_parse_positive_integer_whitespace((unsigned char *) bstr_ptr(hostname) + colon + 1, bstr_len(hostname) - colon - 1, 10); + if (port < 0) { + // Failed to parse port + htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Invalid server port information in request"); + } else if ((port > 0) && (port < 65536)) { + // Valid port + if (port != connp->conn->local_port) { + // Port is different from the TCP port + htp_log(connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "Request server port number differs from the actual TCP port"); + } else { + parsed_uri->port_number = port; + } } } } -- 2.47.3