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