Allow HTTP headers to be configurable

This commit is contained in:
Tara Mallesh
2022-07-02 04:02:56 +00:00
committed by Feng Xie
parent 413edf38bf
commit cfe2ea06d9
5 changed files with 51 additions and 16 deletions

View File

@@ -734,3 +734,18 @@ ipv4-network = 192.168.2.0
ipv4-netmask = 255.255.255.0 ipv4-netmask = 255.255.255.0
cert-user-oid = 0.9.2342.19200300.100.1.1 cert-user-oid = 0.9.2342.19200300.100.1.1
# HTTP headers
included-http-headers = Strict-Transport-Security: max-age=31536000 ; includeSubDomains
included-http-headers = X-Frame-Options: deny
included-http-headers = X-Content-Type-Options: nosniff
included-http-headers = Content-Security-Policy: default-src 'none'
included-http-headers = X-Permitted-Cross-Domain-Policies: none
included-http-headers = Referrer-Policy: no-referrer
included-http-headers = Clear-Site-Data: "cache","cookies","storage"
included-http-headers = Cross-Origin-Embedder-Policy: require-corp
included-http-headers = Cross-Origin-Opener-Policy: same-origin
included-http-headers = Cross-Origin-Resource-Policy: same-origin
included-http-headers = X-XSS-Protection: 0
included-http-headers = Pragma: no-cache
included-http-headers = Cache-control: no-store, no-cache

View File

@@ -1078,6 +1078,12 @@ static int cfg_ini_handler(void *_ctx, const char *section, const char *name, co
READ_MULTI_LINE(config->custom_header, config->custom_header_size); READ_MULTI_LINE(config->custom_header, config->custom_header_size);
} else if (strcmp(name, "split-dns") == 0) { } else if (strcmp(name, "split-dns") == 0) {
READ_MULTI_LINE(config->split_dns, config->split_dns_size); READ_MULTI_LINE(config->split_dns, config->split_dns_size);
} else if (strcmp(name, "included-http-headers") == 0) {
// Don't use sanitized input since http header values can contain optional trailing blanks and double quotes
if (_add_multi_line_val(pool, &(config->included_http_headers), &(config->included_http_headers_size), _value) < 0) {
fprintf(stderr, ERRSTR"memory\n");
exit(1);
}
} else if (strcmp(name, "route") == 0) { } else if (strcmp(name, "route") == 0) {
READ_MULTI_LINE(config->network.routes, config->network.routes_size); READ_MULTI_LINE(config->network.routes, config->network.routes_size);
} else if (strcmp(name, "no-route") == 0) { } else if (strcmp(name, "no-route") == 0) {

View File

@@ -259,6 +259,10 @@ struct cfg_st {
char **split_dns; char **split_dns;
size_t split_dns_size;; size_t split_dns_size;;
/* http headers to include */
char **included_http_headers;
size_t included_http_headers_size;
unsigned int append_routes; /* whether to append global routes to per-user config */ unsigned int append_routes; /* whether to append global routes to per-user config */
unsigned restrict_user_to_routes; /* whether the firewall script will be run for the user */ unsigned restrict_user_to_routes; /* whether the firewall script will be run for the user */
unsigned deny_roaming; /* whether a cookie is restricted to a single IP */ unsigned deny_roaming; /* whether a cookie is restricted to a single IP */

View File

@@ -873,21 +873,15 @@ void http_req_deinit(worker_st * ws)
*/ */
int add_owasp_headers(worker_st * ws) int add_owasp_headers(worker_st * ws)
{ {
if (cstp_puts(ws, "Strict-Transport-Security: max-age=31536000 ; includeSubDomains\r\n") < 0 || // Use only HTTPS unsigned i;
cstp_puts(ws, "X-Frame-Options: deny\r\n") < 0 || // Do not display page in a frame
cstp_puts(ws, "X-Content-Type-Options: nosniff\r\n") < 0 || // Advertised MIME types should be followed for(i=0; i < GETCONFIG(ws)->included_http_headers_size; i++)
cstp_puts(ws, "Content-Security-Policy: default-src \'none\'\r\n") < 0 ||
cstp_puts(ws, "X-Permitted-Cross-Domain-Policies: none\r\n") < 0 ||
cstp_puts(ws, "Referrer-Policy: no-referrer\r\n") < 0 || // No referrer information is included
cstp_puts(ws, "Clear-Site-Data: \"cache\",\"cookies\",\"storage\"\r\n") < 0 || // Clear browsing data (cache, cookies, storage)
cstp_puts(ws, "Cross-Origin-Embedder-Policy: require-corp\r\n") < 0 || // Use CORS header to load cross-origin resource
cstp_puts(ws, "Cross-Origin-Opener-Policy: same-origin\r\n") < 0 || // Do not load cross-origin documents in same browser context
cstp_puts(ws, "Cross-Origin-Resource-Policy: same-origin\r\n") < 0 || // Block no-cors cross-origin/cross-site requests
cstp_puts(ws, "X-XSS-Protection: 0\r\n") < 0 || // Disable XSS filtering
cstp_puts(ws, "Pragma: no-cache\r\n") < 0 || // For backwards compatibility when Cache-control is not recognized
cstp_puts(ws, "Cache-control: no-store\r\n") < 0) // Do not cache responses
{ {
return -1; if (cstp_printf(ws, "%s", GETCONFIG(ws)->included_http_headers[i]) < 0 ||
cstp_puts(ws, "\r\n") < 0)
{
return -1;
}
} }
return 0; return 0;
} }

View File

@@ -29,6 +29,22 @@ eval "${GETPORT}"
echo "Testing ocserv owasp headers... " echo "Testing ocserv owasp headers... "
update_config test-user-cert.config update_config test-user-cert.config
# Add HTTP headers to the config file
echo "included-http-headers = Strict-Transport-Security: max-age=31536000 ; includeSubDomains" >> ${CONFIG}
echo "included-http-headers = X-Frame-Options: deny" >> ${CONFIG}
echo "included-http-headers = X-Content-Type-Options: nosniff" >> ${CONFIG}
echo "included-http-headers = Content-Security-Policy: default-src \'none\'" >> ${CONFIG}
echo "included-http-headers = X-Permitted-Cross-Domain-Policies: none" >> ${CONFIG}
echo "included-http-headers = Referrer-Policy: no-referrer" >> ${CONFIG}
echo "included-http-headers = Clear-Site-Data: \"cache\",\"cookies\",\"storage\"" >> ${CONFIG}
echo "included-http-headers = Cross-Origin-Embedder-Policy: require-corp" >> ${CONFIG}
echo "included-http-headers = Cross-Origin-Opener-Policy: same-origin" >> ${CONFIG}
echo "included-http-headers = Cross-Origin-Resource-Policy: same-origin" >> ${CONFIG}
echo "included-http-headers = X-XSS-Protection: 0" >> ${CONFIG}
echo "included-http-headers = Pragma: no-cache" >> ${CONFIG}
echo "included-http-headers = Cache-control: no-cache, no-store" >> ${CONFIG}
launch_simple_sr_server -d 1 -f -c ${CONFIG} launch_simple_sr_server -d 1 -f -c ${CONFIG}
PID=$! PID=$!
@@ -49,7 +65,7 @@ function CheckHeaders
[[ "$1" =~ .*"X-XSS-Protection".* ]] || fail $PID "Missing HTTP header (X-XSS-Protection)" [[ "$1" =~ .*"X-XSS-Protection".* ]] || fail $PID "Missing HTTP header (X-XSS-Protection)"
[[ "$1" =~ .*"Pragma".* ]] || fail $PID "Missing HTTP header (Pragma)" [[ "$1" =~ .*"Pragma".* ]] || fail $PID "Missing HTTP header (Pragma)"
[[ "$1" =~ .*"Cache-control".* ]] || fail $PID "Missing HTTP header (Cache-control)" [[ "$1" =~ .*"Cache-control".* ]] || fail $PID "Missing HTTP header (Cache-control)"
while IFS=':' read name value; do while IFS=':' read name value; do
case "$name" in case "$name" in
Strict-Transport-Security) Strict-Transport-Security)
@@ -77,7 +93,7 @@ function CheckHeaders
Pragma) Pragma)
[[ "$value" =~ "no-cache" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";; [[ "$value" =~ "no-cache" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
Cache-control) Cache-control)
[[ "$value" =~ "no-store" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";; [[ "$value" =~ "no-cache, no-store" ]] || fail $PID "Unexpected HTTP header value ($name: $value)";;
esac esac
done < <(echo "$1") done < <(echo "$1")
} }