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