diff options
| author | 2022-04-02 21:40:30 +0200 | |
|---|---|---|
| committer | 2022-04-02 21:40:30 +0200 | |
| commit | 2aba861bc983555faf6dd96c5daa4e40e5328c54 (patch) | |
| tree | 68d63f76d0ce79e06cb3cabaaaeb3cd82849c175 | |
| parent | 191abf5ba541107c5a1c5f14202b99e17bee2074 (diff) | |
Add HTTP_REMOTE_USER header for auth (#4063)
* add HTTP_REMOTE_USER header for auth
* add ip whitelist for HTTP_REMOTE_USER header
* add IPv6 support for header auth
* fix formatting
* A few fixes
* Add some default trusted sources
* Fix IPv6 doc
* More standard header names
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
| -rw-r--r-- | app/Models/SystemConfiguration.php | 1 | ||||
| -rw-r--r-- | config.default.php | 8 | ||||
| -rw-r--r-- | docs/en/admins/09_AccessControl.md | 12 | ||||
| -rw-r--r-- | lib/lib_rss.php | 55 |
4 files changed, 74 insertions, 2 deletions
diff --git a/app/Models/SystemConfiguration.php b/app/Models/SystemConfiguration.php index 3b07bc9ff..3170a4180 100644 --- a/app/Models/SystemConfiguration.php +++ b/app/Models/SystemConfiguration.php @@ -22,6 +22,7 @@ * @property-read string $salt * @property-read bool $simplepie_syslog_enabled * @property string $unsafe_autologin_enabled + * @property-read array<string> $trusted_sources */ class FreshRSS_SystemConfiguration extends Minz_Configuration { diff --git a/config.default.php b/config.default.php index a9f6a12ec..df8e9133e 100644 --- a/config.default.php +++ b/config.default.php @@ -189,4 +189,12 @@ return array( # Disable self-update, 'disable_update' => false, + + # Trusted IPs that are allowed to send unsafe headers + # Please read the documentation, before configuring this + # https://freshrss.github.io/FreshRSS/en/admins/09_AccessControl.html + 'trusted_sources' => [ + '127.0.0.0/8', + '::1/128', + ] ); diff --git a/docs/en/admins/09_AccessControl.md b/docs/en/admins/09_AccessControl.md index 8ee193cea..4bd4dc8b5 100644 --- a/docs/en/admins/09_AccessControl.md +++ b/docs/en/admins/09_AccessControl.md @@ -15,13 +15,23 @@ You may also choose to use HTTP Authentication provided by your web server.[^1] If you choose to use this option, create a `./p/i/.htaccess` file with a matching `.htpasswd` file. -You can also use any authentication backend as long as your web server exposes the authenticated user through the `REMOTE_USER` variable. +You can also use any authentication backend as long as your web server exposes the authenticated user through the `Remote-User` variable. By default, new users allowed by HTTP Basic Auth will automatically be created in FreshRSS the first time they log in. You can disable auto-registration of new users by setting `http_auth_auto_register` to `false` in the configuration file. When using auto-registration, you can optionally use the `http_auth_auto_register_email_field` to specify the name of a web server variable containing the email address of the authenticated user (e.g. `REMOTE_USER_EMAIL`). +## External Authentication + +You may also use the `Remote-User` or `X-WebAuth-User` header to integrate with a your reverse-proxy’s authentication. + +To enable this feature, you need to add the IP range (in CIDR notation) of your trusted proxy in the `trusted_sources` configuration option. +To allow only one IPv4, you can use a `/32` like this: `trusted_sources => [ '192.168.1.10/32' ]`. +Likewise to allow only one IPv6, you can use a `/128` like this: `trusted_sources => [ '::1/128' ]`. + +WARNING: FreshRSS will trust any IP configured in the `trusted_sources` option, if your proxy isn’t properly secured, an attacker could simply attach this header and get admin access. + ## No Authentication Not using authentication on your server is dangerous, as anyone with access to your server would be able to make changes as an admin. diff --git a/lib/lib_rss.php b/lib/lib_rss.php index b6fde6437..677e4a413 100644 --- a/lib/lib_rss.php +++ b/lib/lib_rss.php @@ -555,14 +555,67 @@ function get_user_configuration($username) { } /** + * Converts an IP (v4 or v6) to a binary representation using inet_pton + * + * @param string $ip the IP to convert + * @return string a binary representation of the specified IP + */ +function ipToBits(string $ip): string { + $binaryip = ''; + foreach (str_split(inet_pton($ip)) as $char) { + $binaryip .= str_pad(decbin(ord($char)), 8, '0', STR_PAD_LEFT); + } + return $binaryip; +} + +/** + * Check if an ip belongs to the provided range (in CIDR format) + * + * @param string $ip the IP that we want to verify (ex: 192.168.16.1) + * @param string $range the range to check against (ex: 192.168.16.0/24) + * @return boolean true if the IP is in the range, otherwise false + */ +function checkCIDR(string $ip, string $range): bool { + $binary_ip = ipToBits($ip); + list($subnet, $mask_bits) = explode('/', $range); + $mask_bits = intval($mask_bits); + $binary_subnet = ipToBits($subnet); + + $ip_net_bits = substr($binary_ip, 0, $mask_bits); + $subnet_bits = substr($binary_subnet, 0, $mask_bits); + + return $ip_net_bits === $subnet_bits; +} + +/** + * Check if the client is allowed to send unsafe headers + * This uses the REMOTE_ADDR header to determine the sender's IP + * and the configuration option "trusted_sources" to get an array of the authorized ranges + * + * @return boolean, true if the sender's IP is in one of the ranges defined in the configuration, else false + */ +function checkTrustedIP(): bool { + if (!empty($_SERVER['REMOTE_ADDR'])) { + foreach (FreshRSS_Context::$system_conf->trusted_sources as $cidr) { + if (checkCIDR($_SERVER['REMOTE_ADDR'], $cidr)) { + return true; + } + } + } + return false; +} + +/** * @return string */ function httpAuthUser() { if (!empty($_SERVER['REMOTE_USER'])) { return $_SERVER['REMOTE_USER']; + } elseif (!empty($_SERVER['HTTP_REMOTE_USER']) && checkTrustedIP()) { + return $_SERVER['HTTP_REMOTE_USER']; } elseif (!empty($_SERVER['REDIRECT_REMOTE_USER'])) { return $_SERVER['REDIRECT_REMOTE_USER']; - } elseif (!empty($_SERVER['HTTP_X_WEBAUTH_USER'])) { + } elseif (!empty($_SERVER['HTTP_X_WEBAUTH_USER']) && checkTrustedIP()) { return $_SERVER['HTTP_X_WEBAUTH_USER']; } return ''; |
