From: Amos Jeffries Date: Fri, 12 Jul 2019 03:08:00 +0000 (+0000) Subject: Prevent truncation for large origin-relative domains (#427) X-Git-Tag: SQUID_5_0_1~71 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=38aa10ef87e4e2eac60fe481f9def1c295a95c7e;p=thirdparty%2Fsquid.git Prevent truncation for large origin-relative domains (#427) The domain in a URL must obey hostname length restrictions after append_domain is applied, not just MAX_URL for the normalized absolute-URL. --- diff --git a/src/anyp/Uri.cc b/src/anyp/Uri.cc index 6ce8d9ba25..36d3fe2ac4 100644 --- a/src/anyp/Uri.cc +++ b/src/anyp/Uri.cc @@ -167,6 +167,30 @@ urlParseProtocol(const char *b) return AnyP::PROTO_NONE; } +/** + * Appends configured append_domain to hostname, assuming + * the given buffer is at least SQUIDHOSTNAMELEN bytes long, + * and that the host FQDN is not a 'dotless' TLD. + * + * \returns false if and only if there is not enough space to append + */ +bool +urlAppendDomain(char *host) +{ + /* For IPv4 addresses check for a dot */ + /* For IPv6 addresses also check for a colon */ + if (Config.appendDomain && !strchr(host, '.') && !strchr(host, ':')) { + const uint64_t dlen = strlen(host); + const uint64_t want = dlen + Config.appendDomainLen; + if (want > SQUIDHOSTNAMELEN - 1) { + debugs(23, 2, "URL domain too large (" << dlen << " bytes)"); + return false; + } + strncat(host, Config.appendDomain, SQUIDHOSTNAMELEN - dlen - 1); + } + return true; +} + /* * Parse a URI/URL. * @@ -376,9 +400,8 @@ AnyP::Uri::parse(const HttpRequestMethod& method, const char *url) return false; } - /* For IPV6 addresses also check for a colon */ - if (Config.appendDomain && !strchr(foundHost, '.') && !strchr(foundHost, ':')) - strncat(foundHost, Config.appendDomain, SQUIDHOSTNAMELEN - strlen(foundHost) - 1); + if (!urlAppendDomain(foundHost)) + return false; /* remove trailing dots from hostnames */ while ((l = strlen(foundHost)) > 0 && foundHost[--l] == '.') diff --git a/src/anyp/Uri.h b/src/anyp/Uri.h index 5765f7e453..9d28bb0013 100644 --- a/src/anyp/Uri.h +++ b/src/anyp/Uri.h @@ -193,6 +193,7 @@ bool urlIsRelative(const char *); char *urlMakeAbsolute(const HttpRequest *, const char *); char *urlRInternal(const char *host, unsigned short port, const char *dir, const char *name); char *urlInternal(const char *dir, const char *name); +bool urlAppendDomain(char *host); ///< apply append_domain config to the given hostname enum MatchDomainNameFlags { mdnNone = 0, diff --git a/src/internal.cc b/src/internal.cc index 5e18ab5995..053ce629e0 100644 --- a/src/internal.cc +++ b/src/internal.cc @@ -99,13 +99,9 @@ internalRemoteUri(bool encrypt, const char *host, unsigned short port, const cha /* * append the domain in order to mirror the requests with appended - * domains + * domains. If that fails, just use the hostname anyway. */ - - /* For IPv6 addresses also check for a colon */ - if (Config.appendDomain && !strchr(lc_host, '.') && !strchr(lc_host, ':')) - strncat(lc_host, Config.appendDomain, SQUIDHOSTNAMELEN - - strlen(lc_host) - 1); + (void)urlAppendDomain(lc_host); /* build URI */ AnyP::Uri tmp(AnyP::PROTO_HTTP);