diff options
author | Oliver Wegner <void1976@gmail.com> | 2018-10-25 11:36:52 +0200 |
---|---|---|
committer | Oliver Wegner <void1976@gmail.com> | 2018-10-30 09:15:42 +0100 |
commit | 401ca28f0773787146186bd568fd7901029dc5cd (patch) | |
tree | a7df757f5ee3805178f388d721f49293fb4aa2c4 /lib | |
parent | 58fde16226351e085aff60bca0d778f30704c4a8 (diff) | |
download | nextcloud-server-401ca28f0773787146186bd568fd7901029dc5cd.tar.gz nextcloud-server-401ca28f0773787146186bd568fd7901029dc5cd.zip |
Adding handling of CIDR notation to trusted_proxies for IPv4
Signed-off-by: Oliver Wegner <void1976@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/private/AppFramework/Http/Request.php | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/lib/private/AppFramework/Http/Request.php b/lib/private/AppFramework/Http/Request.php index 0485d178b49..f3d4ace252f 100644 --- a/lib/private/AppFramework/Http/Request.php +++ b/lib/private/AppFramework/Http/Request.php @@ -595,6 +595,44 @@ class Request implements \ArrayAccess, \Countable, IRequest { } /** + * Checks if given $remoteAddress matches given $trustedProxy. + * If $trustedProxy is an IPv4 IP range given in CIDR notation, true will be returned if + * $remoteAddress is an IPv4 address within that IP range. + * Otherwise $remoteAddress will be compared to $trustedProxy literally and the result + * will be returned. + * @return boolean true if $remoteAddress matches $trustedProxy, false otherwise + */ + protected function matchesTrustedProxy($trustedProxy, $remoteAddress) { + $cidrre = '/^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})\/([0-9]{1,2})$/'; + + if (preg_match($cidrre, $trustedProxy, $match)) { + $net = $match[1]; + $shiftbits = min(32, max(0, 32 - intval($match[2]))); + $netnum = ip2long($net) >> $shiftbits; + $ipnum = ip2long($remoteAddress) >> $shiftbits; + + return $ipnum === $netnum; + } + + return $trustedProxy === $remoteAddress; + } + + /** + * Checks if given $remoteAddress matches any entry in the given array $trustedProxies. + * For details regarding what "match" means, refer to `matchesTrustedProxy`. + * @return boolean true if $remoteAddress matches any entry in $trustedProxies, false otherwise + */ + protected function isTrustedProxy($trustedProxies, $remoteAddress) { + foreach ($trustedProxies as $tp) { + if ($this->matchesTrustedProxy($tp, $remoteAddress)) { + return true; + } + } + + return false; + } + + /** * Returns the remote address, if the connection came from a trusted proxy * and `forwarded_for_headers` has been configured then the IP address * specified in this header will be returned instead. @@ -605,7 +643,7 @@ class Request implements \ArrayAccess, \Countable, IRequest { $remoteAddress = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : ''; $trustedProxies = $this->config->getSystemValue('trusted_proxies', []); - if(\is_array($trustedProxies) && \in_array($remoteAddress, $trustedProxies)) { + if(\is_array($trustedProxies) && $this->isTrustedProxy($trustedProxies, $remoteAddress)) { $forwardedForHeaders = $this->config->getSystemValue('forwarded_for_headers', [ 'HTTP_X_FORWARDED_FOR' // only have one default, so we cannot ship an insecure product out of the box |