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 12 13 typedef enum { 14 NXT_CONF_VLDT_NULL = 1 << NXT_CONF_NULL, 15 NXT_CONF_VLDT_BOOLEAN = 1 << NXT_CONF_BOOLEAN, 16 NXT_CONF_VLDT_INTEGER = 1 << NXT_CONF_INTEGER, 17 NXT_CONF_VLDT_NUMBER = 1 << NXT_CONF_NUMBER, 18 NXT_CONF_VLDT_STRING = 1 << NXT_CONF_STRING, 19 NXT_CONF_VLDT_ARRAY = 1 << NXT_CONF_ARRAY, 20 NXT_CONF_VLDT_OBJECT = 1 << NXT_CONF_OBJECT, 21 } nxt_conf_vldt_type_t; 22 23 24 typedef struct { 25 nxt_str_t name; 26 nxt_conf_vldt_type_t type; 27 nxt_int_t (*validator)(nxt_conf_validation_t *vldt, 28 nxt_conf_value_t *value, void *data); 29 void *data; 30 } nxt_conf_vldt_object_t; 31 32 33 #define NXT_CONF_VLDT_NEXT(f) { nxt_null_string, 0, NULL, (f) } 34 #define NXT_CONF_VLDT_END { nxt_null_string, 0, NULL, NULL } 35 36 37 typedef nxt_int_t (*nxt_conf_vldt_member_t)(nxt_conf_validation_t *vldt, 38 nxt_str_t *name, 39 nxt_conf_value_t *value); 40 typedef nxt_int_t (*nxt_conf_vldt_element_t)(nxt_conf_validation_t *vldt, 41 nxt_conf_value_t *value); 42 typedef nxt_int_t (*nxt_conf_vldt_system_t)(nxt_conf_validation_t *vldt, 43 char *name); 44 45 46 static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt, 47 nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type); 48 static nxt_int_t nxt_conf_vldt_error(nxt_conf_validation_t *vldt, 49 const char *fmt, ...); 50 51 static nxt_int_t nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, 52 nxt_str_t *name, nxt_conf_value_t *value); 53 #if (NXT_TLS) 54 static nxt_int_t nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, 55 nxt_conf_value_t *value, void *data); 56 #endif 57 static nxt_int_t nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, 58 nxt_conf_value_t *value, void *data); 59 static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt, 60 nxt_str_t *name, nxt_conf_value_t *value); 61 static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt, 62 nxt_conf_value_t *value, void *data); 63 static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, 64 nxt_conf_value_t *value, void *data); 65 static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, 66 nxt_conf_value_t *value, void *data); 67 static nxt_int_t nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, 68 nxt_conf_value_t *value, void *data); 69 static nxt_int_t nxt_conf_vldt_system(nxt_conf_validation_t *vldt, 70 nxt_conf_value_t *value, void *data); 71 static nxt_int_t nxt_conf_vldt_user(nxt_conf_validation_t *vldt, char *name); 72 static nxt_int_t nxt_conf_vldt_group(nxt_conf_validation_t *vldt, char *name); 73 static nxt_int_t nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, 74 nxt_str_t *name, nxt_conf_value_t *value); 75 static nxt_int_t nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, 76 nxt_conf_value_t *value); 77 static nxt_int_t nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, 78 nxt_str_t *name, nxt_conf_value_t *value); 79 80 81 static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[] = { 82 { nxt_string("header_read_timeout"), 83 NXT_CONF_VLDT_INTEGER, 84 NULL, 85 NULL }, 86 87 { nxt_string("body_read_timeout"), 88 NXT_CONF_VLDT_INTEGER, 89 NULL, 90 NULL }, 91 92 { nxt_string("send_timeout"), 93 NXT_CONF_VLDT_INTEGER, 94 NULL, 95 NULL }, 96 97 { nxt_string("idle_timeout"), 98 NXT_CONF_VLDT_INTEGER, 99 NULL, 100 NULL }, 101 102 { nxt_string("max_body_size"), 103 NXT_CONF_VLDT_INTEGER, 104 NULL, 105 NULL }, 106 107 NXT_CONF_VLDT_END 108 }; 109 110 111 static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = { 112 { nxt_string("http"), 113 NXT_CONF_VLDT_OBJECT, 114 &nxt_conf_vldt_object, 115 (void *) &nxt_conf_vldt_http_members }, 116 117 NXT_CONF_VLDT_END 118 }; 119 120 121 static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { 122 { nxt_string("settings"), 123 NXT_CONF_VLDT_OBJECT, 124 &nxt_conf_vldt_object, 125 (void *) &nxt_conf_vldt_setting_members }, 126 127 { nxt_string("listeners"), 128 NXT_CONF_VLDT_OBJECT, 129 &nxt_conf_vldt_object_iterator, 130 (void *) &nxt_conf_vldt_listener }, 131 132 { nxt_string("applications"), 133 NXT_CONF_VLDT_OBJECT, 134 &nxt_conf_vldt_object_iterator, 135 (void *) &nxt_conf_vldt_app }, 136 137 { nxt_string("access_log"), 138 NXT_CONF_VLDT_STRING, 139 NULL, 140 NULL }, 141 142 NXT_CONF_VLDT_END 143 }; 144 145 146 #if (NXT_TLS) 147 148 static nxt_conf_vldt_object_t nxt_conf_vldt_tls_members[] = { 149 { nxt_string("certificate"), 150 NXT_CONF_VLDT_STRING, 151 &nxt_conf_vldt_certificate, 152 NULL }, 153 154 NXT_CONF_VLDT_END 155 }; 156 157 #endif 158 159 160 static nxt_conf_vldt_object_t nxt_conf_vldt_listener_members[] = { 161 { nxt_string("application"), 162 NXT_CONF_VLDT_STRING, 163 &nxt_conf_vldt_app_name, 164 NULL }, 165 166 #if (NXT_TLS) 167 168 { nxt_string("tls"), 169 NXT_CONF_VLDT_OBJECT, 170 &nxt_conf_vldt_object, 171 (void *) &nxt_conf_vldt_tls_members }, 172 173 #endif 174 175 NXT_CONF_VLDT_END 176 }; 177 178 179 static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = { 180 { nxt_string("timeout"), 181 NXT_CONF_VLDT_INTEGER, 182 NULL, 183 NULL }, 184 185 { nxt_string("reschedule_timeout"), 186 NXT_CONF_VLDT_INTEGER, 187 NULL, 188 NULL }, 189 190 { nxt_string("requests"), 191 NXT_CONF_VLDT_INTEGER, 192 NULL, 193 NULL }, 194 195 NXT_CONF_VLDT_END 196 }; 197 198 199 static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = { 200 { nxt_string("spare"), 201 NXT_CONF_VLDT_INTEGER, 202 NULL, 203 NULL }, 204 205 { nxt_string("max"), 206 NXT_CONF_VLDT_INTEGER, 207 NULL, 208 NULL }, 209 210 { nxt_string("idle_timeout"), 211 NXT_CONF_VLDT_INTEGER, 212 NULL, 213 NULL }, 214 215 NXT_CONF_VLDT_END 216 }; 217 218 219 static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = { 220 { nxt_string("type"), 221 NXT_CONF_VLDT_STRING, 222 NULL, 223 NULL }, 224 225 { nxt_string("limits"), 226 NXT_CONF_VLDT_OBJECT, 227 &nxt_conf_vldt_object, 228 (void *) &nxt_conf_vldt_app_limits_members }, 229 230 { nxt_string("processes"), 231 NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT, 232 &nxt_conf_vldt_processes, 233 (void *) &nxt_conf_vldt_app_processes_members }, 234 235 { nxt_string("user"), 236 NXT_CONF_VLDT_STRING, 237 nxt_conf_vldt_system, 238 (void *) &nxt_conf_vldt_user }, 239 240 { nxt_string("group"), 241 NXT_CONF_VLDT_STRING, 242 nxt_conf_vldt_system, 243 (void *) &nxt_conf_vldt_group }, 244 245 { nxt_string("working_directory"), 246 NXT_CONF_VLDT_STRING, 247 NULL, 248 NULL }, 249 250 { nxt_string("environment"), 251 NXT_CONF_VLDT_OBJECT, 252 &nxt_conf_vldt_object_iterator, 253 (void *) &nxt_conf_vldt_environment }, 254 255 NXT_CONF_VLDT_END 256 }; 257 258 259 static nxt_conf_vldt_object_t nxt_conf_vldt_external_members[] = { 260 { nxt_string("executable"), 261 NXT_CONF_VLDT_STRING, 262 NULL, 263 NULL }, 264 265 { nxt_string("arguments"), 266 NXT_CONF_VLDT_ARRAY, 267 &nxt_conf_vldt_array_iterator, 268 (void *) &nxt_conf_vldt_argument }, 269 270 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 271 }; 272 273 274 static nxt_conf_vldt_object_t nxt_conf_vldt_python_members[] = { 275 { nxt_string("home"), 276 NXT_CONF_VLDT_STRING, 277 NULL, 278 NULL }, 279 280 { nxt_string("path"), 281 NXT_CONF_VLDT_STRING, 282 NULL, 283 NULL }, 284 285 { nxt_string("module"), 286 NXT_CONF_VLDT_STRING, 287 NULL, 288 NULL }, 289 290 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 291 }; 292 293 294 static nxt_conf_vldt_object_t nxt_conf_vldt_php_options_members[] = { 295 { nxt_string("file"), 296 NXT_CONF_VLDT_STRING, 297 NULL, 298 NULL }, 299 300 { nxt_string("admin"), 301 NXT_CONF_VLDT_OBJECT, 302 &nxt_conf_vldt_object_iterator, 303 (void *) &nxt_conf_vldt_php_option }, 304 305 { nxt_string("user"), 306 NXT_CONF_VLDT_OBJECT, 307 &nxt_conf_vldt_object_iterator, 308 (void *) &nxt_conf_vldt_php_option }, 309 310 NXT_CONF_VLDT_END 311 }; 312 313 314 static nxt_conf_vldt_object_t nxt_conf_vldt_php_members[] = { 315 { nxt_string("root"), 316 NXT_CONF_VLDT_STRING, 317 NULL, 318 NULL }, 319 320 { nxt_string("script"), 321 NXT_CONF_VLDT_STRING, 322 NULL, 323 NULL }, 324 325 { nxt_string("index"), 326 NXT_CONF_VLDT_STRING, 327 NULL, 328 NULL }, 329 330 { nxt_string("options"), 331 NXT_CONF_VLDT_OBJECT, 332 &nxt_conf_vldt_object, 333 (void *) &nxt_conf_vldt_php_options_members }, 334 335 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 336 }; 337 338 339 static nxt_conf_vldt_object_t nxt_conf_vldt_perl_members[] = { 340 { nxt_string("script"), 341 NXT_CONF_VLDT_STRING, 342 NULL, 343 NULL }, 344 345 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 346 }; 347 348 349 static nxt_conf_vldt_object_t nxt_conf_vldt_ruby_members[] = { 350 { nxt_string("script"), 351 NXT_CONF_VLDT_STRING, 352 NULL, 353 NULL }, 354 355 NXT_CONF_VLDT_NEXT(&nxt_conf_vldt_common_members) 356 }; 357 358 359 nxt_int_t 360 nxt_conf_validate(nxt_conf_validation_t *vldt) 361 { 362 nxt_int_t ret; 363 364 ret = nxt_conf_vldt_type(vldt, NULL, vldt->conf, NXT_CONF_VLDT_OBJECT); 365 366 if (ret != NXT_OK) { 367 return ret; 368 } 369 370 return nxt_conf_vldt_object(vldt, vldt->conf, nxt_conf_vldt_root_members); 371 } 372 373 374 #define NXT_CONF_VLDT_ANY_TYPE \ 375 "either a null, a boolean, an integer, " \ 376 "a number, a string, an array, or an object" 377 378 379 static nxt_int_t 380 nxt_conf_vldt_type(nxt_conf_validation_t *vldt, nxt_str_t *name, 381 nxt_conf_value_t *value, nxt_conf_vldt_type_t type) 382 { 383 u_char *p; 384 nxt_str_t expected; 385 nxt_bool_t serial; 386 nxt_uint_t value_type, n, t; 387 u_char buf[nxt_length(NXT_CONF_VLDT_ANY_TYPE)]; 388 389 static nxt_str_t type_name[] = { 390 nxt_string("a null"), 391 nxt_string("a boolean"), 392 nxt_string("an integer"), 393 nxt_string("a number"), 394 nxt_string("a string"), 395 nxt_string("an array"), 396 nxt_string("an object"), 397 }; 398 399 value_type = nxt_conf_type(value); 400 401 if ((1 << value_type) & type) { 402 return NXT_OK; 403 } 404 405 p = buf; 406 407 n = nxt_popcount(type); 408 409 if (n > 1) { 410 p = nxt_cpymem(p, "either ", 7); 411 } 412 413 serial = (n > 2); 414 415 for ( ;; ) { 416 t = __builtin_ffs(type) - 1; 417 418 p = nxt_cpymem(p, type_name[t].start, type_name[t].length); 419 420 n--; 421 422 if (n == 0) { 423 break; 424 } 425 426 if (n > 1 || serial) { 427 *p++ = ','; 428 } 429 430 if (n == 1) { 431 p = nxt_cpymem(p, " or", 3); 432 } 433 434 *p++ = ' '; 435 436 type = type & ~(1 << t); 437 } 438 439 expected.length = p - buf; 440 expected.start = buf; 441 442 if (name == NULL) { 443 return nxt_conf_vldt_error(vldt, 444 "The configuration must be %V, but not %V.", 445 &expected, &type_name[value_type]); 446 } 447 448 return nxt_conf_vldt_error(vldt, 449 "The \"%V\" value must be %V, but not %V.", 450 name, &expected, &type_name[value_type]); 451 } 452 453 454 static nxt_int_t 455 nxt_conf_vldt_error(nxt_conf_validation_t *vldt, const char *fmt, ...) 456 { 457 u_char *p, *end; 458 size_t size; 459 va_list args; 460 u_char error[NXT_MAX_ERROR_STR]; 461 462 va_start(args, fmt); 463 end = nxt_vsprintf(error, error + NXT_MAX_ERROR_STR, fmt, args); 464 va_end(args); 465 466 size = end - error; 467 468 p = nxt_mp_nget(vldt->pool, size); 469 if (p == NULL) { 470 return NXT_ERROR; 471 } 472 473 nxt_memcpy(p, error, size); 474 475 vldt->error.length = size; 476 vldt->error.start = p; 477 478 return NXT_DECLINED; 479 } 480 481 482 static nxt_int_t 483 nxt_conf_vldt_listener(nxt_conf_validation_t *vldt, nxt_str_t *name, 484 nxt_conf_value_t *value) 485 { 486 nxt_int_t ret; 487 488 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); 489 490 if (ret != NXT_OK) { 491 return ret; 492 } 493 494 return nxt_conf_vldt_object(vldt, value, nxt_conf_vldt_listener_members); 495 } 496 497 498 #if (NXT_TLS) 499 500 static nxt_int_t 501 nxt_conf_vldt_certificate(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 502 void *data) 503 { 504 nxt_str_t name; 505 nxt_conf_value_t *cert; 506 507 nxt_conf_get_string(value, &name); 508 509 cert = nxt_cert_info_get(&name); 510 511 if (cert == NULL) { 512 return nxt_conf_vldt_error(vldt, "Certificate \"%V\" is not found.", 513 &name); 514 } 515 516 return NXT_OK; 517 } 518 519 #endif 520 521 522 static nxt_int_t 523 nxt_conf_vldt_app_name(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 524 void *data) 525 { 526 nxt_str_t name; 527 nxt_conf_value_t *apps, *app; 528 529 static nxt_str_t apps_str = nxt_string("applications"); 530 531 nxt_conf_get_string(value, &name); 532 533 apps = nxt_conf_get_object_member(vldt->conf, &apps_str, NULL); 534 535 if (nxt_slow_path(apps == NULL)) { 536 goto error; 537 } 538 539 app = nxt_conf_get_object_member(apps, &name, NULL); 540 541 if (nxt_slow_path(app == NULL)) { 542 goto error; 543 } 544 545 return NXT_OK; 546 547 error: 548 549 return nxt_conf_vldt_error(vldt, "Listening socket is assigned for " 550 "a non existing application \"%V\".", 551 &name); 552 } 553 554 555 static nxt_int_t 556 nxt_conf_vldt_app(nxt_conf_validation_t *vldt, nxt_str_t *name, 557 nxt_conf_value_t *value) 558 { 559 nxt_int_t ret; 560 nxt_str_t type; 561 nxt_thread_t *thread; 562 nxt_conf_value_t *type_value; 563 nxt_app_lang_module_t *lang; 564 565 static nxt_str_t type_str = nxt_string("type"); 566 567 static void *members[] = { 568 nxt_conf_vldt_external_members, 569 nxt_conf_vldt_python_members, 570 nxt_conf_vldt_php_members, 571 nxt_conf_vldt_perl_members, 572 nxt_conf_vldt_ruby_members, 573 }; 574 575 ret = nxt_conf_vldt_type(vldt, name, value, NXT_CONF_VLDT_OBJECT); 576 577 if (ret != NXT_OK) { 578 return ret; 579 } 580 581 type_value = nxt_conf_get_object_member(value, &type_str, NULL); 582 583 if (type_value == NULL) { 584 return nxt_conf_vldt_error(vldt, 585 "Application must have the \"type\" property set."); 586 } 587 588 ret = nxt_conf_vldt_type(vldt, &type_str, type_value, NXT_CONF_VLDT_STRING); 589 590 if (ret != NXT_OK) { 591 return ret; 592 } 593 594 nxt_conf_get_string(type_value, &type); 595 596 thread = nxt_thread(); 597 598 lang = nxt_app_lang_module(thread->runtime, &type); 599 if (lang == NULL) { 600 return nxt_conf_vldt_error(vldt, 601 "The module to run \"%V\" is not found " 602 "among the available application modules.", 603 &type); 604 } 605 606 return nxt_conf_vldt_object(vldt, value, members[lang->type]); 607 } 608 609 610 static nxt_int_t 611 nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 612 void *data) 613 { 614 uint32_t index; 615 nxt_int_t ret; 616 nxt_str_t name; 617 nxt_conf_value_t *member; 618 nxt_conf_vldt_object_t *vals; 619 620 index = 0; 621 622 for ( ;; ) { 623 member = nxt_conf_next_object_member(value, &name, &index); 624 625 if (member == NULL) { 626 return NXT_OK; 627 } 628 629 vals = data; 630 631 for ( ;; ) { 632 if (vals->name.length == 0) { 633 634 if (vals->data != NULL) { 635 vals = vals->data; 636 continue; 637 } 638 639 return nxt_conf_vldt_error(vldt, "Unknown parameter \"%V\".", 640 &name); 641 } 642 643 if (!nxt_strstr_eq(&vals->name, &name)) { 644 vals++; 645 continue; 646 } 647 648 ret = nxt_conf_vldt_type(vldt, &name, member, vals->type); 649 650 if (ret != NXT_OK) { 651 return ret; 652 } 653 654 if (vals->validator != NULL) { 655 ret = vals->validator(vldt, member, vals->data); 656 657 if (ret != NXT_OK) { 658 return ret; 659 } 660 } 661 662 break; 663 } 664 } 665 } 666 667 668 typedef struct { 669 int64_t spare; 670 int64_t max; 671 int64_t idle_timeout; 672 } nxt_conf_vldt_processes_conf_t; 673 674 675 static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = { 676 { 677 nxt_string("spare"), 678 NXT_CONF_MAP_INT64, 679 offsetof(nxt_conf_vldt_processes_conf_t, spare), 680 }, 681 682 { 683 nxt_string("max"), 684 NXT_CONF_MAP_INT64, 685 offsetof(nxt_conf_vldt_processes_conf_t, max), 686 }, 687 688 { 689 nxt_string("idle_timeout"), 690 NXT_CONF_MAP_INT64, 691 offsetof(nxt_conf_vldt_processes_conf_t, idle_timeout), 692 }, 693 }; 694 695 696 static nxt_int_t 697 nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 698 void *data) 699 { 700 int64_t int_value; 701 nxt_int_t ret; 702 nxt_conf_vldt_processes_conf_t proc; 703 704 if (nxt_conf_type(value) == NXT_CONF_INTEGER) { 705 int_value = nxt_conf_get_integer(value); 706 707 if (int_value < 1) { 708 return nxt_conf_vldt_error(vldt, "The \"processes\" number must be " 709 "equal to or greater than 1."); 710 } 711 712 if (int_value > NXT_INT32_T_MAX) { 713 return nxt_conf_vldt_error(vldt, "The \"processes\" number must " 714 "not exceed %d.", NXT_INT32_T_MAX); 715 } 716 717 return NXT_OK; 718 } 719 720 ret = nxt_conf_vldt_object(vldt, value, data); 721 if (ret != NXT_OK) { 722 return ret; 723 } 724 725 proc.spare = 0; 726 proc.max = 1; 727 proc.idle_timeout = 15; 728 729 ret = nxt_conf_map_object(vldt->pool, value, 730 nxt_conf_vldt_processes_conf_map, 731 nxt_nitems(nxt_conf_vldt_processes_conf_map), 732 &proc); 733 if (ret != NXT_OK) { 734 return ret; 735 } 736 737 if (proc.spare < 0) { 738 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be " 739 "negative."); 740 } 741 742 if (proc.spare > NXT_INT32_T_MAX) { 743 return nxt_conf_vldt_error(vldt, "The \"spare\" number must not " 744 "exceed %d.", NXT_INT32_T_MAX); 745 } 746 747 if (proc.max < 1) { 748 return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal " 749 "to or greater than 1."); 750 } 751 752 if (proc.max > NXT_INT32_T_MAX) { 753 return nxt_conf_vldt_error(vldt, "The \"max\" number must not " 754 "exceed %d.", NXT_INT32_T_MAX); 755 } 756 757 if (proc.max < proc.spare) { 758 return nxt_conf_vldt_error(vldt, "The \"spare\" number must be " 759 "less than or equal to \"max\"."); 760 } 761 762 if (proc.idle_timeout < 0) { 763 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not " 764 "be negative."); 765 } 766 767 if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) { 768 return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not " 769 "exceed %d.", NXT_INT32_T_MAX / 1000); 770 } 771 772 return NXT_OK; 773 } 774 775 776 static nxt_int_t 777 nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt, 778 nxt_conf_value_t *value, void *data) 779 { 780 uint32_t index; 781 nxt_int_t ret; 782 nxt_str_t name; 783 nxt_conf_value_t *member; 784 nxt_conf_vldt_member_t validator; 785 786 validator = (nxt_conf_vldt_member_t) data; 787 index = 0; 788 789 for ( ;; ) { 790 member = nxt_conf_next_object_member(value, &name, &index); 791 792 if (member == NULL) { 793 return NXT_OK; 794 } 795 796 ret = validator(vldt, &name, member); 797 798 if (ret != NXT_OK) { 799 return ret; 800 } 801 } 802 } 803 804 805 static nxt_int_t 806 nxt_conf_vldt_array_iterator(nxt_conf_validation_t *vldt, 807 nxt_conf_value_t *value, void *data) 808 { 809 uint32_t index; 810 nxt_int_t ret; 811 nxt_conf_value_t *element; 812 nxt_conf_vldt_element_t validator; 813 814 validator = (nxt_conf_vldt_element_t) data; 815 816 for (index = 0; /* void */ ; index++) { 817 element = nxt_conf_get_array_element(value, index); 818 819 if (element == NULL) { 820 return NXT_OK; 821 } 822 823 ret = validator(vldt, element); 824 825 if (ret != NXT_OK) { 826 return ret; 827 } 828 } 829 } 830 831 832 static nxt_int_t 833 nxt_conf_vldt_system(nxt_conf_validation_t *vldt, nxt_conf_value_t *value, 834 void *data) 835 { 836 size_t length; 837 nxt_str_t name; 838 nxt_conf_vldt_system_t validator; 839 char string[32]; 840 841 /* The cast is required by Sun C. */ 842 validator = (nxt_conf_vldt_system_t) data; 843 844 nxt_conf_get_string(value, &name); 845 846 length = name.length + 1; 847 length = nxt_min(length, sizeof(string)); 848 849 nxt_cpystrn((u_char *) string, name.start, length); 850 851 return validator(vldt, string); 852 } 853 854 855 static nxt_int_t 856 nxt_conf_vldt_user(nxt_conf_validation_t *vldt, char *user) 857 { 858 struct passwd *pwd; 859 860 nxt_errno = 0; 861 862 pwd = getpwnam(user); 863 864 if (pwd != NULL) { 865 return NXT_OK; 866 } 867 868 if (nxt_errno == 0) { 869 return nxt_conf_vldt_error(vldt, "User \"%s\" is not found.", user); 870 } 871 872 return NXT_ERROR; 873 } 874 875 876 static nxt_int_t 877 nxt_conf_vldt_group(nxt_conf_validation_t *vldt, char *group) 878 { 879 struct group *grp; 880 881 nxt_errno = 0; 882 883 grp = getgrnam(group); 884 885 if (grp != NULL) { 886 return NXT_OK; 887 } 888 889 if (nxt_errno == 0) { 890 return nxt_conf_vldt_error(vldt, "Group \"%s\" is not found.", group); 891 } 892 893 return NXT_ERROR; 894 } 895 896 897 static nxt_int_t 898 nxt_conf_vldt_environment(nxt_conf_validation_t *vldt, nxt_str_t *name, 899 nxt_conf_value_t *value) 900 { 901 nxt_str_t str; 902 903 if (name->length == 0) { 904 return nxt_conf_vldt_error(vldt, 905 "The environment name must not be empty."); 906 } 907 908 if (nxt_memchr(name->start, '\0', name->length) != NULL) { 909 return nxt_conf_vldt_error(vldt, "The environment name must not " 910 "contain null character."); 911 } 912 913 if (nxt_memchr(name->start, '=', name->length) != NULL) { 914 return nxt_conf_vldt_error(vldt, "The environment name must not " 915 "contain '=' character."); 916 } 917 918 if (nxt_conf_type(value) != NXT_CONF_STRING) { 919 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must be " 920 "a string.", name); 921 } 922 923 nxt_conf_get_string(value, &str); 924 925 if (nxt_memchr(str.start, '\0', str.length) != NULL) { 926 return nxt_conf_vldt_error(vldt, "The \"%V\" environment value must " 927 "not contain null character.", name); 928 } 929 930 return NXT_OK; 931 } 932 933 934 static nxt_int_t 935 nxt_conf_vldt_argument(nxt_conf_validation_t *vldt, nxt_conf_value_t *value) 936 { 937 nxt_str_t str; 938 939 if (nxt_conf_type(value) != NXT_CONF_STRING) { 940 return nxt_conf_vldt_error(vldt, "The \"arguments\" array " 941 "must contain only string values."); 942 } 943 944 nxt_conf_get_string(value, &str); 945 946 if (nxt_memchr(str.start, '\0', str.length) != NULL) { 947 return nxt_conf_vldt_error(vldt, "The \"arguments\" array must not " 948 "contain strings with null character."); 949 } 950 951 return NXT_OK; 952 } 953 954 955 static nxt_int_t 956 nxt_conf_vldt_php_option(nxt_conf_validation_t *vldt, nxt_str_t *name, 957 nxt_conf_value_t *value) 958 { 959 if (name->length == 0) { 960 return nxt_conf_vldt_error(vldt, 961 "The PHP option name must not be empty."); 962 } 963 964 if (nxt_conf_type(value) != NXT_CONF_STRING) { 965 return nxt_conf_vldt_error(vldt, "The \"%V\" PHP option must be " 966 "a string.", name); 967 } 968 969 return NXT_OK; 970 } 971