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