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