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