mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-07-29 16:13:39 +00:00
fix: cors allowed origins settings validation
This commit is contained in:
@@ -5856,7 +5856,7 @@ paths:
|
|||||||
response:
|
response:
|
||||||
value:
|
value:
|
||||||
- type: "success"
|
- type: "success"
|
||||||
log: ["cors", "edit", {"allowed_origins": ["*", "mail.mailcow.tld"], "allowed_methods": ["POST", "GET", "DELETE", "PUT"]}]
|
log: ["cors", "edit", {"allowed_origins": ["*", "https://mail.mailcow.tld"], "allowed_methods": ["POST", "GET", "DELETE", "PUT"]}]
|
||||||
msg: "cors_headers_edited"
|
msg: "cors_headers_edited"
|
||||||
description: OK
|
description: OK
|
||||||
headers: { }
|
headers: { }
|
||||||
@@ -5873,7 +5873,7 @@ paths:
|
|||||||
schema:
|
schema:
|
||||||
example:
|
example:
|
||||||
attr:
|
attr:
|
||||||
allowed_origins: ["*", "mail.mailcow.tld"]
|
allowed_origins: ["*", "https://mail.mailcow.tld"]
|
||||||
allowed_methods: ["POST", "GET", "DELETE", "PUT"]
|
allowed_methods: ["POST", "GET", "DELETE", "PUT"]
|
||||||
properties:
|
properties:
|
||||||
attr:
|
attr:
|
||||||
|
|||||||
@@ -53,6 +53,28 @@ function valid_network($network) {
|
|||||||
function valid_hostname($hostname) {
|
function valid_hostname($hostname) {
|
||||||
return filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
|
return filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
|
||||||
}
|
}
|
||||||
|
// Validates a browser-style Origin: scheme://host[:port], no path/query/fragment/credentials
|
||||||
|
function valid_origin($origin) {
|
||||||
|
$parts = parse_url($origin);
|
||||||
|
if ($parts === false || !isset($parts['scheme']) || !isset($parts['host'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!in_array(strtolower($parts['scheme']), array('http', 'https'), true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isset($parts['user']) || isset($parts['pass']) || isset($parts['path']) || isset($parts['query']) || isset($parts['fragment'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$host = $parts['host'];
|
||||||
|
$host_without_brackets = trim($host, '[]');
|
||||||
|
if (!valid_hostname($host_without_brackets) && !filter_var($host_without_brackets, FILTER_VALIDATE_IP)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Reject anything that doesn't round-trip to the exact same origin (e.g. stray trailing slash)
|
||||||
|
$port = isset($parts['port']) ? ':' . $parts['port'] : '';
|
||||||
|
$rebuilt = strtolower($parts['scheme']) . '://' . strtolower($host) . $port;
|
||||||
|
return strtolower($origin) === $rebuilt;
|
||||||
|
}
|
||||||
// Thanks to https://stackoverflow.com/a/49373789
|
// Thanks to https://stackoverflow.com/a/49373789
|
||||||
// Validates exact ip matches and ip-in-cidr, ipv4 and ipv6
|
// Validates exact ip matches and ip-in-cidr, ipv4 and ipv6
|
||||||
function ip_acl($ip, $networks) {
|
function ip_acl($ip, $networks) {
|
||||||
@@ -2283,10 +2305,13 @@ function cors($action, $data = null) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$allowed_origins = isset($data['allowed_origins']) ? $data['allowed_origins'] : array($_SERVER['SERVER_NAME']);
|
$allowed_origins = isset($data['allowed_origins']) ? $data['allowed_origins'] : array(getBaseURL());
|
||||||
$allowed_origins = !is_array($allowed_origins) ? array_filter(array_map('trim', explode("\n", $allowed_origins))) : $allowed_origins;
|
$allowed_origins = !is_array($allowed_origins) ? array_filter(array_map('trim', explode("\n", $allowed_origins))) : $allowed_origins;
|
||||||
foreach ($allowed_origins as $origin) {
|
foreach ($allowed_origins as &$origin) {
|
||||||
if (!filter_var($origin, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME) && $origin != '*') {
|
if ($origin === '*') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!valid_origin($origin)) {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
'log' => array(__FUNCTION__, $action, $data),
|
'log' => array(__FUNCTION__, $action, $data),
|
||||||
@@ -2294,7 +2319,10 @@ function cors($action, $data = null) {
|
|||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// browsers always send a lowercase scheme/host in the Origin header, so normalize to match
|
||||||
|
$origin = strtolower($origin);
|
||||||
}
|
}
|
||||||
|
unset($origin);
|
||||||
|
|
||||||
$allowed_methods = isset($data['allowed_methods']) ? $data['allowed_methods'] : array('GET', 'POST', 'PUT', 'DELETE');
|
$allowed_methods = isset($data['allowed_methods']) ? $data['allowed_methods'] : array('GET', 'POST', 'PUT', 'DELETE');
|
||||||
$allowed_methods = !is_array($allowed_methods) ? array_map('trim', preg_split( "/( |,|;|\n)/", $allowed_methods)) : $allowed_methods;
|
$allowed_methods = !is_array($allowed_methods) ? array_map('trim', preg_split( "/( |,|;|\n)/", $allowed_methods)) : $allowed_methods;
|
||||||
|
|||||||
Reference in New Issue
Block a user