1 #pragma once
2 
3 #include "bmcweb_config.h"
4 
5 #include "http_request.hpp"
6 #include "http_response.hpp"
7 
8 inline void addSecurityHeaders(const crow::Request& req [[maybe_unused]],
9                                crow::Response& res)
10 {
11     /*
12      TODO(ed) these should really check content types.  for example,
13      X-UA-Compatible header doesn't make sense when retrieving a JSON or
14      javascript file.  It doesn't hurt anything, it's just ugly.
15      */
16     using bf = boost::beast::http::field;
17     res.addHeader(bf::strict_transport_security, "max-age=31536000; "
18                                                  "includeSubdomains; "
19                                                  "preload");
20     res.addHeader(bf::x_frame_options, "DENY");
21 
22     res.addHeader(bf::pragma, "no-cache");
23     res.addHeader(bf::cache_control, "no-Store,no-Cache");
24 
25     res.addHeader("X-XSS-Protection", "1; "
26                                       "mode=block");
27     res.addHeader("X-Content-Type-Options", "nosniff");
28 
29     // Recommendations from https://owasp.org/www-project-secure-headers/
30     // https://owasp.org/www-project-secure-headers/ci/headers_add.json
31     res.addHeader("Referrer-Policy", "no-referrer");
32     res.addHeader("Permissions-Policy", "accelerometer=(), "
33                                         "ambient-light-sensor=(), "
34                                         "autoplay=(), "
35                                         "battery=(), "
36                                         "bluetooth=(), "
37                                         "camera=(), "
38                                         "ch-ua=(), "
39                                         "ch-ua-arch=(), "
40                                         "ch-ua-bitness=(), "
41                                         "ch-ua-full-version=(), "
42                                         "ch-ua-full-version-list=(), "
43                                         "ch-ua-mobile=(), "
44                                         "ch-ua-model=(), "
45                                         "ch-ua-platform=(), "
46                                         "ch-ua-platform-version=(), "
47                                         "ch-ua-wow64=(), "
48                                         "cross-origin-isolated=(), "
49                                         "display-capture=(), "
50                                         "encrypted-media=(), "
51                                         "execution-while-not-rendered=(), "
52                                         "execution-while-out-of-viewport=(), "
53                                         "fullscreen=(), "
54                                         "geolocation=(), "
55                                         "gyroscope=(), "
56                                         "hid=(), "
57                                         "idle-detection=(), "
58                                         "keyboard-map=(), "
59                                         "magnetometer=(), "
60                                         "microphone=(), "
61                                         "midi=(), "
62                                         "navigation-override=(), "
63                                         "payment=(), "
64                                         "picture-in-picture=(), "
65                                         "publickey-credentials-get=(), "
66                                         "screen-wake-lock=(), "
67                                         "serial=(), "
68                                         "sync-xhr=(), "
69                                         "usb=(self), "
70                                         "web-share=(), "
71                                         "xr-spatial-tracking2=()");
72 
73     if (bmcwebInsecureDisableXssPrevention == 0)
74     {
75         res.addHeader("Content-Security-Policy", "default-src 'none'; "
76                                                  "img-src 'self' data:; "
77                                                  "font-src 'self'; "
78                                                  "style-src 'self'; "
79                                                  "script-src 'self'; "
80                                                  "connect-src 'self' wss:; "
81                                                  "form-action 'none'; "
82                                                  "frame-ancestors 'none'; "
83                                                  "object-src 'none'; "
84                                                  "base-uri 'none' ");
85         // The KVM currently needs to load images from base64 encoded
86         // strings. img-src 'self' data: is used to allow that.
87         // https://stackoverflow.com/questions/18447970/content-security-polic
88         // y-data-not-working-for-base64-images-in-chrome-28
89     }
90     else
91     {
92         // If XSS is disabled, we need to allow loading from addresses other
93         // than self, as the BMC will be hosted elsewhere.
94         res.addHeader("Content-Security-Policy", "default-src 'none'; "
95                                                  "img-src *; "
96                                                  "font-src *; "
97                                                  "style-src *; "
98                                                  "script-src *; "
99                                                  "connect-src *; "
100                                                  "form-action *; "
101                                                  "frame-ancestors *; "
102                                                  "object-src *; "
103                                                  "base-uri *");
104 
105         std::string_view origin = req.getHeaderValue("Origin");
106         res.addHeader(bf::access_control_allow_origin, origin);
107         res.addHeader(bf::access_control_allow_methods, "GET, "
108                                                         "POST, "
109                                                         "PUT, "
110                                                         "PATCH, "
111                                                         "DELETE");
112         res.addHeader(bf::access_control_allow_credentials, "true");
113         res.addHeader(bf::access_control_allow_headers, "Origin, "
114                                                         "Content-Type, "
115                                                         "Accept, "
116                                                         "Cookie, "
117                                                         "X-XSRF-TOKEN");
118     }
119 }
120