master
h 282 lines 14 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #ifndef NETDATA_WEB_CLIENT_H
4 #define NETDATA_WEB_CLIENT_H 1
5
6 #include "libnetdata/libnetdata.h"
7 #include "../websocket/websocket.h"
8
9 struct web_client;
10
11 extern int web_enable_gzip, web_gzip_level, web_gzip_strategy;
12
13 #define HTTP_REQ_MAX_HEADER_FETCH_TRIES 100
14
15 extern int respect_web_browser_do_not_track_policy;
16 extern const char *web_x_frame_options;
17
18 typedef enum __attribute__((packed)) {
19 HTTP_VALIDATION_OK,
20 HTTP_VALIDATION_NOT_SUPPORTED,
21 HTTP_VALIDATION_TOO_MANY_READ_RETRIES,
22 HTTP_VALIDATION_MALFORMED_URL,
23 HTTP_VALIDATION_INCOMPLETE,
24 HTTP_VALIDATION_REDIRECT
25 } HTTP_VALIDATION;
26
27 typedef enum __attribute__((packed)) {
28 WEB_CLIENT_FLAG_DEAD = (1 << 0), // this client is dead
29
30 WEB_CLIENT_FLAG_KEEPALIVE = (1 << 1), // the web client will be re-used
31
32 // compression
33 WEB_CLIENT_ENCODING_GZIP = (1 << 2),
34 WEB_CLIENT_ENCODING_DEFLATE = (1 << 3),
35 WEB_CLIENT_CHUNKED_TRANSFER = (1 << 4), // chunked transfer (used with zlib compression)
36
37 WEB_CLIENT_FLAG_WAIT_RECEIVE = (1 << 5), // we are waiting more input data
38 WEB_CLIENT_FLAG_WAIT_SEND = (1 << 6), // we have data to send to the client
39 WEB_CLIENT_FLAG_SSL_WAIT_RECEIVE = (1 << 7), // we are waiting more input data from ssl connection
40 WEB_CLIENT_FLAG_SSL_WAIT_SEND = (1 << 8), // we have data to send to the client from ssl connection
41
42 // DNT
43 WEB_CLIENT_FLAG_DO_NOT_TRACK = (1 << 9), // we should not set cookies on this client
44 WEB_CLIENT_FLAG_TRACKING_REQUIRED = (1 << 10), // we need to send cookies
45
46 // connection type
47 WEB_CLIENT_FLAG_CONN_TCP = (1 << 11), // the client is using a TCP socket
48 WEB_CLIENT_FLAG_CONN_UNIX = (1 << 12), // the client is using a UNIX socket
49 WEB_CLIENT_FLAG_CONN_CLOUD = (1 << 13), // the client is using Netdata Cloud
50 WEB_CLIENT_FLAG_CONN_WEBRTC = (1 << 14), // the client is using WebRTC
51
52 // streaming and websocket
53 WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET = (1 << 15), // don't close the socket when cleaning up
54
55 // dashboard version
56 WEB_CLIENT_FLAG_PATH_IS_V0 = (1 << 16), // v0 dashboard found on the path
57 WEB_CLIENT_FLAG_PATH_IS_V1 = (1 << 17), // v1 dashboard found on the path
58 WEB_CLIENT_FLAG_PATH_IS_V2 = (1 << 18), // v2 dashboard found on the path
59 WEB_CLIENT_FLAG_PATH_IS_V3 = (1 << 19), // v3 dashboard found on the path
60 WEB_CLIENT_FLAG_PATH_HAS_TRAILING_SLASH = (1 << 20), // the path has a trailing hash
61 WEB_CLIENT_FLAG_PATH_HAS_FILE_EXTENSION = (1 << 21), // the path ends with a filename extension
62
63 // transient settings
64 WEB_CLIENT_FLAG_PROGRESS_TRACKING = (1 << 22), // flag to avoid redoing progress work
65
66 // websocket flags
67 WEB_CLIENT_FLAG_WEBSOCKET_CLIENT = (1 << 23), // this is a websocket client
68 WEB_CLIENT_FLAG_WEBSOCKET_HANDSHAKE = (1 << 24), // websocket handshake detected
69 WEB_CLIENT_FLAG_ACCEPT_JSON = (1 << 25),
70 WEB_CLIENT_FLAG_ACCEPT_SSE = (1 << 26),
71 WEB_CLIENT_FLAG_ACCEPT_TEXT = (1 << 27),
72 WEB_CLIENT_FLAG_MCP_PREVIEW_KEY = (1 << 28), // Authorization header matched MCP preview key
73 WEB_CLIENT_FLAG_PATH_IS_MCP = (1 << 29), // URL path is /mcp[/...] or /sse[/...] — set during URL decoding so it's also available for OPTIONS preflights (which skip the URL dispatcher)
74 } WEB_CLIENT_FLAGS;
75
76 #define WEB_CLIENT_FLAG_PATH_WITH_VERSION (WEB_CLIENT_FLAG_PATH_IS_V0|WEB_CLIENT_FLAG_PATH_IS_V1|WEB_CLIENT_FLAG_PATH_IS_V2|WEB_CLIENT_FLAG_PATH_IS_V3)
77 // PATH_IS_MCP is intentionally *not* in the reset mask: it is set during
78 // URL decoding, not during URL dispatch, so resetting it here (which runs
79 // after decoding but before dispatch on POST/GET/etc.) would wipe it
80 // before the response builder could read it.
81 #define web_client_reset_path_flags(w) (w)->flags &= ~(WEB_CLIENT_FLAG_PATH_WITH_VERSION|WEB_CLIENT_FLAG_PATH_HAS_TRAILING_SLASH|WEB_CLIENT_FLAG_PATH_HAS_FILE_EXTENSION)
82
83 #define web_client_flag_check(w, flag) ((w)->flags & (flag))
84 #define web_client_flag_set(w, flag) (w)->flags |= (flag)
85 #define web_client_flag_clear(w, flag) (w)->flags &= ~(flag)
86
87 #define WEB_CLIENT_IS_DEAD(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DEAD)
88 #define web_client_check_dead(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DEAD)
89
90 #define web_client_has_keepalive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_KEEPALIVE)
91 #define web_client_enable_keepalive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_KEEPALIVE)
92 #define web_client_disable_keepalive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_KEEPALIVE)
93
94 #define web_client_has_donottrack(w) web_client_flag_check(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
95 #define web_client_enable_donottrack(w) web_client_flag_set(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
96 #define web_client_disable_donottrack(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_DO_NOT_TRACK)
97
98 #define web_client_has_tracking_required(w) web_client_flag_check(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
99 #define web_client_enable_tracking_required(w) web_client_flag_set(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
100 #define web_client_disable_tracking_required(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_TRACKING_REQUIRED)
101
102 #define web_client_has_wait_receive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
103 #define web_client_enable_wait_receive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
104 #define web_client_disable_wait_receive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WAIT_RECEIVE)
105
106 #define web_client_has_wait_send(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WAIT_SEND)
107 #define web_client_enable_wait_send(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WAIT_SEND)
108 #define web_client_disable_wait_send(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WAIT_SEND)
109
110 #define web_client_has_ssl_wait_receive(w) web_client_flag_check(w, WEB_CLIENT_FLAG_SSL_WAIT_RECEIVE)
111 #define web_client_enable_ssl_wait_receive(w) web_client_flag_set(w, WEB_CLIENT_FLAG_SSL_WAIT_RECEIVE)
112 #define web_client_disable_ssl_wait_receive(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_SSL_WAIT_RECEIVE)
113
114 #define web_client_has_ssl_wait_send(w) web_client_flag_check(w, WEB_CLIENT_FLAG_SSL_WAIT_SEND)
115 #define web_client_enable_ssl_wait_send(w) web_client_flag_set(w, WEB_CLIENT_FLAG_SSL_WAIT_SEND)
116 #define web_client_disable_ssl_wait_send(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_SSL_WAIT_SEND)
117
118 #define web_client_has_mcp_preview_key(w) web_client_flag_check(w, WEB_CLIENT_FLAG_MCP_PREVIEW_KEY)
119 #define web_client_set_mcp_preview_key(w) web_client_flag_set(w, WEB_CLIENT_FLAG_MCP_PREVIEW_KEY)
120 #define web_client_clear_mcp_preview_key(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_MCP_PREVIEW_KEY)
121
122 #define web_client_check_conn_unix(w) web_client_flag_check(w, WEB_CLIENT_FLAG_CONN_UNIX)
123 #define web_client_check_conn_tcp(w) web_client_flag_check(w, WEB_CLIENT_FLAG_CONN_TCP)
124 #define web_client_check_conn_cloud(w) web_client_flag_check(w, WEB_CLIENT_FLAG_CONN_CLOUD)
125 #define web_client_check_conn_webrtc(w) web_client_flag_check(w, WEB_CLIENT_FLAG_CONN_WEBRTC)
126 #define web_client_flags_clear_conn(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_CONN_TCP | WEB_CLIENT_FLAG_CONN_UNIX | WEB_CLIENT_FLAG_CONN_CLOUD | WEB_CLIENT_FLAG_CONN_WEBRTC)
127
128 #define web_client_is_websocket(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WEBSOCKET_CLIENT)
129 #define web_client_set_websocket(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WEBSOCKET_CLIENT)
130 #define web_client_clear_websocket(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WEBSOCKET_CLIENT)
131
132 #define web_client_has_websocket_handshake(w) web_client_flag_check(w, WEB_CLIENT_FLAG_WEBSOCKET_HANDSHAKE)
133 #define web_client_set_websocket_handshake(w) web_client_flag_set(w, WEB_CLIENT_FLAG_WEBSOCKET_HANDSHAKE)
134 #define web_client_clear_websocket_handshake(w) web_client_flag_clear(w, WEB_CLIENT_FLAG_WEBSOCKET_HANDSHAKE)
135
136 void web_client_reset_permissions(struct web_client *w);
137 void web_client_set_permissions(struct web_client *w, HTTP_ACCESS access, HTTP_USER_ROLE role, USER_AUTH_METHOD type);
138
139 void web_client_set_conn_tcp(struct web_client *w);
140 void web_client_set_conn_unix(struct web_client *w);
141 void web_client_set_conn_cloud(struct web_client *w);
142 void web_client_set_conn_webrtc(struct web_client *w);
143
144 #define NETDATA_WEB_REQUEST_URL_SIZE 65536 // static allocation
145
146 #define NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE 16384
147
148 #define NETDATA_WEB_RESPONSE_HEADER_INITIAL_SIZE 4096
149 #define NETDATA_WEB_RESPONSE_INITIAL_SIZE 8192
150 #define NETDATA_WEB_REQUEST_INITIAL_SIZE 8192
151 #define NETDATA_WEB_REQUEST_MAX_SIZE (128 * 1024)
152 #define NETDATA_WEB_DECODED_URL_INITIAL_SIZE 512
153
154 struct response {
155 BUFFER *header; // our response header
156 BUFFER *header_output; // internal use
157 BUFFER *data; // our response data buffer
158 size_t sent; // current data length sent to output
159 short int code; // the HTTP response code
160 bool has_cookies;
161 bool zoutput; // if set to 1, web_client_send() will send compressed data
162 bool zinitialized;
163 z_stream zstream; // zlib stream for sending compressed output to client
164 size_t zsent; // the compressed bytes we have sent to the client
165 size_t zhave; // the compressed bytes that we have received from zlib
166 Bytef zbuffer[NETDATA_WEB_RESPONSE_ZLIB_CHUNK_SIZE]; // temporary buffer for storing compressed output
167 };
168
169 struct web_client;
170 typedef bool (*web_client_interrupt_t)(struct web_client *, void *data);
171
172 struct web_client {
173 unsigned long long id;
174 size_t use_count;
175
176 nd_uuid_t transaction;
177
178 WEB_CLIENT_FLAGS flags; // status flags for the client
179 HTTP_REQUEST_MODE mode; // the operational mode of the client
180 HTTP_ACL acl; // the access list of the client
181 HTTP_ACL port_acl; // the operations permitted on the port the client connected to
182 HTTP_ACCESS access; // the access permissions of the client
183 size_t header_parse_tries;
184 size_t header_parse_last_size;
185
186 int fd;
187
188 USER_AUTH user_auth; // the user authentication data
189
190 char client_port[NI_MAXSERV];
191 char client_host[NI_MAXHOST];
192
193 BUFFER *url_as_received; // the entire URL as received, used for logging - DO NOT MODIFY
194 BUFFER *url_path_decoded; // the path, decoded - it is incrementally parsed and altered
195 BUFFER *url_query_string_decoded; // the query string, decoded - it is incrementally parsed and altered
196
197 // THESE NEED TO BE FREED
198 char *auth_bearer_token; // the Bearer auth token (if sent)
199 char *server_host; // the Host: header
200 char *forwarded_host; // the X-Forwarded-Host: header
201 char *origin; // the Origin: header
202 char *user_agent; // the User-Agent: header
203 nd_uuid_t mcp_session_id; // the Mcp-Session-Id: header (MCP HTTP transport)
204
205 // WebSocket related data - NEED TO BE FREED
206 struct {
207 char *key; // the Sec-WebSocket-Key header
208 WEBSOCKET_PROTOCOL protocol; // the selected subprotocol
209 WEBSOCKET_EXTENSION ext_flags; // bit flags for supported extensions
210 uint8_t client_max_window_bits; // client_max_window_bits parameter (8-15)
211 uint8_t server_max_window_bits; // server_max_window_bits parameter (8-15)
212 } websocket;
213
214 BUFFER *payload; // when this request is a POST, this has the payload
215
216 NETDATA_SSL ssl;
217
218 struct {
219 nd_uuid_t bearer_token;
220 } auth;
221
222 struct { // A callback to check if the query should be interrupted / stopped
223 web_client_interrupt_t callback;
224 void *callback_data;
225 } interrupt;
226
227 struct {
228 size_t received_bytes;
229 size_t sent_bytes;
230 size_t *memory_accounting; // temporary pointer for constructor to use
231 } statistics;
232
233 struct {
234 usec_t timeout_ut; // timeout if set, or zero
235 struct timeval tv_in; // request received
236 struct timeval tv_ready; // request processed - response ready
237 struct timeval tv_timeout_last_checkpoint; // last checkpoint
238 } timings;
239
240 struct {
241 struct web_client *prev;
242 struct web_client *next;
243 } cache;
244
245 struct response response;
246 };
247
248 int web_client_permission_denied(struct web_client *w);
249 int web_client_permission_denied_acl(struct web_client *w);
250
251 int web_client_service_unavailable(struct web_client *w);
252
253 ssize_t web_client_send(struct web_client *w);
254 ssize_t web_client_receive(struct web_client *w);
255
256 void web_client_process_request_from_web_server(struct web_client *w);
257 void web_client_request_done(struct web_client *w);
258
259 void web_client_build_http_header(struct web_client *w);
260
261 void web_client_reuse_from_cache(struct web_client *w);
262 struct web_client *web_client_create(size_t *statistics_memory_accounting);
263 void web_client_free(struct web_client *w);
264
265 #include "web/api/web_api_v1.h"
266 #include "web/api/web_api_v2.h"
267 #include "database/rrd.h"
268
269 void web_client_decode_path_and_query_string(struct web_client *w, const char *path_and_query_string);
270 int web_client_api_request(RRDHOST *host, struct web_client *w, char *url_path_fragment);
271 int web_client_api_request_with_node_selection(RRDHOST *host, struct web_client *w, char *decoded_url_path);
272
273 void web_client_timeout_checkpoint_init(struct web_client *w);
274 void web_client_timeout_checkpoint_set(struct web_client *w, int timeout_ms);
275 usec_t web_client_timeout_checkpoint(struct web_client *w);
276 bool web_client_timeout_checkpoint_and_check(struct web_client *w, usec_t *usec_since_last_checkpoint);
277 usec_t web_client_timeout_checkpoint_response_ready(struct web_client *w, usec_t *usec_since_last_checkpoint);
278 void web_client_log_completed_request(struct web_client *w, bool update_web_stats);
279
280 HTTP_VALIDATION http_request_validate(struct web_client *w);
281
282 #endif