1
2 /*
3 * Copyright (C) Valentin V. Bartenev
4 * Copyright (C) NGINX, Inc.
5 * Copyright 2024, Alejandro Colomar <alx@kernel.org>
6 */
7
8 #include <nxt_main.h>
9 #include <nxt_conf.h>
10 #include <nxt_cert.h>
11 #include <nxt_script.h>
12 #include <nxt_router.h>
13 #include <nxt_http.h>
14 #include <nxt_sockaddr.h>
15 #include <nxt_http_route_addr.h>
16 #include <nxt_regex.h>
17
18
19 typedef enum {
20 NXT_CONF_VLDT_NULL = 1 << NXT_CONF_NULL,
21 NXT_CONF_VLDT_BOOLEAN = 1 << NXT_CONF_BOOLEAN,
22 NXT_CONF_VLDT_INTEGER = 1 << NXT_CONF_INTEGER,
23 NXT_CONF_VLDT_NUMBER = (1 << NXT_CONF_NUMBER) | NXT_CONF_VLDT_INTEGER,
24 NXT_CONF_VLDT_STRING = 1 << NXT_CONF_STRING,
25 NXT_CONF_VLDT_ARRAY = 1 << NXT_CONF_ARRAY,
26 NXT_CONF_VLDT_OBJECT = 1 << NXT_CONF_OBJECT,
27 } nxt_conf_vldt_type_t;
28
29 #define NXT_CONF_VLDT_ANY_TYPE (NXT_CONF_VLDT_NULL \
30 |NXT_CONF_VLDT_BOOLEAN \
31 |NXT_CONF_VLDT_NUMBER \
32 |NXT_CONF_VLDT_STRING \
33 |NXT_CONF_VLDT_ARRAY \
34 |NXT_CONF_VLDT_OBJECT)
35
36
37 typedef enum {
38 NXT_CONF_VLDT_REQUIRED = 1 << 0,
39 NXT_CONF_VLDT_TSTR = 1 << 1,
40 } nxt_conf_vldt_flags_t;
41
42
43 typedef nxt_int_t (*nxt_conf_vldt_handler_t)(nxt_conf_validation_t *vldt,
44 nxt_conf_value_t *value,
45 void *data);
46 typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt,
47 nxt_str_t *name,
48 nxt_conf_value_t *value);
49 typedef nxt_int_t (*nxt_conf_vldt_element_t)(nxt_conf_validation_t *vldt,
50 nxt_conf_value_t *value);
51
52
53 typedef struct nxt_conf_vldt_object_s nxt_conf_vldt_object_t;
54
55 struct nxt_conf_vldt_object_s {
56 nxt_str_t name;
57 nxt_conf_vldt_type_t type:32;
58 nxt_conf_vldt_flags_t flags:32;
59 nxt_conf_vldt_handler_t validator;
60
61 union {
62 nxt_conf_vldt_object_t *members;
63 nxt_conf_vldt_object_t *next;
64 nxt_conf_vldt_member_t object;
65 nxt_conf_vldt_element_t array;
66 const char *string;
67 } u;
68 };
69
70
71 #define NXT_CONF_VLDT_NEXT(next) { .u.members = next }
72 #define NXT_CONF_VLDT_END { .name = nxt_null_string }
73
74
75 static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt,
76 nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type);
77 static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt,
78 const char *fmt, ...);
79 static nxt_int_t nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name,
80 nxt_str_t *value);
81 static nxt_int_t nxt_conf_vldt_if(nxt_conf_validation_t *vldt,
82 nxt_conf_value_t *value, void *data);
83 nxt_inline nxt_int_t nxt_conf_vldt_unsupported(nxt_conf_validation_t *vldt,
84 nxt_conf_value_t *value, void *data)
85 NXT_MAYBE_UNUSED;
86
87 static nxt_int_t nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt,
88 nxt_conf_value_t *value, void *data);
89 static nxt_int_t nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt,
90 nxt_str_t *name, nxt_conf_value_t *value);
91 static nxt_int_t nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt,
92 nxt_conf_value_t *value);
93 static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt,
94 nxt_str_t *name, nxt_conf_value_t *value);
95 #if (NXT_TLS)
96 static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt,
97 nxt_conf_value_t *value, void *data);
98 #if (NXT_HAVE_OPENSSL_CONF_CMD)
99 static nxt_int_t nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt,
100 nxt_conf_value_t *value, void *data);
101 #endif
102 static nxt_int_t nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt,
103 nxt_conf_value_t *value);
104 static nxt_int_t nxt_conf_vldt_tls_cache_size(nxt_conf_validation_t *vldt,
105 nxt_conf_value_t *value, void *data);
106 static nxt_int_t nxt_conf_vldt_tls_timeout(nxt_conf_validation_t *vldt,
107 nxt_conf_value_t *value, void *data);
108 #if (NXT_HAVE_OPENSSL_TLSEXT)
109 static nxt_int_t nxt_conf_vldt_ticket_key(nxt_conf_validation_t *vldt,
110 nxt_conf_value_t *value, void *data);
111 static nxt_int_t nxt_conf_vldt_ticket_key_element(nxt_conf_validation_t *vldt,
112 nxt_conf_value_t *value);
113 #endif
114 #endif
115 static nxt_int_t nxt_conf_vldt_action(nxt_conf_validation_t *vldt,
116 nxt_conf_value_t *value, void *data);
117 static nxt_int_t nxt_conf_vldt_pass(nxt_conf_validation_t *vldt,
118 nxt_conf_value_t *value, void *data);
119 static nxt_int_t nxt_conf_vldt_return(nxt_conf_validation_t *vldt,
120 nxt_conf_value_t *value, void *data);
121 static nxt_int_t nxt_conf_vldt_share(nxt_conf_validation_t *vldt,
122 nxt_conf_value_t *value, void *data);
123 static nxt_int_t nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt,
124 nxt_conf_value_t *value);
125 static nxt_int_t nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt,
126 nxt_conf_value_t *value, void *data);
127 static nxt_int_t nxt_conf_vldt_python(nxt_conf_validation_t *vldt,
128 nxt_conf_value_t *value, void *data);
129 static nxt_int_t nxt_conf_vldt_python_path(nxt_conf_validation_t *vldt,
130 nxt_conf_value_t *value, void *data);
131 static nxt_int_t nxt_conf_vldt_python_path_element(nxt_conf_validation_t *vldt,
132 nxt_conf_value_t *value);
133 static nxt_int_t nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt,
134 nxt_conf_value_t *value, void *data);
135 static nxt_int_t nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt,
136 nxt_conf_value_t *value, void *data);
137 static nxt_int_t nxt_conf_vldt_threads(nxt_conf_validation_t *vldt,
138 nxt_conf_value_t *value, void *data);
139 static nxt_int_t nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt,
140 nxt_conf_value_t *value, void *data);
141 static nxt_int_t nxt_conf_vldt_routes(nxt_conf_validation_t *vldt,
142 nxt_conf_value_t *value, void *data);
143 static nxt_int_t nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt,
144 nxt_str_t *name, nxt_conf_value_t *value);
145 static nxt_int_t nxt_conf_vldt_route(nxt_conf_validation_t *vldt,
146 nxt_conf_value_t *value);
147 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets(
148 nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data);
149 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set(
150 nxt_conf_validation_t *vldt, nxt_conf_value_t *value);
151 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set_member(
152 nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value);
153 static nxt_int_t nxt_conf_vldt_match_encoded_patterns(
154 nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data);
155 static nxt_int_t nxt_conf_vldt_match_encoded_pattern(
156 nxt_conf_validation_t *vldt, nxt_conf_value_t *value);
157 static nxt_int_t nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
158 nxt_conf_value_t *value, void *data);
159 static nxt_int_t nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
160 nxt_conf_value_t *value);
161 static nxt_int_t nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt,
162 nxt_conf_value_t *value, void *data);
163 static nxt_int_t nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt,
164 nxt_conf_value_t *value);
165 static nxt_int_t nxt_conf_vldt_match_patterns_set_member(
166 nxt_conf_validation_t *vldt, nxt_str_t *name, nxt_conf_value_t *value);
167 static nxt_int_t nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt,
168 nxt_conf_value_t *value, void *data);
169 static nxt_int_t nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
170 nxt_conf_value_t *value, void *data);
171 static nxt_int_t nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
172 nxt_conf_value_t *value);
173 static nxt_int_t nxt_conf_vldt_response_header(nxt_conf_validation_t *vldt,
174 nxt_str_t *name, nxt_conf_value_t *value);
175 static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt,
176 nxt_conf_value_t *value, void *data);
177 static nxt_int_t nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt,
178 nxt_conf_value_t *value, void *data);
179 static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
180 nxt_str_t *name, nxt_conf_value_t *value);
181 static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
182 nxt_conf_value_t *value, void *data);
183 static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt,
184 nxt_conf_value_t *value, void *data);
185 static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
186 nxt_conf_value_t *value, void *data);
187 static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt,
188 nxt_conf_value_t *value, void *data);
189 static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt,
190 nxt_str_t *name, nxt_conf_value_t *value);
191 static nxt_int_t nxt_conf_vldt_targets_exclusive(
192 nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data);
193 static nxt_int_t nxt_conf_vldt_targets(nxt_conf_validation_t *vldt,
194 nxt_conf_value_t *value, void *data);
195 static nxt_int_t nxt_conf_vldt_target(nxt_conf_validation_t *vldt,
196 nxt_str_t *name, nxt_conf_value_t *value);
197 static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt,
198 nxt_conf_value_t *value);
199 static nxt_int_t nxt_conf_vldt_php(nxt_conf_validation_t *vldt,
200 nxt_conf_value_t *value, void *data);
201 static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt,
202 nxt_str_t *name, nxt_conf_value_t *value);
203 static nxt_int_t nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
204 nxt_conf_value_t *value);
205 static nxt_int_t nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt,
206 nxt_conf_value_t *value);
207 static nxt_int_t nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt,
208 nxt_str_t *name, nxt_conf_value_t *value);
209 static nxt_int_t nxt_conf_vldt_server(nxt_conf_validation_t *vldt,
210 nxt_str_t *name, nxt_conf_value_t *value);
211 static nxt_int_t nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
212 nxt_conf_value_t *value, void *data);
213 static nxt_int_t nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt,
214 nxt_conf_value_t *value, void *data);
215
216 static nxt_int_t nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt,
217 nxt_conf_value_t *value, void *data);
218 static nxt_int_t nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt,
219 nxt_conf_value_t *value, void *data);
220
221 #if (NXT_HAVE_CLONE_NEWUSER)
222 static nxt_int_t nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt,
223 nxt_conf_value_t *value);
224 static nxt_int_t nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt,
225 nxt_conf_value_t *value);
226 #endif
227
228 #if (NXT_HAVE_CGROUP)
229 static nxt_int_t nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt,
230 nxt_conf_value_t *value, void *data);
231 #endif
232
233 #if (NXT_HAVE_NJS)
234 static nxt_int_t nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt,
235 nxt_conf_value_t *value, void *data);
236 static nxt_int_t nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt,
237 nxt_conf_value_t *value);
238 #endif
239
240
241 static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[];
242 static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[];
243 static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[];
244 static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[];
245 static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[];
246 static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[];
247 #if (NXT_TLS)
248 static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[];
249 static nxt_conf_vldt_object_t nxt_conf_vldt_session_members[];
250 #endif
251 static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[];
252 static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[];
253 static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[];
254 static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[];
255 static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[];
256 static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_access_members[];
257 static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[];
258 static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[];
259 static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[];
260 static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[];
261 static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[];
262 #if (NXT_HAVE_CGROUP)
263 static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[];
264 #endif
265 #if (NXT_HAVE_ISOLATION_ROOTFS)
266 static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[];
267 #endif
268 static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[];
269
270
271 static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = {
272 {
273 .name = nxt_string("settings"),
274 .type = NXT_CONF_VLDT_OBJECT,
275 .validator = nxt_conf_vldt_object,
276 .u.members = nxt_conf_vldt_setting_members,
277 }, {
278 .name = nxt_string("listeners"),
279 .type = NXT_CONF_VLDT_OBJECT,
280 .validator = nxt_conf_vldt_object_iterator,
281 .u.object = nxt_conf_vldt_listener,
282 }, {
283 .name = nxt_string("routes"),
284 .type = NXT_CONF_VLDT_ARRAY | NXT_CONF_VLDT_OBJECT,
285 .validator = nxt_conf_vldt_routes,
286 }, {
287 .name = nxt_string("applications"),
288 .type = NXT_CONF_VLDT_OBJECT,
289 .validator = nxt_conf_vldt_object_iterator,
290 .u.object = nxt_conf_vldt_app,
291 }, {
292 .name = nxt_string("upstreams"),
293 .type = NXT_CONF_VLDT_OBJECT,
294 .validator = nxt_conf_vldt_object_iterator,
295 .u.object = nxt_conf_vldt_upstream,
296 }, {
297 .name = nxt_string("access_log"),
298 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_OBJECT,
299 .validator = nxt_conf_vldt_access_log,
300 },
301
302 NXT_CONF_VLDT_END
303 };
304
305
306 static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = {
307 {
308 .name = nxt_string("http"),
309 .type = NXT_CONF_VLDT_OBJECT,
310 .validator = nxt_conf_vldt_object,
311 .u.members = nxt_conf_vldt_http_members,
312 #if (NXT_HAVE_NJS)
313 }, {
314 .name = nxt_string("js_module"),
315 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
316 .validator = nxt_conf_vldt_js_module,
317 #endif
318 },
319
320 NXT_CONF_VLDT_END
321 };
322
323
324 static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = {
325 {
326 .name = nxt_string("header_read_timeout"),
327 .type = NXT_CONF_VLDT_INTEGER,
328 }, {
329 .name = nxt_string("body_read_timeout"),
330 .type = NXT_CONF_VLDT_INTEGER,
331 }, {
332 .name = nxt_string("send_timeout"),
333 .type = NXT_CONF_VLDT_INTEGER,
334 }, {
335 .name = nxt_string("idle_timeout"),
336 .type = NXT_CONF_VLDT_INTEGER,
337 }, {
338 .name = nxt_string("large_header_buffer_size"),
339 .type = NXT_CONF_VLDT_INTEGER,
340 }, {
341 .name = nxt_string("large_header_buffers"),
342 .type = NXT_CONF_VLDT_INTEGER,
343 }, {
344 .name = nxt_string("body_buffer_size"),
345 .type = NXT_CONF_VLDT_INTEGER,
346 }, {
347 .name = nxt_string("max_body_size"),
348 .type = NXT_CONF_VLDT_INTEGER,
349 }, {
350 .name = nxt_string("body_temp_path"),
351 .type = NXT_CONF_VLDT_STRING,
352 }, {
353 .name = nxt_string("discard_unsafe_fields"),
354 .type = NXT_CONF_VLDT_BOOLEAN,
355 }, {
356 .name = nxt_string("websocket"),
357 .type = NXT_CONF_VLDT_OBJECT,
358 .validator = nxt_conf_vldt_object,
359 .u.members = nxt_conf_vldt_websocket_members,
360 }, {
361 .name = nxt_string("static"),
362 .type = NXT_CONF_VLDT_OBJECT,
363 .validator = nxt_conf_vldt_object,
364 .u.members = nxt_conf_vldt_static_members,
365 }, {
366 .name = nxt_string("log_route"),
367 .type = NXT_CONF_VLDT_BOOLEAN,
368 }, {
369 .name = nxt_string("server_version"),
370 .type = NXT_CONF_VLDT_BOOLEAN,
371 },
372
373 NXT_CONF_VLDT_END
374 };
375
376
377 static nxt_conf_vldt_object_t nxt_conf_vldt_websocket_members[] = {
378 {
379 .name = nxt_string("read_timeout"),
380 .type = NXT_CONF_VLDT_INTEGER,
381 }, {
382
383 .name = nxt_string("keepalive_interval"),
384 .type = NXT_CONF_VLDT_INTEGER,
385 }, {
386 .name = nxt_string("max_frame_size"),
387 .type = NXT_CONF_VLDT_INTEGER,
388 },
389
390 NXT_CONF_VLDT_END
391 };
392
393
394 static nxt_conf_vldt_object_t nxt_conf_vldt_static_members[] = {
395 {
396 .name = nxt_string("mime_types"),
397 .type = NXT_CONF_VLDT_OBJECT,
398 .validator = nxt_conf_vldt_mtypes,
399 },
400
401 NXT_CONF_VLDT_END
402 };
403
404
405 static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = {
406 {
407 .name = nxt_string("pass"),
408 .type = NXT_CONF_VLDT_STRING,
409 .validator = nxt_conf_vldt_pass,
410 .flags = NXT_CONF_VLDT_TSTR,
411 }, {
412 .name = nxt_string("application"),
413 .type = NXT_CONF_VLDT_STRING,
414 .validator = nxt_conf_vldt_app_name,
415 }, {
416 .name = nxt_string("forwarded"),
417 .type = NXT_CONF_VLDT_OBJECT,
418 .validator = nxt_conf_vldt_forwarded,
419 }, {
420 .name = nxt_string("client_ip"),
421 .type = NXT_CONF_VLDT_OBJECT,
422 .validator = nxt_conf_vldt_object,
423 .u.members = nxt_conf_vldt_client_ip_members
424 },
425
426 #if (NXT_TLS)
427 {
428 .name = nxt_string("tls"),
429 .type = NXT_CONF_VLDT_OBJECT,
430 .validator = nxt_conf_vldt_object,
431 .u.members = nxt_conf_vldt_tls_members,
432 },
433 #endif
434
435 NXT_CONF_VLDT_END
436 };
437
438
439 static nxt_conf_vldt_object_t nxt_conf_vldt_forwarded_members[] = {
440 {
441 .name = nxt_string("client_ip"),
442 .type = NXT_CONF_VLDT_STRING,
443 }, {
444 .name = nxt_string("protocol"),
445 .type = NXT_CONF_VLDT_STRING,
446 }, {
447 .name = nxt_string("source"),
448 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
449 .validator = nxt_conf_vldt_match_addrs,
450 .flags = NXT_CONF_VLDT_REQUIRED
451 }, {
452 .name = nxt_string("recursive"),
453 .type = NXT_CONF_VLDT_BOOLEAN,
454 },
455
456 NXT_CONF_VLDT_END
457 };
458
459
460 static nxt_conf_vldt_object_t nxt_conf_vldt_client_ip_members[] = {
461 {
462 .name = nxt_string("source"),
463 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
464 .validator = nxt_conf_vldt_match_addrs,
465 .flags = NXT_CONF_VLDT_REQUIRED
466 }, {
467 .name = nxt_string("header"),
468 .type = NXT_CONF_VLDT_STRING,
469 .flags = NXT_CONF_VLDT_REQUIRED
470 }, {
471 .name = nxt_string("recursive"),
472 .type = NXT_CONF_VLDT_BOOLEAN,
473 },
474
475 NXT_CONF_VLDT_END
476 };
477
478
479 #if (NXT_TLS)
480
481 static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = {
482 {
483 .name = nxt_string("certificate"),
484 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
485 .flags = NXT_CONF_VLDT_REQUIRED,
486 .validator = nxt_conf_vldt_certificate,
487 }, {
488 .name = nxt_string("conf_commands"),
489 .type = NXT_CONF_VLDT_OBJECT,
490 #if (NXT_HAVE_OPENSSL_CONF_CMD)
491 .validator = nxt_conf_vldt_object_conf_commands,
492 #else
493 .validator = nxt_conf_vldt_unsupported,
494 .u.string = "conf_commands",
495 #endif
496 }, {
497 .name = nxt_string("session"),
498 .type = NXT_CONF_VLDT_OBJECT,
499 .validator = nxt_conf_vldt_object,
500 .u.members = nxt_conf_vldt_session_members,
501 },
502
503 NXT_CONF_VLDT_END
504 };
505
506
507 static nxt_conf_vldt_object_t nxt_conf_vldt_session_members[] = {
508 {
509 .name = nxt_string("cache_size"),
510 .type = NXT_CONF_VLDT_INTEGER,
511 .validator = nxt_conf_vldt_tls_cache_size,
512 }, {
513 .name = nxt_string("timeout"),
514 .type = NXT_CONF_VLDT_INTEGER,
515 .validator = nxt_conf_vldt_tls_timeout,
516 }, {
517 .name = nxt_string("tickets"),
518 .type = NXT_CONF_VLDT_STRING
519 | NXT_CONF_VLDT_ARRAY
520 | NXT_CONF_VLDT_BOOLEAN,
521 #if (NXT_HAVE_OPENSSL_TLSEXT)
522 .validator = nxt_conf_vldt_ticket_key,
523 #else
524 .validator = nxt_conf_vldt_unsupported,
525 .u.string = "tickets",
526 #endif
527 },
528
529 NXT_CONF_VLDT_END
530 };
531
532
533 static nxt_int_t
nxt_conf_vldt_tls_cache_size(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)534 nxt_conf_vldt_tls_cache_size(nxt_conf_validation_t *vldt,
535 nxt_conf_value_t *value, void *data)
536 {
537 int64_t cache_size;
538
539 cache_size = nxt_conf_get_number(value);
540
541 if (cache_size < 0) {
542 return nxt_conf_vldt_error(vldt, "The \"cache_size\" number must not "
543 "be negative.");
544 }
545
546 return NXT_OK;
547 }
548
549
550 static nxt_int_t
nxt_conf_vldt_tls_timeout(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)551 nxt_conf_vldt_tls_timeout(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
552 void *data)
553 {
554 int64_t timeout;
555
556 timeout = nxt_conf_get_number(value);
557
558 if (timeout <= 0) {
559 return nxt_conf_vldt_error(vldt, "The \"timeout\" number must be "
560 "greater than zero.");
561 }
562
563 return NXT_OK;
564 }
565
566 #endif
567
568 #if (NXT_HAVE_OPENSSL_TLSEXT)
569
570 static nxt_int_t
nxt_conf_vldt_ticket_key(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)571 nxt_conf_vldt_ticket_key(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
572 void *data)
573 {
574 if (nxt_conf_type(value) == NXT_CONF_BOOLEAN) {
575 return NXT_OK;
576 }
577
578 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
579 return nxt_conf_vldt_array_iterator(vldt, value,
580 &nxt_conf_vldt_ticket_key_element);
581 }
582
583 /* NXT_CONF_STRING */
584
585 return nxt_conf_vldt_ticket_key_element(vldt, value);
586 }
587
588
589 static nxt_int_t
nxt_conf_vldt_ticket_key_element(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)590 nxt_conf_vldt_ticket_key_element(nxt_conf_validation_t *vldt,
591 nxt_conf_value_t *value)
592 {
593 ssize_t ret;
594 nxt_str_t key;
595
596 if (nxt_conf_type(value) != NXT_CONF_STRING) {
597 return nxt_conf_vldt_error(vldt, "The \"key\" array must "
598 "contain only string values.");
599 }
600
601 nxt_conf_get_string(value, &key);
602
603 ret = nxt_base64_decode(NULL, key.start, key.length);
604 if (ret == NXT_ERROR) {
605 return nxt_conf_vldt_error(vldt, "Invalid Base64 format for the ticket "
606 "key \"%V\".", &key);
607 }
608
609 if (ret != 48 && ret != 80) {
610 return nxt_conf_vldt_error(vldt, "Invalid length %d of the ticket "
611 "key \"%V\". Must be 48 or 80 bytes.",
612 ret, &key);
613 }
614
615 return NXT_OK;
616 }
617
618 #endif
619
620
621 static nxt_conf_vldt_object_t nxt_conf_vldt_route_members[] = {
622 {
623 .name = nxt_string("match"),
624 .type = NXT_CONF_VLDT_OBJECT,
625 .validator = nxt_conf_vldt_object,
626 .u.members = nxt_conf_vldt_match_members,
627 }, {
628 .name = nxt_string("action"),
629 .type = NXT_CONF_VLDT_OBJECT,
630 .validator = nxt_conf_vldt_action,
631 },
632
633 NXT_CONF_VLDT_END
634 };
635
636
637 static nxt_conf_vldt_object_t nxt_conf_vldt_match_members[] = {
638 {
639 .name = nxt_string("method"),
640 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
641 .validator = nxt_conf_vldt_match_patterns,
642 .u.string = "method",
643 }, {
644 .name = nxt_string("scheme"),
645 .type = NXT_CONF_VLDT_STRING,
646 .validator = nxt_conf_vldt_match_scheme_pattern,
647 }, {
648 .name = nxt_string("host"),
649 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
650 .validator = nxt_conf_vldt_match_patterns,
651 .u.string = "host",
652 }, {
653 .name = nxt_string("source"),
654 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
655 .validator = nxt_conf_vldt_match_addrs,
656 }, {
657 .name = nxt_string("destination"),
658 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
659 .validator = nxt_conf_vldt_match_addrs,
660 }, {
661 .name = nxt_string("uri"),
662 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
663 .validator = nxt_conf_vldt_match_encoded_patterns,
664 .u.string = "uri"
665 }, {
666 .name = nxt_string("query"),
667 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
668 .validator = nxt_conf_vldt_match_encoded_patterns,
669 .u.string = "query"
670 }, {
671 .name = nxt_string("arguments"),
672 .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
673 .validator = nxt_conf_vldt_match_encoded_patterns_sets,
674 }, {
675 .name = nxt_string("headers"),
676 .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
677 .validator = nxt_conf_vldt_match_patterns_sets,
678 .u.string = "headers"
679 }, {
680 .name = nxt_string("cookies"),
681 .type = NXT_CONF_VLDT_OBJECT | NXT_CONF_VLDT_ARRAY,
682 .validator = nxt_conf_vldt_match_patterns_sets,
683 .u.string = "cookies"
684 },
685
686 NXT_CONF_VLDT_END
687 };
688
689
690 static nxt_conf_vldt_object_t nxt_conf_vldt_action_common_members[] = {
691 {
692 .name = nxt_string("rewrite"),
693 .type = NXT_CONF_VLDT_STRING,
694 .flags = NXT_CONF_VLDT_TSTR,
695 },
696 {
697 .name = nxt_string("response_headers"),
698 .type = NXT_CONF_VLDT_OBJECT,
699 .validator = nxt_conf_vldt_object_iterator,
700 .u.object = nxt_conf_vldt_response_header,
701 },
702
703 NXT_CONF_VLDT_END
704 };
705
706
707 static nxt_conf_vldt_object_t nxt_conf_vldt_pass_action_members[] = {
708 {
709 .name = nxt_string("pass"),
710 .type = NXT_CONF_VLDT_STRING,
711 .validator = nxt_conf_vldt_pass,
712 .flags = NXT_CONF_VLDT_TSTR,
713 },
714
715 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
716 };
717
718
719 static nxt_conf_vldt_object_t nxt_conf_vldt_return_action_members[] = {
720 {
721 .name = nxt_string("return"),
722 .type = NXT_CONF_VLDT_INTEGER,
723 .validator = nxt_conf_vldt_return,
724 }, {
725 .name = nxt_string("location"),
726 .type = NXT_CONF_VLDT_STRING,
727 .flags = NXT_CONF_VLDT_TSTR,
728 },
729
730 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
731 };
732
733
734 static nxt_conf_vldt_object_t nxt_conf_vldt_share_action_members[] = {
735 {
736 .name = nxt_string("share"),
737 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
738 .validator = nxt_conf_vldt_share,
739 }, {
740 .name = nxt_string("index"),
741 .type = NXT_CONF_VLDT_STRING,
742 }, {
743 .name = nxt_string("types"),
744 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
745 .validator = nxt_conf_vldt_match_patterns,
746 }, {
747 .name = nxt_string("fallback"),
748 .type = NXT_CONF_VLDT_OBJECT,
749 .validator = nxt_conf_vldt_action,
750 }, {
751 .name = nxt_string("chroot"),
752 .type = NXT_CONF_VLDT_STRING,
753 #if !(NXT_HAVE_OPENAT2)
754 .validator = nxt_conf_vldt_unsupported,
755 .u.string = "chroot",
756 #endif
757 .flags = NXT_CONF_VLDT_TSTR,
758 }, {
759 .name = nxt_string("follow_symlinks"),
760 .type = NXT_CONF_VLDT_BOOLEAN,
761 #if !(NXT_HAVE_OPENAT2)
762 .validator = nxt_conf_vldt_unsupported,
763 .u.string = "follow_symlinks",
764 #endif
765 }, {
766 .name = nxt_string("traverse_mounts"),
767 .type = NXT_CONF_VLDT_BOOLEAN,
768 #if !(NXT_HAVE_OPENAT2)
769 .validator = nxt_conf_vldt_unsupported,
770 .u.string = "traverse_mounts",
771 #endif
772 },
773
774 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
775 };
776
777
778 static nxt_conf_vldt_object_t nxt_conf_vldt_proxy_action_members[] = {
779 {
780 .name = nxt_string("proxy"),
781 .type = NXT_CONF_VLDT_STRING,
782 .validator = nxt_conf_vldt_proxy,
783 },
784
785 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_action_common_members)
786 };
787
788
789 static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = {
790 {
791 .name = nxt_string("executable"),
792 .type = NXT_CONF_VLDT_STRING,
793 .flags = NXT_CONF_VLDT_REQUIRED,
794 }, {
795 .name = nxt_string("arguments"),
796 .type = NXT_CONF_VLDT_ARRAY,
797 .validator = nxt_conf_vldt_array_iterator,
798 .u.array = nxt_conf_vldt_argument,
799 },
800
801 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
802 };
803
804
805 static nxt_conf_vldt_object_t nxt_conf_vldt_python_common_members[] = {
806 {
807 .name = nxt_string("home"),
808 .type = NXT_CONF_VLDT_STRING,
809 }, {
810 .name = nxt_string("path"),
811 .type = NXT_CONF_VLDT_STRING | NXT_CONF_VLDT_ARRAY,
812 .validator = nxt_conf_vldt_python_path,
813 }, {
814 .name = nxt_string("protocol"),
815 .type = NXT_CONF_VLDT_STRING,
816 .validator = nxt_conf_vldt_python_protocol,
817 }, {
818 .name = nxt_string("threads"),
819 .type = NXT_CONF_VLDT_INTEGER,
820 .validator = nxt_conf_vldt_threads,
821 }, {
822 .name = nxt_string("thread_stack_size"),
823 .type = NXT_CONF_VLDT_INTEGER,
824 .validator = nxt_conf_vldt_thread_stack_size,
825 },
826
827 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
828 };
829
830 static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = {
831 {
832 .name = nxt_string("module"),
833 .type = NXT_CONF_VLDT_STRING,
834 .validator = nxt_conf_vldt_targets_exclusive,
835 .u.string = "module",
836 }, {
837 .name = nxt_string("callable"),
838 .type = NXT_CONF_VLDT_STRING,
839 .validator = nxt_conf_vldt_targets_exclusive,
840 .u.string = "callable",
841 }, {
842 .name = nxt_string("prefix"),
843 .type = NXT_CONF_VLDT_STRING,
844 .validator = nxt_conf_vldt_targets_exclusive,
845 .u.string = "prefix",
846 }, {
847 .name = nxt_string("targets"),
848 .type = NXT_CONF_VLDT_OBJECT,
849 .validator = nxt_conf_vldt_targets,
850 .u.members = nxt_conf_vldt_python_target_members
851 },
852
853 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members)
854 };
855
856
857 static nxt_conf_vldt_object_t nxt_conf_vldt_python_target_members[] = {
858 {
859 .name = nxt_string("module"),
860 .type = NXT_CONF_VLDT_STRING,
861 .flags = NXT_CONF_VLDT_REQUIRED,
862 }, {
863 .name = nxt_string("callable"),
864 .type = NXT_CONF_VLDT_STRING,
865 }, {
866 .name = nxt_string("prefix"),
867 .type = NXT_CONF_VLDT_STRING,
868 .validator = nxt_conf_vldt_python_prefix,
869 },
870
871 NXT_CONF_VLDT_END
872 };
873
874
875 static nxt_conf_vldt_object_t nxt_conf_vldt_python_notargets_members[] = {
876 {
877 .name = nxt_string("module"),
878 .type = NXT_CONF_VLDT_STRING,
879 .flags = NXT_CONF_VLDT_REQUIRED,
880 }, {
881 .name = nxt_string("callable"),
882 .type = NXT_CONF_VLDT_STRING,
883 }, {
884 .name = nxt_string("prefix"),
885 .type = NXT_CONF_VLDT_STRING,
886 .validator = nxt_conf_vldt_python_prefix,
887 },
888
889 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_python_common_members)
890 };
891
892
893 static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = {
894 {
895 .name = nxt_string("root"),
896 .type = NXT_CONF_VLDT_ANY_TYPE,
897 .validator = nxt_conf_vldt_targets_exclusive,
898 .u.string = "root",
899 }, {
900 .name = nxt_string("script"),
901 .type = NXT_CONF_VLDT_ANY_TYPE,
902 .validator = nxt_conf_vldt_targets_exclusive,
903 .u.string = "script",
904 }, {
905 .name = nxt_string("index"),
906 .type = NXT_CONF_VLDT_ANY_TYPE,
907 .validator = nxt_conf_vldt_targets_exclusive,
908 .u.string = "index",
909 }, {
910 .name = nxt_string("targets"),
911 .type = NXT_CONF_VLDT_OBJECT,
912 .validator = nxt_conf_vldt_targets,
913 .u.members = nxt_conf_vldt_php_target_members
914 },
915
916 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_php_common_members)
917 };
918
919
920 static nxt_conf_vldt_object_t nxt_conf_vldt_php_common_members[] = {
921 {
922 .name = nxt_string("options"),
923 .type = NXT_CONF_VLDT_OBJECT,
924 .validator = nxt_conf_vldt_object,
925 .u.members = nxt_conf_vldt_php_options_members,
926 },
927
928 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
929 };
930
931
932 static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[] = {
933 {
934 .name = nxt_string("file"),
935 .type = NXT_CONF_VLDT_STRING,
936 }, {
937 .name = nxt_string("admin"),
938 .type = NXT_CONF_VLDT_OBJECT,
939 .validator = nxt_conf_vldt_object_iterator,
940 .u.object = nxt_conf_vldt_php_option,
941 }, {
942 .name = nxt_string("user"),
943 .type = NXT_CONF_VLDT_OBJECT,
944 .validator = nxt_conf_vldt_object_iterator,
945 .u.object = nxt_conf_vldt_php_option,
946 },
947
948 NXT_CONF_VLDT_END
949 };
950
951
952 static nxt_conf_vldt_object_t nxt_conf_vldt_php_target_members[] = {
953 {
954 .name = nxt_string("root"),
955 .type = NXT_CONF_VLDT_STRING,
956 .flags = NXT_CONF_VLDT_REQUIRED,
957 }, {
958 .name = nxt_string("script"),
959 .type = NXT_CONF_VLDT_STRING,
960 }, {
961 .name = nxt_string("index"),
962 .type = NXT_CONF_VLDT_STRING,
963 },
964
965 NXT_CONF_VLDT_END
966 };
967
968
969 static nxt_conf_vldt_object_t nxt_conf_vldt_php_notargets_members[] = {
970 {
971 .name = nxt_string("root"),
972 .type = NXT_CONF_VLDT_STRING,
973 .flags = NXT_CONF_VLDT_REQUIRED,
974 }, {
975 .name = nxt_string("script"),
976 .type = NXT_CONF_VLDT_STRING,
977 }, {
978 .name = nxt_string("index"),
979 .type = NXT_CONF_VLDT_STRING,
980 },
981
982 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_php_common_members)
983 };
984
985
986 static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = {
987 {
988 .name = nxt_string("script"),
989 .type = NXT_CONF_VLDT_STRING,
990 .flags = NXT_CONF_VLDT_REQUIRED,
991 }, {
992 .name = nxt_string("threads"),
993 .type = NXT_CONF_VLDT_INTEGER,
994 .validator = nxt_conf_vldt_threads,
995 }, {
996 .name = nxt_string("thread_stack_size"),
997 .type = NXT_CONF_VLDT_INTEGER,
998 .validator = nxt_conf_vldt_thread_stack_size,
999 },
1000
1001 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
1002 };
1003
1004
1005 static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = {
1006 {
1007 .name = nxt_string("script"),
1008 .type = NXT_CONF_VLDT_STRING,
1009 .flags = NXT_CONF_VLDT_REQUIRED,
1010 }, {
1011 .name = nxt_string("threads"),
1012 .type = NXT_CONF_VLDT_INTEGER,
1013 .validator = nxt_conf_vldt_threads,
1014 }, {
1015 .name = nxt_string("hooks"),
1016 .type = NXT_CONF_VLDT_STRING
1017 },
1018
1019 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
1020 };
1021
1022
1023 static nxt_conf_vldt_object_t nxt_conf_vldt_java_members[] = {
1024 {
1025 .name = nxt_string("classpath"),
1026 .type = NXT_CONF_VLDT_ARRAY,
1027 .validator = nxt_conf_vldt_array_iterator,
1028 .u.array = nxt_conf_vldt_java_classpath,
1029 }, {
1030 .name = nxt_string("webapp"),
1031 .type = NXT_CONF_VLDT_STRING,
1032 .flags = NXT_CONF_VLDT_REQUIRED,
1033 }, {
1034 .name = nxt_string("options"),
1035 .type = NXT_CONF_VLDT_ARRAY,
1036 .validator = nxt_conf_vldt_array_iterator,
1037 .u.array = nxt_conf_vldt_java_option,
1038 }, {
1039 .name = nxt_string("unit_jars"),
1040 .type = NXT_CONF_VLDT_STRING,
1041 }, {
1042 .name = nxt_string("threads"),
1043 .type = NXT_CONF_VLDT_INTEGER,
1044 .validator = nxt_conf_vldt_threads,
1045 }, {
1046 .name = nxt_string("thread_stack_size"),
1047 .type = NXT_CONF_VLDT_INTEGER,
1048 .validator = nxt_conf_vldt_thread_stack_size,
1049 },
1050
1051 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
1052 };
1053
1054
1055 static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_members[] = {
1056 {
1057 .name = nxt_string("module"),
1058 .type = NXT_CONF_VLDT_STRING,
1059 .flags = NXT_CONF_VLDT_REQUIRED,
1060 }, {
1061 .name = nxt_string("request_handler"),
1062 .type = NXT_CONF_VLDT_STRING,
1063 .flags = NXT_CONF_VLDT_REQUIRED,
1064 },{
1065 .name = nxt_string("malloc_handler"),
1066 .type = NXT_CONF_VLDT_STRING,
1067 .flags = NXT_CONF_VLDT_REQUIRED,
1068 }, {
1069 .name = nxt_string("free_handler"),
1070 .type = NXT_CONF_VLDT_STRING,
1071 .flags = NXT_CONF_VLDT_REQUIRED,
1072 }, {
1073 .name = nxt_string("module_init_handler"),
1074 .type = NXT_CONF_VLDT_STRING,
1075 }, {
1076 .name = nxt_string("module_end_handler"),
1077 .type = NXT_CONF_VLDT_STRING,
1078 }, {
1079 .name = nxt_string("request_init_handler"),
1080 .type = NXT_CONF_VLDT_STRING,
1081 }, {
1082 .name = nxt_string("request_end_handler"),
1083 .type = NXT_CONF_VLDT_STRING,
1084 }, {
1085 .name = nxt_string("response_end_handler"),
1086 .type = NXT_CONF_VLDT_STRING,
1087 }, {
1088 .name = nxt_string("access"),
1089 .type = NXT_CONF_VLDT_OBJECT,
1090 .validator = nxt_conf_vldt_object,
1091 .u.members = nxt_conf_vldt_wasm_access_members,
1092 },
1093
1094 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
1095 };
1096
1097
1098 static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_wc_members[] = {
1099 {
1100 .name = nxt_string("component"),
1101 .type = NXT_CONF_VLDT_STRING,
1102 .flags = NXT_CONF_VLDT_REQUIRED,
1103 }, {
1104 .name = nxt_string("access"),
1105 .type = NXT_CONF_VLDT_OBJECT,
1106 .validator = nxt_conf_vldt_object,
1107 .u.members = nxt_conf_vldt_wasm_access_members,
1108 },
1109
1110 NXT_CONF_VLDT_NEXT(nxt_conf_vldt_common_members)
1111 };
1112
1113
1114 static nxt_conf_vldt_object_t nxt_conf_vldt_wasm_access_members[] = {
1115 {
1116 .name = nxt_string("filesystem"),
1117 .type = NXT_CONF_VLDT_ARRAY,
1118 },
1119
1120 NXT_CONF_VLDT_END
1121 };
1122
1123
1124 static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = {
1125 {
1126 .name = nxt_string("type"),
1127 .type = NXT_CONF_VLDT_STRING,
1128 }, {
1129 .name = nxt_string("limits"),
1130 .type = NXT_CONF_VLDT_OBJECT,
1131 .validator = nxt_conf_vldt_object,
1132 .u.members = nxt_conf_vldt_app_limits_members,
1133 }, {
1134 .name = nxt_string("processes"),
1135 .type = NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT,
1136 .validator = nxt_conf_vldt_processes,
1137 .u.members = nxt_conf_vldt_app_processes_members,
1138 }, {
1139 .name = nxt_string("user"),
1140 .type = NXT_CONF_VLDT_STRING,
1141 }, {
1142 .name = nxt_string("group"),
1143 .type = NXT_CONF_VLDT_STRING,
1144 }, {
1145 .name = nxt_string("working_directory"),
1146 .type = NXT_CONF_VLDT_STRING,
1147 }, {
1148 .name = nxt_string("environment"),
1149 .type = NXT_CONF_VLDT_OBJECT,
1150 .validator = nxt_conf_vldt_object_iterator,
1151 .u.object = nxt_conf_vldt_environment,
1152 }, {
1153 .name = nxt_string("isolation"),
1154 .type = NXT_CONF_VLDT_OBJECT,
1155 .validator = nxt_conf_vldt_isolation,
1156 .u.members = nxt_conf_vldt_app_isolation_members,
1157 }, {
1158 .name = nxt_string("stdout"),
1159 .type = NXT_CONF_VLDT_STRING,
1160 }, {
1161 .name = nxt_string("stderr"),
1162 .type = NXT_CONF_VLDT_STRING,
1163 },
1164
1165 NXT_CONF_VLDT_END
1166 };
1167
1168
1169 static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = {
1170 {
1171 .name = nxt_string("timeout"),
1172 .type = NXT_CONF_VLDT_INTEGER,
1173 }, {
1174 .name = nxt_string("requests"),
1175 .type = NXT_CONF_VLDT_INTEGER,
1176 }, {
1177 .name = nxt_string("shm"),
1178 .type = NXT_CONF_VLDT_INTEGER,
1179 },
1180
1181 NXT_CONF_VLDT_END
1182 };
1183
1184
1185 static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = {
1186 {
1187 .name = nxt_string("spare"),
1188 .type = NXT_CONF_VLDT_INTEGER,
1189 }, {
1190 .name = nxt_string("max"),
1191 .type = NXT_CONF_VLDT_INTEGER,
1192 }, {
1193 .name = nxt_string("idle_timeout"),
1194 .type = NXT_CONF_VLDT_INTEGER,
1195 },
1196
1197 NXT_CONF_VLDT_END
1198 };
1199
1200
1201 static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = {
1202 {
1203 .name = nxt_string("namespaces"),
1204 .type = NXT_CONF_VLDT_OBJECT,
1205 .validator = nxt_conf_vldt_clone_namespaces,
1206 .u.members = nxt_conf_vldt_app_namespaces_members,
1207 },
1208
1209 #if (NXT_HAVE_CLONE_NEWUSER)
1210 {
1211 .name = nxt_string("uidmap"),
1212 .type = NXT_CONF_VLDT_ARRAY,
1213 .validator = nxt_conf_vldt_array_iterator,
1214 .u.array = nxt_conf_vldt_clone_uidmap,
1215 }, {
1216 .name = nxt_string("gidmap"),
1217 .type = NXT_CONF_VLDT_ARRAY,
1218 .validator = nxt_conf_vldt_array_iterator,
1219 .u.array = nxt_conf_vldt_clone_gidmap,
1220 },
1221 #endif
1222
1223 #if (NXT_HAVE_ISOLATION_ROOTFS)
1224 {
1225 .name = nxt_string("rootfs"),
1226 .type = NXT_CONF_VLDT_STRING,
1227 }, {
1228 .name = nxt_string("automount"),
1229 .type = NXT_CONF_VLDT_OBJECT,
1230 .validator = nxt_conf_vldt_object,
1231 .u.members = nxt_conf_vldt_app_automount_members,
1232 },
1233 #endif
1234
1235 #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
1236 {
1237 .name = nxt_string("new_privs"),
1238 .type = NXT_CONF_VLDT_BOOLEAN,
1239 },
1240 #endif
1241
1242 #if (NXT_HAVE_CGROUP)
1243 {
1244 .name = nxt_string("cgroup"),
1245 .type = NXT_CONF_VLDT_OBJECT,
1246 .validator = nxt_conf_vldt_object,
1247 .u.members = nxt_conf_vldt_app_cgroup_members,
1248 },
1249 #endif
1250
1251 NXT_CONF_VLDT_END
1252 };
1253
1254
1255 static nxt_conf_vldt_object_t nxt_conf_vldt_app_namespaces_members[] = {
1256
1257 #if (NXT_HAVE_CLONE_NEWUSER)
1258 {
1259 .name = nxt_string("credential"),
1260 .type = NXT_CONF_VLDT_BOOLEAN,
1261 },
1262 #endif
1263
1264 #if (NXT_HAVE_CLONE_NEWPID)
1265 {
1266 .name = nxt_string("pid"),
1267 .type = NXT_CONF_VLDT_BOOLEAN,
1268 },
1269 #endif
1270
1271 #if (NXT_HAVE_CLONE_NEWNET)
1272 {
1273 .name = nxt_string("network"),
1274 .type = NXT_CONF_VLDT_BOOLEAN,
1275 },
1276 #endif
1277
1278 #if (NXT_HAVE_CLONE_NEWNS)
1279 {
1280 .name = nxt_string("mount"),
1281 .type = NXT_CONF_VLDT_BOOLEAN,
1282 },
1283 #endif
1284
1285 #if (NXT_HAVE_CLONE_NEWUTS)
1286 {
1287 .name = nxt_string("uname"),
1288 .type = NXT_CONF_VLDT_BOOLEAN,
1289 },
1290 #endif
1291
1292 #if (NXT_HAVE_CLONE_NEWCGROUP)
1293 {
1294 .name = nxt_string("cgroup"),
1295 .type = NXT_CONF_VLDT_BOOLEAN,
1296 },
1297 #endif
1298
1299 NXT_CONF_VLDT_END
1300 };
1301
1302
1303 #if (NXT_HAVE_ISOLATION_ROOTFS)
1304
1305 static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[] = {
1306 {
1307 .name = nxt_string("language_deps"),
1308 .type = NXT_CONF_VLDT_BOOLEAN,
1309 }, {
1310 .name = nxt_string("tmpfs"),
1311 .type = NXT_CONF_VLDT_BOOLEAN,
1312 }, {
1313 .name = nxt_string("procfs"),
1314 .type = NXT_CONF_VLDT_BOOLEAN,
1315 },
1316
1317 NXT_CONF_VLDT_END
1318 };
1319
1320 #endif
1321
1322
1323 #if (NXT_HAVE_CGROUP)
1324
1325 static nxt_conf_vldt_object_t nxt_conf_vldt_app_cgroup_members[] = {
1326 {
1327 .name = nxt_string("path"),
1328 .type = NXT_CONF_VLDT_STRING,
1329 .flags = NXT_CONF_VLDT_REQUIRED,
1330 .validator = nxt_conf_vldt_cgroup_path,
1331 },
1332
1333 NXT_CONF_VLDT_END
1334 };
1335
1336 #endif
1337
1338
1339 #if (NXT_HAVE_CLONE_NEWUSER)
1340
1341 static nxt_conf_vldt_object_t nxt_conf_vldt_app_procmap_members[] = {
1342 {
1343 .name = nxt_string("container"),
1344 .type = NXT_CONF_VLDT_INTEGER,
1345 .flags = NXT_CONF_VLDT_REQUIRED,
1346 }, {
1347 .name = nxt_string("host"),
1348 .type = NXT_CONF_VLDT_INTEGER,
1349 .flags = NXT_CONF_VLDT_REQUIRED,
1350 }, {
1351 .name = nxt_string("size"),
1352 .type = NXT_CONF_VLDT_INTEGER,
1353 .flags = NXT_CONF_VLDT_REQUIRED,
1354 },
1355
1356 NXT_CONF_VLDT_END
1357 };
1358
1359 #endif
1360
1361
1362 static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_members[] = {
1363 {
1364 .name = nxt_string("servers"),
1365 .type = NXT_CONF_VLDT_OBJECT,
1366 .validator = nxt_conf_vldt_object_iterator,
1367 .u.object = nxt_conf_vldt_server,
1368 },
1369
1370 NXT_CONF_VLDT_END
1371 };
1372
1373
1374 static nxt_conf_vldt_object_t nxt_conf_vldt_upstream_server_members[] = {
1375 {
1376 .name = nxt_string("weight"),
1377 .type = NXT_CONF_VLDT_NUMBER,
1378 .validator = nxt_conf_vldt_server_weight,
1379 },
1380
1381 NXT_CONF_VLDT_END
1382 };
1383
1384
1385 static nxt_conf_vldt_object_t nxt_conf_vldt_access_log_members[] = {
1386 {
1387 .name = nxt_string("path"),
1388 .type = NXT_CONF_VLDT_STRING,
1389 }, {
1390 .name = nxt_string("format"),
1391 .type = NXT_CONF_VLDT_STRING,
1392 }, {
1393 .name = nxt_string("if"),
1394 .type = NXT_CONF_VLDT_STRING,
1395 .validator = nxt_conf_vldt_if,
1396 },
1397
1398 NXT_CONF_VLDT_END
1399 };
1400
1401
1402 nxt_int_t
nxt_conf_validate(nxt_conf_validation_t * vldt)1403 nxt_conf_validate(nxt_conf_validation_t *vldt)
1404 {
1405 nxt_int_t ret;
1406 u_char error[NXT_MAX_ERROR_STR];
1407
1408 vldt->tstr_state = nxt_tstr_state_new(vldt->pool, 1);
1409 if (nxt_slow_path(vldt->tstr_state == NULL)) {
1410 return NXT_ERROR;
1411 }
1412
1413 ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT);
1414 if (ret != NXT_OK) {
1415 return ret;
1416 }
1417
1418 ret = nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members);
1419 if (ret != NXT_OK) {
1420 return ret;
1421 }
1422
1423 ret = nxt_tstr_state_done(vldt->tstr_state, error);
1424 if (ret != NXT_OK) {
1425 ret = nxt_conf_vldt_error(vldt, "%s", error);
1426 return ret;
1427 }
1428
1429 return NXT_OK;
1430 }
1431
1432
1433 #define NXT_CONF_VLDT_ANY_TYPE_STR \
1434 "either a null, a boolean, an integer, " \
1435 "a number, a string, an array, or an object"
1436
1437
1438 static nxt_int_t
nxt_conf_vldt_type(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value,nxt_conf_vldt_type_t type)1439 nxt_conf_vldt_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
1440 nxt_conf_value_t *value, nxt_conf_vldt_type_t type)
1441 {
1442 u_char *p;
1443 nxt_str_t expected;
1444 nxt_bool_t comma;
1445 nxt_uint_t value_type, n, t;
1446 u_char buf[nxt_length(NXT_CONF_VLDT_ANY_TYPE_STR)];
1447
1448 static nxt_str_t type_name[] = {
1449 nxt_string("a null"),
1450 nxt_string("a boolean"),
1451 nxt_string("an integer number"),
1452 nxt_string("a fractional number"),
1453 nxt_string("a string"),
1454 nxt_string("an array"),
1455 nxt_string("an object"),
1456 };
1457
1458 value_type = nxt_conf_type(value);
1459
1460 if ((1 << value_type) & type) {
1461 return NXT_OK;
1462 }
1463
1464 p = buf;
1465
1466 n = nxt_popcount(type);
1467
1468 if (n > 1) {
1469 p = nxt_cpymem(p, "either ", 7);
1470 }
1471
1472 comma = (n > 2);
1473
1474 for ( ;; ) {
1475 t = __builtin_ffs(type) - 1;
1476
1477 p = nxt_cpymem(p, type_name[t].start, type_name[t].length);
1478
1479 n--;
1480
1481 if (n == 0) {
1482 break;
1483 }
1484
1485 if (comma) {
1486 *p++ = ',';
1487 }
1488
1489 if (n == 1) {
1490 p = nxt_cpymem(p, " or", 3);
1491 }
1492
1493 *p++ = ' ';
1494
1495 type = type & ~(1 << t);
1496 }
1497
1498 expected.length = p - buf;
1499 expected.start = buf;
1500
1501 if (name == NULL) {
1502 return nxt_conf_vldt_error(vldt,
1503 "The configuration must be %V, but not %V.",
1504 &expected, &type_name[value_type]);
1505 }
1506
1507 return nxt_conf_vldt_error(vldt,
1508 "The \"%V\" value must be %V, but not %V.",
1509 name, &expected, &type_name[value_type]);
1510 }
1511
1512
1513 static nxt_int_t
nxt_conf_vldt_error(nxt_conf_validation_t * vldt,const char * fmt,...)1514 nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...)
1515 {
1516 u_char *p, *end;
1517 size_t size;
1518 va_list args;
1519 u_char error[NXT_MAX_ERROR_STR];
1520
1521 va_start(args, fmt);
1522 end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args);
1523 va_end(args);
1524
1525 size = end - error;
1526
1527 p = nxt_mp_nget(vldt->pool, size);
1528 if (p == NULL) {
1529 return NXT_ERROR;
1530 }
1531
1532 nxt_memcpy(p, error, size);
1533
1534 vldt->error.length = size;
1535 vldt->error.start = p;
1536
1537 return NXT_DECLINED;
1538 }
1539
1540
1541 nxt_inline nxt_int_t
nxt_conf_vldt_unsupported(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1542 nxt_conf_vldt_unsupported(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1543 void *data)
1544 {
1545 return nxt_conf_vldt_error(vldt, "Unit is built without the \"%s\" "
1546 "option support.", data);
1547 }
1548
1549
1550 static nxt_int_t
nxt_conf_vldt_var(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_str_t * value)1551 nxt_conf_vldt_var(nxt_conf_validation_t *vldt, nxt_str_t *name,
1552 nxt_str_t *value)
1553 {
1554 u_char error[NXT_MAX_ERROR_STR];
1555
1556 if (nxt_tstr_test(vldt->tstr_state, value, error) != NXT_OK) {
1557 return nxt_conf_vldt_error(vldt, "%s in the \"%V\" value.",
1558 error, name);
1559 }
1560
1561 return NXT_OK;
1562 }
1563
1564
1565 static nxt_int_t
nxt_conf_vldt_if(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1566 nxt_conf_vldt_if(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1567 void *data)
1568 {
1569 nxt_str_t str;
1570
1571 static nxt_str_t if_str = nxt_string("if");
1572
1573 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1574 return nxt_conf_vldt_error(vldt, "The \"if\" must be a string");
1575 }
1576
1577 nxt_conf_get_string(value, &str);
1578
1579 if (str.length == 0) {
1580 return NXT_OK;
1581 }
1582
1583 if (str.start[0] == '!') {
1584 str.start++;
1585 str.length--;
1586 }
1587
1588 if (nxt_is_tstr(&str)) {
1589 return nxt_conf_vldt_var(vldt, &if_str, &str);
1590 }
1591
1592 return NXT_OK;
1593 }
1594
1595
1596 typedef struct {
1597 nxt_mp_t *pool;
1598 nxt_str_t *type;
1599 nxt_lvlhsh_t hash;
1600 } nxt_conf_vldt_mtypes_ctx_t;
1601
1602
1603 static nxt_int_t
nxt_conf_vldt_mtypes(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1604 nxt_conf_vldt_mtypes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1605 void *data)
1606 {
1607 nxt_int_t ret;
1608 nxt_conf_vldt_mtypes_ctx_t ctx;
1609
1610 ctx.pool = nxt_mp_create(1024, 128, 256, 32);
1611 if (nxt_slow_path(ctx.pool == NULL)) {
1612 return NXT_ERROR;
1613 }
1614
1615 nxt_lvlhsh_init(&ctx.hash);
1616
1617 vldt->ctx = &ctx;
1618
1619 ret = nxt_conf_vldt_object_iterator(vldt, value,
1620 &nxt_conf_vldt_mtypes_type);
1621
1622 vldt->ctx = NULL;
1623
1624 nxt_mp_destroy(ctx.pool);
1625
1626 return ret;
1627 }
1628
1629
1630 static nxt_int_t
nxt_conf_vldt_mtypes_type(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)1631 nxt_conf_vldt_mtypes_type(nxt_conf_validation_t *vldt, nxt_str_t *name,
1632 nxt_conf_value_t *value)
1633 {
1634 nxt_int_t ret;
1635 nxt_conf_vldt_mtypes_ctx_t *ctx;
1636
1637 ret = nxt_conf_vldt_type(vldt, name, value,
1638 NXT_CONF_VLDT_STRING|NXT_CONF_VLDT_ARRAY);
1639 if (ret != NXT_OK) {
1640 return ret;
1641 }
1642
1643 ctx = vldt->ctx;
1644
1645 ctx->type = nxt_mp_get(ctx->pool, sizeof(nxt_str_t));
1646 if (nxt_slow_path(ctx->type == NULL)) {
1647 return NXT_ERROR;
1648 }
1649
1650 *ctx->type = *name;
1651
1652 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1653 return nxt_conf_vldt_array_iterator(vldt, value,
1654 &nxt_conf_vldt_mtypes_extension);
1655 }
1656
1657 /* NXT_CONF_STRING */
1658
1659 return nxt_conf_vldt_mtypes_extension(vldt, value);
1660 }
1661
1662
1663 static nxt_int_t
nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)1664 nxt_conf_vldt_mtypes_extension(nxt_conf_validation_t *vldt,
1665 nxt_conf_value_t *value)
1666 {
1667 nxt_str_t exten, *dup_type;
1668 nxt_conf_vldt_mtypes_ctx_t *ctx;
1669
1670 ctx = vldt->ctx;
1671
1672 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1673 return nxt_conf_vldt_error(vldt, "The \"%V\" MIME type array must "
1674 "contain only strings.", ctx->type);
1675 }
1676
1677 nxt_conf_get_string(value, &exten);
1678
1679 if (exten.length == 0) {
1680 return nxt_conf_vldt_error(vldt, "An empty file extension for "
1681 "the \"%V\" MIME type.", ctx->type);
1682 }
1683
1684 dup_type = nxt_http_static_mtype_get(&ctx->hash, &exten);
1685
1686 if (dup_type->length != 0) {
1687 return nxt_conf_vldt_error(vldt, "The \"%V\" file extension has been "
1688 "declared for \"%V\" and \"%V\" "
1689 "MIME types at the same time.",
1690 &exten, dup_type, ctx->type);
1691 }
1692
1693 return nxt_http_static_mtypes_hash_add(ctx->pool, &ctx->hash, &exten,
1694 ctx->type);
1695 }
1696
1697
1698 static nxt_int_t
nxt_conf_vldt_listener(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)1699 nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name,
1700 nxt_conf_value_t *value)
1701 {
1702 nxt_int_t ret;
1703 nxt_str_t str;
1704 nxt_sockaddr_t *sa;
1705
1706 if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) {
1707 return NXT_ERROR;
1708 }
1709
1710 sa = nxt_sockaddr_parse(vldt->pool, &str);
1711 if (nxt_slow_path(sa == NULL)) {
1712 return nxt_conf_vldt_error(vldt,
1713 "The listener address \"%V\" is invalid.",
1714 name);
1715 }
1716
1717 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
1718 if (ret != NXT_OK) {
1719 return ret;
1720 }
1721
1722 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members);
1723 }
1724
1725
1726 static nxt_int_t
nxt_conf_vldt_action(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1727 nxt_conf_vldt_action(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1728 void *data)
1729 {
1730 nxt_uint_t i;
1731 nxt_conf_value_t *action;
1732 nxt_conf_vldt_object_t *members;
1733
1734 static struct {
1735 nxt_str_t name;
1736 nxt_conf_vldt_object_t *members;
1737
1738 } actions[] = {
1739 { nxt_string("pass"), nxt_conf_vldt_pass_action_members },
1740 { nxt_string("return"), nxt_conf_vldt_return_action_members },
1741 { nxt_string("share"), nxt_conf_vldt_share_action_members },
1742 { nxt_string("proxy"), nxt_conf_vldt_proxy_action_members },
1743 };
1744
1745 members = NULL;
1746
1747 for (i = 0; i < nxt_nitems(actions); i++) {
1748 action = nxt_conf_get_object_member(value, &actions[i].name, NULL);
1749
1750 if (action == NULL) {
1751 continue;
1752 }
1753
1754 if (members != NULL) {
1755 return nxt_conf_vldt_error(vldt, "The \"action\" object must have "
1756 "just one of \"pass\", \"return\", "
1757 "\"share\", or \"proxy\" options set.");
1758 }
1759
1760 members = actions[i].members;
1761 }
1762
1763 if (members == NULL) {
1764 return nxt_conf_vldt_error(vldt, "The \"action\" object must have "
1765 "either \"pass\", \"return\", \"share\", "
1766 "or \"proxy\" option set.");
1767 }
1768
1769 return nxt_conf_vldt_object(vldt, value, members);
1770 }
1771
1772
1773 static nxt_int_t
nxt_conf_vldt_pass(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1774 nxt_conf_vldt_pass(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1775 void *data)
1776 {
1777 nxt_str_t pass;
1778 nxt_int_t ret;
1779 nxt_str_t segments[3];
1780
1781 static nxt_str_t targets_str = nxt_string("targets");
1782
1783 nxt_conf_get_string(value, &pass);
1784
1785 ret = nxt_http_pass_segments(vldt->pool, &pass, segments, 3);
1786
1787 if (ret != NXT_OK) {
1788 if (ret == NXT_DECLINED) {
1789 return nxt_conf_vldt_error(vldt, "Request \"pass\" value \"%V\" "
1790 "is invalid.", &pass);
1791 }
1792
1793 return NXT_ERROR;
1794 }
1795
1796 if (nxt_str_eq(&segments[0], "applications", 12)) {
1797
1798 if (segments[1].length == 0) {
1799 goto error;
1800 }
1801
1802 value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
1803
1804 if (value == NULL) {
1805 goto error;
1806 }
1807
1808 value = nxt_conf_get_object_member(value, &segments[1], NULL);
1809
1810 if (value == NULL) {
1811 goto error;
1812 }
1813
1814 if (segments[2].length > 0) {
1815 value = nxt_conf_get_object_member(value, &targets_str, NULL);
1816
1817 if (value == NULL) {
1818 goto error;
1819 }
1820
1821 value = nxt_conf_get_object_member(value, &segments[2], NULL);
1822
1823 if (value == NULL) {
1824 goto error;
1825 }
1826 }
1827
1828 return NXT_OK;
1829 }
1830
1831 if (nxt_str_eq(&segments[0], "upstreams", 9)) {
1832
1833 if (segments[1].length == 0 || segments[2].length != 0) {
1834 goto error;
1835 }
1836
1837 value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
1838
1839 if (value == NULL) {
1840 goto error;
1841 }
1842
1843 value = nxt_conf_get_object_member(value, &segments[1], NULL);
1844
1845 if (value == NULL) {
1846 goto error;
1847 }
1848
1849 return NXT_OK;
1850 }
1851
1852 if (nxt_str_eq(&segments[0], "routes", 6)) {
1853
1854 if (segments[2].length != 0) {
1855 goto error;
1856 }
1857
1858 value = nxt_conf_get_object_member(vldt->conf, &segments[0], NULL);
1859
1860 if (value == NULL) {
1861 goto error;
1862 }
1863
1864 if (segments[1].length == 0) {
1865 if (nxt_conf_type(value) != NXT_CONF_ARRAY) {
1866 goto error;
1867 }
1868
1869 return NXT_OK;
1870 }
1871
1872 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
1873 goto error;
1874 }
1875
1876 value = nxt_conf_get_object_member(value, &segments[1], NULL);
1877
1878 if (value == NULL) {
1879 goto error;
1880 }
1881
1882 return NXT_OK;
1883 }
1884
1885 error:
1886
1887 return nxt_conf_vldt_error(vldt, "Request \"pass\" points to invalid "
1888 "location \"%V\".", &pass);
1889 }
1890
1891
1892 static nxt_int_t
nxt_conf_vldt_return(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1893 nxt_conf_vldt_return(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1894 void *data)
1895 {
1896 int64_t status;
1897
1898 status = nxt_conf_get_number(value);
1899
1900 if (status < NXT_HTTP_INVALID || status > NXT_HTTP_STATUS_MAX) {
1901 return nxt_conf_vldt_error(vldt, "The \"return\" value is out of "
1902 "allowed HTTP status code range 0-999.");
1903 }
1904
1905 return NXT_OK;
1906 }
1907
1908
1909 static nxt_int_t
nxt_conf_vldt_share(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1910 nxt_conf_vldt_share(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1911 void *data)
1912 {
1913 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
1914 if (nxt_conf_array_elements_count(value) == 0) {
1915 return nxt_conf_vldt_error(vldt, "The \"share\" array "
1916 "must contain at least one element.");
1917 }
1918
1919 return nxt_conf_vldt_array_iterator(vldt, value,
1920 &nxt_conf_vldt_share_element);
1921 }
1922
1923 /* NXT_CONF_STRING */
1924
1925 return nxt_conf_vldt_share_element(vldt, value);
1926 }
1927
1928
1929 static nxt_int_t
nxt_conf_vldt_share_element(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)1930 nxt_conf_vldt_share_element(nxt_conf_validation_t *vldt,
1931 nxt_conf_value_t *value)
1932 {
1933 nxt_str_t str;
1934
1935 static nxt_str_t share = nxt_string("share");
1936
1937 if (nxt_conf_type(value) != NXT_CONF_STRING) {
1938 return nxt_conf_vldt_error(vldt, "The \"share\" array must "
1939 "contain only string values.");
1940 }
1941
1942 nxt_conf_get_string(value, &str);
1943
1944 if (nxt_is_tstr(&str)) {
1945 return nxt_conf_vldt_var(vldt, &share, &str);
1946 }
1947
1948 return NXT_OK;
1949 }
1950
1951
1952 static nxt_int_t
nxt_conf_vldt_proxy(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1953 nxt_conf_vldt_proxy(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1954 void *data)
1955 {
1956 nxt_str_t name, *ret;
1957 nxt_sockaddr_t *sa;
1958
1959 ret = nxt_conf_get_string_dup(value, vldt->pool, &name);
1960 if (nxt_slow_path(ret == NULL)) {
1961 return NXT_ERROR;
1962 }
1963
1964 if (nxt_str_start(&name, "http://", 7)) {
1965 name.length -= 7;
1966 name.start += 7;
1967
1968 sa = nxt_sockaddr_parse(vldt->pool, &name);
1969 if (sa != NULL) {
1970 return NXT_OK;
1971 }
1972 }
1973
1974 return nxt_conf_vldt_error(vldt, "The \"proxy\" address is invalid \"%V\"",
1975 &name);
1976 }
1977
1978
1979 static nxt_int_t
nxt_conf_vldt_python(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1980 nxt_conf_vldt_python(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
1981 void *data)
1982 {
1983 nxt_conf_value_t *targets;
1984
1985 static nxt_str_t targets_str = nxt_string("targets");
1986
1987 targets = nxt_conf_get_object_member(value, &targets_str, NULL);
1988
1989 if (targets != NULL) {
1990 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_python_members);
1991 }
1992
1993 return nxt_conf_vldt_object(vldt, value,
1994 nxt_conf_vldt_python_notargets_members);
1995 }
1996
1997
1998 static nxt_int_t
nxt_conf_vldt_python_path(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)1999 nxt_conf_vldt_python_path(nxt_conf_validation_t *vldt,
2000 nxt_conf_value_t *value, void *data)
2001 {
2002 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
2003 return nxt_conf_vldt_array_iterator(vldt, value,
2004 &nxt_conf_vldt_python_path_element);
2005 }
2006
2007 /* NXT_CONF_STRING */
2008
2009 return NXT_OK;
2010 }
2011
2012
2013 static nxt_int_t
nxt_conf_vldt_python_path_element(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)2014 nxt_conf_vldt_python_path_element(nxt_conf_validation_t *vldt,
2015 nxt_conf_value_t *value)
2016 {
2017 if (nxt_conf_type(value) != NXT_CONF_STRING) {
2018 return nxt_conf_vldt_error(vldt, "The \"path\" array must contain "
2019 "only string values.");
2020 }
2021
2022 return NXT_OK;
2023 }
2024
2025
2026 static nxt_int_t
nxt_conf_vldt_python_protocol(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2027 nxt_conf_vldt_python_protocol(nxt_conf_validation_t *vldt,
2028 nxt_conf_value_t *value, void *data)
2029 {
2030 nxt_str_t proto;
2031
2032 static const nxt_str_t wsgi = nxt_string("wsgi");
2033 static const nxt_str_t asgi = nxt_string("asgi");
2034
2035 nxt_conf_get_string(value, &proto);
2036
2037 if (nxt_strstr_eq(&proto, &wsgi) || nxt_strstr_eq(&proto, &asgi)) {
2038 return NXT_OK;
2039 }
2040
2041 return nxt_conf_vldt_error(vldt, "The \"protocol\" can either be "
2042 "\"wsgi\" or \"asgi\".");
2043 }
2044
2045
2046 static nxt_int_t
nxt_conf_vldt_python_prefix(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2047 nxt_conf_vldt_python_prefix(nxt_conf_validation_t *vldt,
2048 nxt_conf_value_t *value, void *data)
2049 {
2050 nxt_str_t prefix;
2051
2052 if (nxt_conf_type(value) != NXT_CONF_STRING) {
2053 return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string "
2054 "beginning with \"/\".");
2055 }
2056
2057 nxt_conf_get_string(value, &prefix);
2058
2059 if (!nxt_strchr_start(&prefix, '/')) {
2060 return nxt_conf_vldt_error(vldt, "The \"prefix\" must be a string "
2061 "beginning with \"/\".");
2062 }
2063
2064 return NXT_OK;
2065 }
2066
2067
2068 static nxt_int_t
nxt_conf_vldt_threads(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2069 nxt_conf_vldt_threads(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
2070 void *data)
2071 {
2072 int64_t threads;
2073
2074 threads = nxt_conf_get_number(value);
2075
2076 if (threads < 1) {
2077 return nxt_conf_vldt_error(vldt, "The \"threads\" number must be "
2078 "equal to or greater than 1.");
2079 }
2080
2081 if (threads > NXT_INT32_T_MAX) {
2082 return nxt_conf_vldt_error(vldt, "The \"threads\" number must "
2083 "not exceed %d.", NXT_INT32_T_MAX);
2084 }
2085
2086 return NXT_OK;
2087 }
2088
2089
2090 static nxt_int_t
nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2091 nxt_conf_vldt_thread_stack_size(nxt_conf_validation_t *vldt,
2092 nxt_conf_value_t *value, void *data)
2093 {
2094 int64_t size, min_size;
2095
2096 size = nxt_conf_get_number(value);
2097 min_size = sysconf(_SC_THREAD_STACK_MIN);
2098
2099 if (size < min_size) {
2100 return nxt_conf_vldt_error(vldt, "The \"thread_stack_size\" number "
2101 "must be equal to or greater than %d.",
2102 min_size);
2103 }
2104
2105 if ((size % nxt_pagesize) != 0) {
2106 return nxt_conf_vldt_error(vldt, "The \"thread_stack_size\" number "
2107 "must be a multiple of the system page size (%d).",
2108 nxt_pagesize);
2109 }
2110
2111 return NXT_OK;
2112 }
2113
2114
2115 static nxt_int_t
nxt_conf_vldt_routes(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2116 nxt_conf_vldt_routes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
2117 void *data)
2118 {
2119 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
2120 return nxt_conf_vldt_array_iterator(vldt, value,
2121 &nxt_conf_vldt_route);
2122 }
2123
2124 /* NXT_CONF_OBJECT */
2125
2126 return nxt_conf_vldt_object_iterator(vldt, value,
2127 &nxt_conf_vldt_routes_member);
2128 }
2129
2130
2131 static nxt_int_t
nxt_conf_vldt_routes_member(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)2132 nxt_conf_vldt_routes_member(nxt_conf_validation_t *vldt, nxt_str_t *name,
2133 nxt_conf_value_t *value)
2134 {
2135 nxt_int_t ret;
2136
2137 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_ARRAY);
2138
2139 if (ret != NXT_OK) {
2140 return ret;
2141 }
2142
2143 return nxt_conf_vldt_array_iterator(vldt, value, &nxt_conf_vldt_route);
2144 }
2145
2146
2147 static nxt_int_t
nxt_conf_vldt_route(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)2148 nxt_conf_vldt_route(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
2149 {
2150 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
2151 return nxt_conf_vldt_error(vldt, "The \"routes\" array must contain "
2152 "only object values.");
2153 }
2154
2155 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_route_members);
2156 }
2157
2158
2159 static nxt_int_t
nxt_conf_vldt_match_patterns(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2160 nxt_conf_vldt_match_patterns(nxt_conf_validation_t *vldt,
2161 nxt_conf_value_t *value, void *data)
2162 {
2163 nxt_int_t ret;
2164
2165 vldt->ctx = data;
2166
2167 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
2168 ret = nxt_conf_vldt_array_iterator(vldt, value,
2169 &nxt_conf_vldt_match_pattern);
2170
2171 } else {
2172 /* NXT_CONF_STRING */
2173 ret = nxt_conf_vldt_match_pattern(vldt, value);
2174 }
2175
2176 vldt->ctx = NULL;
2177
2178 return ret;
2179 }
2180
2181
2182 static nxt_int_t
nxt_conf_vldt_match_pattern(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)2183 nxt_conf_vldt_match_pattern(nxt_conf_validation_t *vldt,
2184 nxt_conf_value_t *value)
2185 {
2186 nxt_str_t pattern;
2187 nxt_uint_t i, first, last;
2188 #if (NXT_HAVE_REGEX)
2189 nxt_regex_t *re;
2190 nxt_regex_err_t err;
2191 #endif
2192
2193 if (nxt_conf_type(value) != NXT_CONF_STRING) {
2194 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" "
2195 "must be strings.", vldt->ctx);
2196 }
2197
2198 nxt_conf_get_string(value, &pattern);
2199
2200 if (pattern.length == 0) {
2201 return NXT_OK;
2202 }
2203
2204 first = (pattern.start[0] == '!');
2205
2206 if (first < pattern.length && pattern.start[first] == '~') {
2207 #if (NXT_HAVE_REGEX)
2208 pattern.start += first + 1;
2209 pattern.length -= first + 1;
2210
2211 re = nxt_regex_compile(vldt->pool, &pattern, &err);
2212 if (nxt_slow_path(re == NULL)) {
2213 if (err.offset < pattern.length) {
2214 return nxt_conf_vldt_error(vldt, "Invalid regular expression: "
2215 "%s at offset %d",
2216 err.msg, err.offset);
2217 }
2218
2219 return nxt_conf_vldt_error(vldt, "Invalid regular expression: %s",
2220 err.msg);
2221 }
2222
2223 return NXT_OK;
2224 #else
2225 return nxt_conf_vldt_error(vldt, "Unit is built without support of "
2226 "regular expressions: \"--no-regex\" "
2227 "./configure option was set.");
2228 #endif
2229 }
2230
2231 last = pattern.length - 1;
2232
2233 for (i = first; i < last; i++) {
2234 if (pattern.start[i] == '*' && pattern.start[i + 1] == '*') {
2235 return nxt_conf_vldt_error(vldt, "The \"match\" pattern must "
2236 "not contain double \"*\" markers.");
2237 }
2238 }
2239
2240 return NXT_OK;
2241 }
2242
2243
nxt_conf_vldt_match_encoded_patterns_sets(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2244 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_sets(
2245 nxt_conf_validation_t *vldt, nxt_conf_value_t *value, void *data)
2246 {
2247 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
2248 return nxt_conf_vldt_array_iterator(vldt, value,
2249 &nxt_conf_vldt_match_encoded_patterns_set);
2250 }
2251
2252 /* NXT_CONF_OBJECT */
2253
2254 return nxt_conf_vldt_match_encoded_patterns_set(vldt, value);
2255 }
2256
2257
nxt_conf_vldt_match_encoded_patterns_set(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)2258 static nxt_int_t nxt_conf_vldt_match_encoded_patterns_set(
2259 nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
2260 {
2261 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
2262 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
2263 "\"arguments\" must be an object.");
2264 }
2265
2266 return nxt_conf_vldt_object_iterator(vldt, value,
2267 &nxt_conf_vldt_match_encoded_patterns_set_member);
2268 }
2269
2270
2271 static nxt_int_t
nxt_conf_vldt_match_encoded_patterns_set_member(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)2272 nxt_conf_vldt_match_encoded_patterns_set_member(nxt_conf_validation_t *vldt,
2273 nxt_str_t *name, nxt_conf_value_t *value)
2274 {
2275 u_char *p, *end;
2276
2277 if (nxt_slow_path(name->length == 0)) {
2278 return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must "
2279 "not contain empty member names.");
2280 }
2281
2282 p = nxt_mp_nget(vldt->pool, name->length);
2283 if (nxt_slow_path(p == NULL)) {
2284 return NXT_ERROR;
2285 }
2286
2287 end = nxt_decode_uri(p, name->start, name->length);
2288 if (nxt_slow_path(end == NULL)) {
2289 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
2290 "\"arguments\" is encoded but is invalid.");
2291 }
2292
2293 return nxt_conf_vldt_match_encoded_patterns(vldt, value,
2294 (void *) "arguments");
2295 }
2296
2297
2298 static nxt_int_t
nxt_conf_vldt_match_encoded_patterns(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2299 nxt_conf_vldt_match_encoded_patterns(nxt_conf_validation_t *vldt,
2300 nxt_conf_value_t *value, void *data)
2301 {
2302 nxt_int_t ret;
2303
2304 vldt->ctx = data;
2305
2306 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
2307 ret = nxt_conf_vldt_array_iterator(vldt, value,
2308 &nxt_conf_vldt_match_encoded_pattern);
2309
2310 } else {
2311 /* NXT_CONF_STRING */
2312 ret = nxt_conf_vldt_match_encoded_pattern(vldt, value);
2313 }
2314
2315 vldt->ctx = NULL;
2316
2317 return ret;
2318 }
2319
2320
2321 static nxt_int_t
nxt_conf_vldt_match_encoded_pattern(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)2322 nxt_conf_vldt_match_encoded_pattern(nxt_conf_validation_t *vldt,
2323 nxt_conf_value_t *value)
2324 {
2325 u_char *p, *end;
2326 nxt_int_t ret;
2327 nxt_str_t pattern;
2328
2329 if (nxt_conf_type(value) != NXT_CONF_STRING) {
2330 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" "
2331 "must be a string.", vldt->ctx);
2332 }
2333
2334 ret = nxt_conf_vldt_match_pattern(vldt, value);
2335 if (nxt_slow_path(ret != NXT_OK)) {
2336 return ret;
2337 }
2338
2339 nxt_conf_get_string(value, &pattern);
2340
2341 p = nxt_mp_nget(vldt->pool, pattern.length);
2342 if (nxt_slow_path(p == NULL)) {
2343 return NXT_ERROR;
2344 }
2345
2346 end = nxt_decode_uri(p, pattern.start, pattern.length);
2347 if (nxt_slow_path(end == NULL)) {
2348 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for \"%s\" "
2349 "is encoded but is invalid.", vldt->ctx);
2350 }
2351
2352 return NXT_OK;
2353 }
2354
2355
2356 static nxt_int_t
nxt_conf_vldt_match_addrs(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2357 nxt_conf_vldt_match_addrs(nxt_conf_validation_t *vldt,
2358 nxt_conf_value_t *value, void *data)
2359 {
2360 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
2361 return nxt_conf_vldt_array_iterator(vldt, value,
2362 &nxt_conf_vldt_match_addr);
2363 }
2364
2365 return nxt_conf_vldt_match_addr(vldt, value);
2366 }
2367
2368
2369 static nxt_int_t
nxt_conf_vldt_match_addr(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)2370 nxt_conf_vldt_match_addr(nxt_conf_validation_t *vldt,
2371 nxt_conf_value_t *value)
2372 {
2373 nxt_http_route_addr_pattern_t pattern;
2374
2375 switch (nxt_http_route_addr_pattern_parse(vldt->pool, &pattern, value)) {
2376
2377 case NXT_OK:
2378 return NXT_OK;
2379
2380 case NXT_ADDR_PATTERN_PORT_ERROR:
2381 return nxt_conf_vldt_error(vldt, "The \"address\" port an invalid "
2382 "port.");
2383
2384 case NXT_ADDR_PATTERN_CV_TYPE_ERROR:
2385 return nxt_conf_vldt_error(vldt, "The \"match\" pattern for "
2386 "\"address\" must be a string.");
2387
2388 case NXT_ADDR_PATTERN_LENGTH_ERROR:
2389 return nxt_conf_vldt_error(vldt, "The \"address\" is too short.");
2390
2391 case NXT_ADDR_PATTERN_FORMAT_ERROR:
2392 return nxt_conf_vldt_error(vldt, "The \"address\" format is invalid.");
2393
2394 case NXT_ADDR_PATTERN_RANGE_OVERLAP_ERROR:
2395 return nxt_conf_vldt_error(vldt, "The \"address\" range is "
2396 "overlapping.");
2397
2398 case NXT_ADDR_PATTERN_CIDR_ERROR:
2399 return nxt_conf_vldt_error(vldt, "The \"address\" has an invalid CIDR "
2400 "prefix.");
2401
2402 case NXT_ADDR_PATTERN_NO_IPv6_ERROR:
2403 return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
2404 "IPv6 with your configuration.");
2405
2406 case NXT_ADDR_PATTERN_NO_UNIX_ERROR:
2407 return nxt_conf_vldt_error(vldt, "The \"address\" does not support "
2408 "UNIX domain sockets with your "
2409 "configuration.");
2410
2411 default:
2412 return nxt_conf_vldt_error(vldt, "The \"address\" has an unknown "
2413 "format.");
2414 }
2415 }
2416
2417
2418 static nxt_int_t
nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2419 nxt_conf_vldt_match_scheme_pattern(nxt_conf_validation_t *vldt,
2420 nxt_conf_value_t *value, void *data)
2421 {
2422 nxt_str_t scheme;
2423
2424 static const nxt_str_t http = nxt_string("http");
2425 static const nxt_str_t https = nxt_string("https");
2426
2427 nxt_conf_get_string(value, &scheme);
2428
2429 if (nxt_strcasestr_eq(&scheme, &http)
2430 || nxt_strcasestr_eq(&scheme, &https))
2431 {
2432 return NXT_OK;
2433 }
2434
2435 return nxt_conf_vldt_error(vldt, "The \"scheme\" can either be "
2436 "\"http\" or \"https\".");
2437 }
2438
2439
2440 static nxt_int_t
nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2441 nxt_conf_vldt_match_patterns_sets(nxt_conf_validation_t *vldt,
2442 nxt_conf_value_t *value, void *data)
2443 {
2444 nxt_int_t ret;
2445
2446 vldt->ctx = data;
2447
2448 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
2449 ret = nxt_conf_vldt_array_iterator(vldt, value,
2450 &nxt_conf_vldt_match_patterns_set);
2451
2452 } else {
2453 /* NXT_CONF_OBJECT */
2454 ret = nxt_conf_vldt_match_patterns_set(vldt, value);
2455 }
2456
2457 vldt->ctx = NULL;
2458
2459 return ret;
2460 }
2461
2462
2463 static nxt_int_t
nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)2464 nxt_conf_vldt_match_patterns_set(nxt_conf_validation_t *vldt,
2465 nxt_conf_value_t *value)
2466 {
2467 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
2468 return nxt_conf_vldt_error(vldt, "The \"match\" patterns for "
2469 "\"%s\" must be objects.", vldt->ctx);
2470 }
2471
2472 return nxt_conf_vldt_object_iterator(vldt, value,
2473 &nxt_conf_vldt_match_patterns_set_member);
2474 }
2475
2476
2477 static nxt_int_t
nxt_conf_vldt_match_patterns_set_member(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)2478 nxt_conf_vldt_match_patterns_set_member(nxt_conf_validation_t *vldt,
2479 nxt_str_t *name, nxt_conf_value_t *value)
2480 {
2481 if (name->length == 0) {
2482 return nxt_conf_vldt_error(vldt, "The \"match\" pattern objects must "
2483 "not contain empty member names.");
2484 }
2485
2486 return nxt_conf_vldt_match_patterns(vldt, value, vldt->ctx);
2487 }
2488
2489
2490 #if (NXT_TLS)
2491
2492 static nxt_int_t
nxt_conf_vldt_certificate(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2493 nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
2494 void *data)
2495 {
2496 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
2497 if (nxt_conf_array_elements_count(value) == 0) {
2498 return nxt_conf_vldt_error(vldt, "The \"certificate\" array "
2499 "must contain at least one element.");
2500 }
2501
2502 return nxt_conf_vldt_array_iterator(vldt, value,
2503 &nxt_conf_vldt_certificate_element);
2504 }
2505
2506 /* NXT_CONF_STRING */
2507
2508 return nxt_conf_vldt_certificate_element(vldt, value);
2509 }
2510
2511
2512 static nxt_int_t
nxt_conf_vldt_certificate_element(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)2513 nxt_conf_vldt_certificate_element(nxt_conf_validation_t *vldt,
2514 nxt_conf_value_t *value)
2515 {
2516 nxt_str_t name;
2517 nxt_conf_value_t *cert;
2518
2519 if (nxt_conf_type(value) != NXT_CONF_STRING) {
2520 return nxt_conf_vldt_error(vldt, "The \"certificate\" array must "
2521 "contain only string values.");
2522 }
2523
2524 nxt_conf_get_string(value, &name);
2525
2526 cert = nxt_cert_info_get(&name);
2527
2528 if (cert == NULL) {
2529 return nxt_conf_vldt_error(vldt, "Certificate \"%V\" is not found.",
2530 &name);
2531 }
2532
2533 return NXT_OK;
2534 }
2535
2536
2537 #if (NXT_HAVE_OPENSSL_CONF_CMD)
2538
2539 static nxt_int_t
nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2540 nxt_conf_vldt_object_conf_commands(nxt_conf_validation_t *vldt,
2541 nxt_conf_value_t *value, void *data)
2542 {
2543 uint32_t index;
2544 nxt_int_t ret;
2545 nxt_str_t name;
2546 nxt_conf_value_t *member;
2547
2548 index = 0;
2549
2550 for ( ;; ) {
2551 member = nxt_conf_next_object_member(value, &name, &index);
2552
2553 if (member == NULL) {
2554 break;
2555 }
2556
2557 ret = nxt_conf_vldt_type(vldt, &name, member, NXT_CONF_VLDT_STRING);
2558 if (ret != NXT_OK) {
2559 return ret;
2560 }
2561 }
2562
2563 return NXT_OK;
2564 }
2565
2566 #endif
2567
2568 #endif
2569
2570
2571 static nxt_int_t
nxt_conf_vldt_response_header(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)2572 nxt_conf_vldt_response_header(nxt_conf_validation_t *vldt, nxt_str_t *name,
2573 nxt_conf_value_t *value)
2574 {
2575 nxt_uint_t type;
2576
2577 static nxt_str_t content_length = nxt_string("Content-Length");
2578
2579 if (name->length == 0) {
2580 return nxt_conf_vldt_error(vldt, "The response header name "
2581 "must not be empty.");
2582 }
2583
2584 if (nxt_strstr_eq(name, &content_length)) {
2585 return nxt_conf_vldt_error(vldt, "The \"Content-Length\" response "
2586 "header value is not supported");
2587 }
2588
2589 type = nxt_conf_type(value);
2590
2591 if (type == NXT_CONF_STRING || type == NXT_CONF_NULL) {
2592 return NXT_OK;
2593 }
2594
2595 return nxt_conf_vldt_error(vldt, "The \"%V\" response header value "
2596 "must either be a string or a null", name);
2597 }
2598
2599
2600 static nxt_int_t
nxt_conf_vldt_app_name(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2601 nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
2602 void *data)
2603 {
2604 nxt_str_t name;
2605 nxt_conf_value_t *apps, *app;
2606
2607 static nxt_str_t apps_str = nxt_string("applications");
2608
2609 nxt_conf_get_string(value, &name);
2610
2611 apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL);
2612
2613 if (nxt_slow_path(apps == NULL)) {
2614 goto error;
2615 }
2616
2617 app = nxt_conf_get_object_member(apps, &name, NULL);
2618
2619 if (nxt_slow_path(app == NULL)) {
2620 goto error;
2621 }
2622
2623 return NXT_OK;
2624
2625 error:
2626
2627 return nxt_conf_vldt_error(vldt, "Listening socket is assigned for "
2628 "a non existing application \"%V\".",
2629 &name);
2630 }
2631
2632
2633 static nxt_int_t
nxt_conf_vldt_forwarded(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2634 nxt_conf_vldt_forwarded(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
2635 void *data)
2636 {
2637 nxt_conf_value_t *client_ip, *protocol;
2638
2639 static nxt_str_t client_ip_str = nxt_string("client_ip");
2640 static nxt_str_t protocol_str = nxt_string("protocol");
2641
2642 client_ip = nxt_conf_get_object_member(value, &client_ip_str, NULL);
2643 protocol = nxt_conf_get_object_member(value, &protocol_str, NULL);
2644
2645 if (client_ip == NULL && protocol == NULL) {
2646 return nxt_conf_vldt_error(vldt, "The \"forwarded\" object must have "
2647 "either \"client_ip\" or \"protocol\" "
2648 "option set.");
2649 }
2650
2651 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_forwarded_members);
2652 }
2653
2654
2655 static nxt_int_t
nxt_conf_vldt_app(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)2656 nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name,
2657 nxt_conf_value_t *value)
2658 {
2659 nxt_int_t ret;
2660 nxt_str_t type;
2661 nxt_thread_t *thread;
2662 nxt_conf_value_t *type_value;
2663 nxt_app_lang_module_t *lang;
2664
2665 static nxt_str_t type_str = nxt_string("type");
2666
2667 static struct {
2668 nxt_conf_vldt_handler_t validator;
2669 nxt_conf_vldt_object_t *members;
2670
2671 } types[] = {
2672 { nxt_conf_vldt_object, nxt_conf_vldt_external_members },
2673 { nxt_conf_vldt_python, NULL },
2674 { nxt_conf_vldt_php, NULL },
2675 { nxt_conf_vldt_object, nxt_conf_vldt_perl_members },
2676 { nxt_conf_vldt_object, nxt_conf_vldt_ruby_members },
2677 { nxt_conf_vldt_object, nxt_conf_vldt_java_members },
2678 { nxt_conf_vldt_object, nxt_conf_vldt_wasm_members },
2679 { nxt_conf_vldt_object, nxt_conf_vldt_wasm_wc_members },
2680 };
2681
2682 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
2683
2684 if (ret != NXT_OK) {
2685 return ret;
2686 }
2687
2688 type_value = nxt_conf_get_object_member(value, &type_str, NULL);
2689
2690 if (type_value == NULL) {
2691 return nxt_conf_vldt_error(vldt,
2692 "Application must have the \"type\" property set.");
2693 }
2694
2695 ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_VLDT_STRING);
2696
2697 if (ret != NXT_OK) {
2698 return ret;
2699 }
2700
2701 nxt_conf_get_string(type_value, &type);
2702
2703 thread = nxt_thread();
2704
2705 lang = nxt_app_lang_module(thread->runtime, &type);
2706 if (lang == NULL) {
2707 return nxt_conf_vldt_error(vldt,
2708 "The module to run \"%V\" is not found "
2709 "among the available application modules.",
2710 &type);
2711 }
2712
2713 return types[lang->type].validator(vldt, value, types[lang->type].members);
2714 }
2715
2716
2717 static nxt_int_t
nxt_conf_vldt_object(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2718 nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
2719 void *data)
2720 {
2721 uint32_t index;
2722 nxt_int_t ret;
2723 nxt_str_t name, var;
2724 nxt_conf_value_t *member;
2725 nxt_conf_vldt_object_t *vals;
2726
2727 vals = data;
2728
2729 for ( ;; ) {
2730 if (vals->name.length == 0) {
2731
2732 if (vals->u.members != NULL) {
2733 vals = vals->u.members;
2734 continue;
2735 }
2736
2737 break;
2738 }
2739
2740 if (vals->flags & NXT_CONF_VLDT_REQUIRED) {
2741 member = nxt_conf_get_object_member(value, &vals->name, NULL);
2742
2743 if (member == NULL) {
2744 return nxt_conf_vldt_error(vldt, "Required parameter \"%V\" "
2745 "is missing.", &vals->name);
2746 }
2747 }
2748
2749 vals++;
2750 }
2751
2752 index = 0;
2753
2754 for ( ;; ) {
2755 member = nxt_conf_next_object_member(value, &name, &index);
2756
2757 if (member == NULL) {
2758 return NXT_OK;
2759 }
2760
2761 vals = data;
2762
2763 for ( ;; ) {
2764 if (vals->name.length == 0) {
2765
2766 if (vals->u.members != NULL) {
2767 vals = vals->u.members;
2768 continue;
2769 }
2770
2771 return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".",
2772 &name);
2773 }
2774
2775 if (!nxt_strstr_eq(&vals->name, &name)) {
2776 vals++;
2777 continue;
2778 }
2779
2780 if (vals->flags & NXT_CONF_VLDT_TSTR
2781 && nxt_conf_type(member) == NXT_CONF_STRING)
2782 {
2783 nxt_conf_get_string(member, &var);
2784
2785 if (nxt_is_tstr(&var)) {
2786 ret = nxt_conf_vldt_var(vldt, &name, &var);
2787 if (ret != NXT_OK) {
2788 return ret;
2789 }
2790
2791 break;
2792 }
2793 }
2794
2795 ret = nxt_conf_vldt_type(vldt, &name, member, vals->type);
2796 if (ret != NXT_OK) {
2797 return ret;
2798 }
2799
2800 if (vals->validator != NULL) {
2801 ret = vals->validator(vldt, member, vals->u.members);
2802
2803 if (ret != NXT_OK) {
2804 return ret;
2805 }
2806 }
2807
2808 break;
2809 }
2810 }
2811 }
2812
2813
2814 typedef struct {
2815 int64_t spare;
2816 int64_t max;
2817 int64_t idle_timeout;
2818 } nxt_conf_vldt_processes_conf_t;
2819
2820
2821 static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = {
2822 {
2823 nxt_string("spare"),
2824 NXT_CONF_MAP_INT64,
2825 offsetof(nxt_conf_vldt_processes_conf_t, spare),
2826 },
2827
2828 {
2829 nxt_string("max"),
2830 NXT_CONF_MAP_INT64,
2831 offsetof(nxt_conf_vldt_processes_conf_t, max),
2832 },
2833
2834 {
2835 nxt_string("idle_timeout"),
2836 NXT_CONF_MAP_INT64,
2837 offsetof(nxt_conf_vldt_processes_conf_t, idle_timeout),
2838 },
2839 };
2840
2841
2842 static nxt_int_t
nxt_conf_vldt_processes(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2843 nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
2844 void *data)
2845 {
2846 int64_t int_value;
2847 nxt_int_t ret;
2848 nxt_conf_vldt_processes_conf_t proc;
2849
2850 if (nxt_conf_type(value) == NXT_CONF_INTEGER) {
2851 int_value = nxt_conf_get_number(value);
2852
2853 if (int_value < 1) {
2854 return nxt_conf_vldt_error(vldt, "The \"processes\" number must be "
2855 "equal to or greater than 1.");
2856 }
2857
2858 if (int_value > NXT_INT32_T_MAX) {
2859 return nxt_conf_vldt_error(vldt, "The \"processes\" number must "
2860 "not exceed %d.", NXT_INT32_T_MAX);
2861 }
2862
2863 return NXT_OK;
2864 }
2865
2866 ret = nxt_conf_vldt_object(vldt, value, data);
2867 if (ret != NXT_OK) {
2868 return ret;
2869 }
2870
2871 proc.spare = 0;
2872 proc.max = 1;
2873 proc.idle_timeout = 15;
2874
2875 ret = nxt_conf_map_object(vldt->pool, value,
2876 nxt_conf_vldt_processes_conf_map,
2877 nxt_nitems(nxt_conf_vldt_processes_conf_map),
2878 &proc);
2879 if (ret != NXT_OK) {
2880 return ret;
2881 }
2882
2883 if (proc.spare < 0) {
2884 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be "
2885 "negative.");
2886 }
2887
2888 if (proc.spare > NXT_INT32_T_MAX) {
2889 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not "
2890 "exceed %d.", NXT_INT32_T_MAX);
2891 }
2892
2893 if (proc.max < 1) {
2894 return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal "
2895 "to or greater than 1.");
2896 }
2897
2898 if (proc.max > NXT_INT32_T_MAX) {
2899 return nxt_conf_vldt_error(vldt, "The \"max\" number must not "
2900 "exceed %d.", NXT_INT32_T_MAX);
2901 }
2902
2903 if (proc.max < proc.spare) {
2904 return nxt_conf_vldt_error(vldt, "The \"spare\" number must be "
2905 "less than or equal to \"max\".");
2906 }
2907
2908 if (proc.idle_timeout < 0) {
2909 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
2910 "be negative.");
2911 }
2912
2913 if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) {
2914 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
2915 "exceed %d.", NXT_INT32_T_MAX / 1000);
2916 }
2917
2918 return NXT_OK;
2919 }
2920
2921
2922 static nxt_int_t
nxt_conf_vldt_object_iterator(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2923 nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
2924 nxt_conf_value_t *value, void *data)
2925 {
2926 uint32_t index;
2927 nxt_int_t ret;
2928 nxt_str_t name;
2929 nxt_conf_value_t *member;
2930 nxt_conf_vldt_member_t validator;
2931
2932 validator = (nxt_conf_vldt_member_t) data;
2933 index = 0;
2934
2935 for ( ;; ) {
2936 member = nxt_conf_next_object_member(value, &name, &index);
2937 if (member == NULL) {
2938 return NXT_OK;
2939 }
2940
2941 ret = validator(vldt, &name, member);
2942 if (ret != NXT_OK) {
2943 return ret;
2944 }
2945 }
2946 }
2947
2948
2949 static nxt_int_t
nxt_conf_vldt_array_iterator(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)2950 nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt,
2951 nxt_conf_value_t *value, void *data)
2952 {
2953 uint32_t index;
2954 nxt_int_t ret;
2955 nxt_conf_value_t *element;
2956 nxt_conf_vldt_element_t validator;
2957
2958 validator = (nxt_conf_vldt_element_t) data;
2959
2960 for (index = 0; /* void */ ; index++) {
2961 element = nxt_conf_get_array_element(value, index);
2962
2963 if (element == NULL) {
2964 return NXT_OK;
2965 }
2966
2967 ret = validator(vldt, element);
2968
2969 if (ret != NXT_OK) {
2970 return ret;
2971 }
2972 }
2973 }
2974
2975
2976 static nxt_int_t
nxt_conf_vldt_environment(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)2977 nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name,
2978 nxt_conf_value_t *value)
2979 {
2980 nxt_str_t str;
2981
2982 if (name->length == 0) {
2983 return nxt_conf_vldt_error(vldt,
2984 "The environment name must not be empty.");
2985 }
2986
2987 if (memchr(name->start, '\0', name->length) != NULL) {
2988 return nxt_conf_vldt_error(vldt, "The environment name must not "
2989 "contain null character.");
2990 }
2991
2992 if (memchr(name->start, '=', name->length) != NULL) {
2993 return nxt_conf_vldt_error(vldt, "The environment name must not "
2994 "contain '=' character.");
2995 }
2996
2997 if (nxt_conf_type(value) != NXT_CONF_STRING) {
2998 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must be "
2999 "a string.", name);
3000 }
3001
3002 nxt_conf_get_string(value, &str);
3003
3004 if (memchr(str.start, '\0', str.length) != NULL) {
3005 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must "
3006 "not contain null character.", name);
3007 }
3008
3009 return NXT_OK;
3010 }
3011
3012
3013 static nxt_int_t
nxt_conf_vldt_targets_exclusive(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3014 nxt_conf_vldt_targets_exclusive(nxt_conf_validation_t *vldt,
3015 nxt_conf_value_t *value, void *data)
3016 {
3017 return nxt_conf_vldt_error(vldt, "The \"%s\" option is mutually exclusive "
3018 "with the \"targets\" object.", data);
3019 }
3020
3021
3022 static nxt_int_t
nxt_conf_vldt_targets(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3023 nxt_conf_vldt_targets(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
3024 void *data)
3025 {
3026 nxt_int_t ret;
3027 nxt_uint_t n;
3028
3029 n = nxt_conf_object_members_count(value);
3030
3031 if (n > 254) {
3032 return nxt_conf_vldt_error(vldt, "The \"targets\" object must not "
3033 "contain more than 254 members.");
3034 }
3035
3036 vldt->ctx = data;
3037
3038 ret = nxt_conf_vldt_object_iterator(vldt, value, &nxt_conf_vldt_target);
3039
3040 vldt->ctx = NULL;
3041
3042 return ret;
3043 }
3044
3045
3046 static nxt_int_t
nxt_conf_vldt_target(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)3047 nxt_conf_vldt_target(nxt_conf_validation_t *vldt, nxt_str_t *name,
3048 nxt_conf_value_t *value)
3049 {
3050 if (name->length == 0) {
3051 return nxt_conf_vldt_error(vldt,
3052 "The target name must not be empty.");
3053 }
3054
3055 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
3056 return nxt_conf_vldt_error(vldt, "The \"%V\" target must be "
3057 "an object.", name);
3058 }
3059
3060 return nxt_conf_vldt_object(vldt, value, vldt->ctx);
3061 }
3062
3063
3064 #if (NXT_HAVE_CGROUP)
3065
3066 static nxt_int_t
nxt_conf_vldt_cgroup_path(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3067 nxt_conf_vldt_cgroup_path(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
3068 void *data)
3069 {
3070 char path[NXT_MAX_PATH_LEN];
3071 nxt_str_t cgpath;
3072
3073 nxt_conf_get_string(value, &cgpath);
3074 if (cgpath.length >= NXT_MAX_PATH_LEN - strlen(NXT_CGROUP_ROOT) - 1) {
3075 return nxt_conf_vldt_error(vldt, "The cgroup path \"%V\" is too long.",
3076 &cgpath);
3077 }
3078
3079 sprintf(path, "/%*s/", (int) cgpath.length, cgpath.start);
3080
3081 if (cgpath.length == 0 || strstr(path, "/../") != NULL) {
3082 return nxt_conf_vldt_error(vldt,
3083 "The cgroup path \"%V\" is invalid.",
3084 &cgpath);
3085 }
3086
3087 return NXT_OK;
3088 }
3089
3090 #endif
3091
3092
3093 static nxt_int_t
nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3094 nxt_conf_vldt_clone_namespaces(nxt_conf_validation_t *vldt,
3095 nxt_conf_value_t *value, void *data)
3096 {
3097 return nxt_conf_vldt_object(vldt, value, data);
3098 }
3099
3100
3101 static nxt_int_t
nxt_conf_vldt_isolation(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3102 nxt_conf_vldt_isolation(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
3103 void *data)
3104 {
3105 return nxt_conf_vldt_object(vldt, value, data);
3106 }
3107
3108
3109 #if (NXT_HAVE_CLONE_NEWUSER)
3110
3111 static nxt_int_t
nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)3112 nxt_conf_vldt_clone_uidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
3113 {
3114 nxt_int_t ret;
3115
3116 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
3117 return nxt_conf_vldt_error(vldt, "The \"uidmap\" array "
3118 "must contain only object values.");
3119 }
3120
3121 ret = nxt_conf_vldt_object(vldt, value,
3122 (void *) nxt_conf_vldt_app_procmap_members);
3123 if (nxt_slow_path(ret != NXT_OK)) {
3124 return ret;
3125 }
3126
3127 return NXT_OK;
3128 }
3129
3130
3131 static nxt_int_t
nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)3132 nxt_conf_vldt_clone_gidmap(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
3133 {
3134 nxt_int_t ret;
3135
3136 if (nxt_conf_type(value) != NXT_CONF_OBJECT) {
3137 return nxt_conf_vldt_error(vldt, "The \"gidmap\" array "
3138 "must contain only object values.");
3139 }
3140
3141 ret = nxt_conf_vldt_object(vldt, value,
3142 (void *) nxt_conf_vldt_app_procmap_members);
3143 if (nxt_slow_path(ret != NXT_OK)) {
3144 return ret;
3145 }
3146
3147 return NXT_OK;
3148 }
3149
3150 #endif
3151
3152
3153 static nxt_int_t
nxt_conf_vldt_argument(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)3154 nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
3155 {
3156 nxt_str_t str;
3157
3158 if (nxt_conf_type(value) != NXT_CONF_STRING) {
3159 return nxt_conf_vldt_error(vldt, "The \"arguments\" array "
3160 "must contain only string values.");
3161 }
3162
3163 nxt_conf_get_string(value, &str);
3164
3165 if (memchr(str.start, '\0', str.length) != NULL) {
3166 return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not "
3167 "contain strings with null character.");
3168 }
3169
3170 return NXT_OK;
3171 }
3172
3173
3174 static nxt_int_t
nxt_conf_vldt_php(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3175 nxt_conf_vldt_php(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
3176 void *data)
3177 {
3178 nxt_conf_value_t *targets;
3179
3180 static nxt_str_t targets_str = nxt_string("targets");
3181
3182 targets = nxt_conf_get_object_member(value, &targets_str, NULL);
3183
3184 if (targets != NULL) {
3185 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_php_members);
3186 }
3187
3188 return nxt_conf_vldt_object(vldt, value,
3189 nxt_conf_vldt_php_notargets_members);
3190 }
3191
3192
3193 static nxt_int_t
nxt_conf_vldt_php_option(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)3194 nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, nxt_str_t *name,
3195 nxt_conf_value_t *value)
3196 {
3197 if (name->length == 0) {
3198 return nxt_conf_vldt_error(vldt,
3199 "The PHP option name must not be empty.");
3200 }
3201
3202 if (nxt_conf_type(value) != NXT_CONF_STRING) {
3203 return nxt_conf_vldt_error(vldt, "The \"%V\" PHP option must be "
3204 "a string.", name);
3205 }
3206
3207 return NXT_OK;
3208 }
3209
3210
3211 static nxt_int_t
nxt_conf_vldt_java_classpath(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)3212 nxt_conf_vldt_java_classpath(nxt_conf_validation_t *vldt,
3213 nxt_conf_value_t *value)
3214 {
3215 nxt_str_t str;
3216
3217 if (nxt_conf_type(value) != NXT_CONF_STRING) {
3218 return nxt_conf_vldt_error(vldt, "The \"classpath\" array "
3219 "must contain only string values.");
3220 }
3221
3222 nxt_conf_get_string(value, &str);
3223
3224 if (memchr(str.start, '\0', str.length) != NULL) {
3225 return nxt_conf_vldt_error(vldt, "The \"classpath\" array must not "
3226 "contain strings with null character.");
3227 }
3228
3229 return NXT_OK;
3230 }
3231
3232
3233 static nxt_int_t
nxt_conf_vldt_java_option(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)3234 nxt_conf_vldt_java_option(nxt_conf_validation_t *vldt, nxt_conf_value_t *value)
3235 {
3236 nxt_str_t str;
3237
3238 if (nxt_conf_type(value) != NXT_CONF_STRING) {
3239 return nxt_conf_vldt_error(vldt, "The \"options\" array "
3240 "must contain only string values.");
3241 }
3242
3243 nxt_conf_get_string(value, &str);
3244
3245 if (memchr(str.start, '\0', str.length) != NULL) {
3246 return nxt_conf_vldt_error(vldt, "The \"options\" array must not "
3247 "contain strings with null character.");
3248 }
3249
3250 return NXT_OK;
3251 }
3252
3253
3254 static nxt_int_t
nxt_conf_vldt_upstream(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)3255 nxt_conf_vldt_upstream(nxt_conf_validation_t *vldt, nxt_str_t *name,
3256 nxt_conf_value_t *value)
3257 {
3258 nxt_int_t ret;
3259 nxt_conf_value_t *conf;
3260
3261 static nxt_str_t servers = nxt_string("servers");
3262
3263 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
3264
3265 if (ret != NXT_OK) {
3266 return ret;
3267 }
3268
3269 ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_upstream_members);
3270
3271 if (ret != NXT_OK) {
3272 return ret;
3273 }
3274
3275 conf = nxt_conf_get_object_member(value, &servers, NULL);
3276 if (conf == NULL) {
3277 return nxt_conf_vldt_error(vldt, "The \"%V\" upstream must contain "
3278 "\"servers\" object value.", name);
3279 }
3280
3281 return NXT_OK;
3282 }
3283
3284
3285 static nxt_int_t
nxt_conf_vldt_server(nxt_conf_validation_t * vldt,nxt_str_t * name,nxt_conf_value_t * value)3286 nxt_conf_vldt_server(nxt_conf_validation_t *vldt, nxt_str_t *name,
3287 nxt_conf_value_t *value)
3288 {
3289 nxt_int_t ret;
3290 nxt_str_t str;
3291 nxt_sockaddr_t *sa;
3292
3293 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT);
3294 if (ret != NXT_OK) {
3295 return ret;
3296 }
3297
3298 if (nxt_slow_path(nxt_str_dup(vldt->pool, &str, name) == NULL)) {
3299 return NXT_ERROR;
3300 }
3301
3302 sa = nxt_sockaddr_parse(vldt->pool, &str);
3303 if (sa == NULL) {
3304 return nxt_conf_vldt_error(vldt, "The \"%V\" is not valid "
3305 "server address.", name);
3306 }
3307
3308 return nxt_conf_vldt_object(vldt, value,
3309 nxt_conf_vldt_upstream_server_members);
3310 }
3311
3312
3313 static nxt_int_t
nxt_conf_vldt_server_weight(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3314 nxt_conf_vldt_server_weight(nxt_conf_validation_t *vldt,
3315 nxt_conf_value_t *value, void *data)
3316 {
3317 double num_value;
3318
3319 num_value = nxt_conf_get_number(value);
3320
3321 if (num_value < 0) {
3322 return nxt_conf_vldt_error(vldt, "The \"weight\" number must be "
3323 "positive.");
3324 }
3325
3326 if (num_value > 1000000) {
3327 return nxt_conf_vldt_error(vldt, "The \"weight\" number must "
3328 "not exceed 1,000,000");
3329 }
3330
3331 return NXT_OK;
3332 }
3333
3334
3335 #if (NXT_HAVE_NJS)
3336
3337 static nxt_int_t
nxt_conf_vldt_js_module(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3338 nxt_conf_vldt_js_module(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
3339 void *data)
3340 {
3341 if (nxt_conf_type(value) == NXT_CONF_ARRAY) {
3342 return nxt_conf_vldt_array_iterator(vldt, value,
3343 &nxt_conf_vldt_js_module_element);
3344 }
3345
3346 /* NXT_CONF_STRING */
3347
3348 return nxt_conf_vldt_js_module_element(vldt, value);
3349 }
3350
3351
3352 static nxt_int_t
nxt_conf_vldt_js_module_element(nxt_conf_validation_t * vldt,nxt_conf_value_t * value)3353 nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt,
3354 nxt_conf_value_t *value)
3355 {
3356 nxt_str_t name;
3357 nxt_conf_value_t *module;
3358
3359 if (nxt_conf_type(value) != NXT_CONF_STRING) {
3360 return nxt_conf_vldt_error(vldt, "The \"js_module\" array must "
3361 "contain only string values.");
3362 }
3363
3364 nxt_conf_get_string(value, &name);
3365
3366 module = nxt_script_info_get(&name);
3367 if (module == NULL) {
3368 return nxt_conf_vldt_error(vldt, "JS module \"%V\" is not found.",
3369 &name);
3370 }
3371
3372 return NXT_OK;
3373 }
3374
3375 #endif
3376
3377
3378 typedef struct {
3379 nxt_str_t path;
3380 nxt_str_t format;
3381 } nxt_conf_vldt_access_log_conf_t;
3382
3383
3384 static nxt_conf_map_t nxt_conf_vldt_access_log_map[] = {
3385 {
3386 nxt_string("path"),
3387 NXT_CONF_MAP_STR,
3388 offsetof(nxt_conf_vldt_access_log_conf_t, path),
3389 },
3390
3391 {
3392 nxt_string("format"),
3393 NXT_CONF_MAP_STR,
3394 offsetof(nxt_conf_vldt_access_log_conf_t, format),
3395 },
3396 };
3397
3398
3399 static nxt_int_t
nxt_conf_vldt_access_log(nxt_conf_validation_t * vldt,nxt_conf_value_t * value,void * data)3400 nxt_conf_vldt_access_log(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
3401 void *data)
3402 {
3403 nxt_int_t ret;
3404 nxt_conf_vldt_access_log_conf_t conf;
3405
3406 static nxt_str_t format_str = nxt_string("format");
3407
3408 if (nxt_conf_type(value) == NXT_CONF_STRING) {
3409 return NXT_OK;
3410 }
3411
3412 ret = nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_access_log_members);
3413 if (ret != NXT_OK) {
3414 return ret;
3415 }
3416
3417 nxt_memzero(&conf, sizeof(nxt_conf_vldt_access_log_conf_t));
3418
3419 ret = nxt_conf_map_object(vldt->pool, value,
3420 nxt_conf_vldt_access_log_map,
3421 nxt_nitems(nxt_conf_vldt_access_log_map),
3422 &conf);
3423 if (ret != NXT_OK) {
3424 return ret;
3425 }
3426
3427 if (conf.path.length == 0) {
3428 return nxt_conf_vldt_error(vldt,
3429 "The \"path\" string must not be empty.");
3430 }
3431
3432 if (nxt_is_tstr(&conf.format)) {
3433 return nxt_conf_vldt_var(vldt, &format_str, &conf.format);
3434 }
3435
3436 return NXT_OK;
3437 }
3438