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