1 /* $NetBSD: main.c,v 1.4 2025/09/05 21:16:25 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2024 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in the file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 /* Portions Copyright (c) 1995 Regents of the University of Michigan. 18 * All rights reserved. 19 * 20 * Redistribution and use in source and binary forms are permitted 21 * provided that this notice is preserved and that due credit is given 22 * to the University of Michigan at Ann Arbor. The name of the University 23 * may not be used to endorse or promote products derived from this 24 * software without specific prior written permission. This software 25 * is provided ``as is'' without express or implied warranty. 26 */ 27 28 #include <sys/cdefs.h> 29 __RCSID("$NetBSD: main.c,v 1.4 2025/09/05 21:16:25 christos Exp $"); 30 31 #include "portable.h" 32 33 #include <stdio.h> 34 35 #include <ac/ctype.h> 36 #include <ac/socket.h> 37 #include <ac/string.h> 38 #include <ac/time.h> 39 #include <ac/unistd.h> 40 #include <ac/wait.h> 41 #include <ac/errno.h> 42 43 #include "slap.h" 44 #include "lutil.h" 45 #include "ldif.h" 46 47 #ifdef LDAP_SLAPI 48 #include "slapi/slapi.h" 49 #endif 50 51 #ifdef LDAP_SIGCHLD 52 static RETSIGTYPE wait4child( int sig ); 53 #endif 54 55 #ifdef HAVE_NT_SERVICE_MANAGER 56 #define MAIN_RETURN(x) return 57 static struct sockaddr_in bind_addr; 58 59 #define SERVICE_EXIT( e, n ) do { \ 60 if ( is_NT_Service ) { \ 61 lutil_ServiceStatus.dwWin32ExitCode = (e); \ 62 lutil_ServiceStatus.dwServiceSpecificExitCode = (n); \ 63 } \ 64 } while ( 0 ) 65 66 #else 67 #define SERVICE_EXIT( e, n ) 68 #define MAIN_RETURN(x) return(x) 69 #endif 70 71 typedef int (MainFunc) LDAP_P(( int argc, char *argv[] )); 72 extern MainFunc slapadd, slapcat, slapdn, slapindex, slappasswd, 73 slaptest, slapauth, slapacl, slapschema, slapmodify; 74 75 static struct { 76 char *name; 77 MainFunc *func; 78 } tools[] = { 79 {"slapadd", slapadd}, 80 {"slapcat", slapcat}, 81 {"slapdn", slapdn}, 82 {"slapindex", slapindex}, 83 {"slapmodify", slapmodify}, 84 {"slappasswd", slappasswd}, 85 {"slapschema", slapschema}, 86 {"slaptest", slaptest}, 87 {"slapauth", slapauth}, 88 {"slapacl", slapacl}, 89 /* NOTE: new tools must be added in chronological order, 90 * not in alphabetical order, because for backwards 91 * compatibility name[4] is used to identify the 92 * tools; so name[4]=='a' must refer to "slapadd" and 93 * not to "slapauth". Alphabetical order can be used 94 * for tools whose name[4] is not used yet */ 95 {NULL, NULL} 96 }; 97 98 /* 99 * when more than one slapd is running on one machine, each one might have 100 * it's own LOCAL for syslogging and must have its own pid/args files 101 */ 102 103 #ifndef HAVE_MKVERSION 104 const char Versionstr[] = 105 OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Server (slapd)"; 106 #endif 107 108 extern OverlayInit slap_oinfo[]; 109 extern BackendInfo slap_binfo[]; 110 111 #define CHECK_NONE 0x00 112 #define CHECK_CONFIG 0x01 113 #define CHECK_LOGLEVEL 0x02 114 static int check = CHECK_NONE; 115 static int version = 0; 116 117 void *slap_tls_ctx; 118 LDAP *slap_tls_ld; 119 120 static int 121 slapd_opt_slp( const char *val, void *arg ) 122 { 123 #ifdef HAVE_SLP 124 /* NULL is default */ 125 if ( val == NULL || *val == '(' || strcasecmp( val, "on" ) == 0 ) { 126 slapd_register_slp = 1; 127 slapd_slp_attrs = (val != NULL && *val == '(') ? val : NULL; 128 129 } else if ( strcasecmp( val, "off" ) == 0 ) { 130 slapd_register_slp = 0; 131 132 /* NOTE: add support for URL specification? */ 133 134 } else { 135 fprintf(stderr, "unrecognized value \"%s\" for SLP option\n", val ); 136 return -1; 137 } 138 139 return 0; 140 141 #else 142 fputs( "slapd: SLP support is not available\n", stderr ); 143 return 0; 144 #endif 145 } 146 147 /* 148 * Option helper structure: 149 * 150 * oh_nam is left-hand part of <option>[=<value>] 151 * oh_fnc is handler function 152 * oh_arg is an optional arg to oh_fnc 153 * oh_usage is the one-line usage string related to the option, 154 * which is assumed to start with <option>[=<value>] 155 * 156 * please leave valid options in the structure, and optionally #ifdef 157 * their processing inside the helper, so that reasonable and helpful 158 * error messages can be generated if a disabled option is requested. 159 */ 160 struct option_helper { 161 struct berval oh_name; 162 int (*oh_fnc)(const char *val, void *arg); 163 void *oh_arg; 164 const char *oh_usage; 165 } option_helpers[] = { 166 { BER_BVC("slp"), slapd_opt_slp, NULL, "slp[={on|off|(attrs)}] enable/disable SLP using (attrs)" }, 167 { BER_BVNULL, 0, NULL, NULL } 168 }; 169 170 static void 171 usage( char *name ) 172 { 173 fprintf( stderr, 174 "usage: %s options\n", name ); 175 fprintf( stderr, 176 "\t-4\t\tIPv4 only\n" 177 #ifdef LDAP_PF_INET6 178 "\t-6\t\tIPv6 only\n" 179 #endif 180 "\t-T {acl|add|auth|cat|dn|index|modify|passwd|test}\n" 181 "\t\t\tRun in Tool mode\n" 182 "\t-c cookie\tSync cookie of consumer\n" 183 "\t-d level\tDebug level" "\n" 184 "\t-f filename\tConfiguration file\n" 185 "\t-F dir\tConfiguration directory\n" 186 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 187 "\t-g group\tGroup (id or name) to run as\n" 188 #endif 189 "\t-h URLs\t\tList of URLs to serve\n" 190 #ifdef SLAP_DEFAULT_SYSLOG_USER 191 "\t-l facility\tSyslog facility (default: LOCAL4)\n" 192 #endif 193 "\t-n serverName\tService name\n" 194 "\t-o <opt>[=val] generic means to specify options" ); 195 if ( !BER_BVISNULL( &option_helpers[0].oh_name ) ) { 196 int i; 197 198 fprintf( stderr, "; supported options:\n" ); 199 for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++) { 200 fprintf( stderr, "\t\t%s\n", option_helpers[i].oh_usage ); 201 } 202 } else { 203 fprintf( stderr, "\n" ); 204 } 205 fprintf( stderr, 206 #ifdef HAVE_CHROOT 207 "\t-r directory\tSandbox directory to chroot to\n" 208 #endif 209 "\t-s level\tSyslog level\n" 210 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 211 "\t-u user\t\tUser (id or name) to run as\n" 212 #endif 213 "\t-V\t\tprint version info (-VV exit afterwards, -VVV print\n" 214 "\t\t\tinfo about static overlays and backends)\n" 215 ); 216 } 217 218 #ifdef HAVE_NT_SERVICE_MANAGER 219 void WINAPI ServiceMain( DWORD argc, LPTSTR *argv ) 220 #else 221 int main( int argc, char **argv ) 222 #endif 223 { 224 int i, no_detach = 0; 225 int rc = 1; 226 char *urls = NULL; 227 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 228 char *username = NULL; 229 char *groupname = NULL; 230 #endif 231 #if defined(HAVE_CHROOT) 232 char *sandbox = NULL; 233 #endif 234 #ifdef SLAP_DEFAULT_SYSLOG_USER 235 int syslogUser = SLAP_DEFAULT_SYSLOG_USER; 236 #endif 237 238 #ifndef HAVE_WINSOCK 239 int pid, waitfds[2]; 240 #endif 241 int g_argc = argc; 242 char **g_argv = argv; 243 244 char *configfile = NULL; 245 char *configdir = NULL; 246 int serverMode = SLAP_SERVER_MODE; 247 248 struct sync_cookie *scp = NULL; 249 struct sync_cookie *scp_entry = NULL; 250 251 char *serverNamePrefix = ""; 252 size_t l; 253 254 int slapd_pid_file_unlink = 0, slapd_args_file_unlink = 0; 255 int firstopt = 1; 256 257 #ifdef CSRIMALLOC 258 FILE *leakfile; 259 if( ( leakfile = fopen( "slapd.leak", "w" )) == NULL ) { 260 leakfile = stderr; 261 } 262 #endif 263 264 slap_sl_mem_init(); 265 266 (void) ldap_pvt_thread_initialize(); 267 ldap_pvt_thread_mutex_init( &logfile_mutex ); 268 269 #ifdef HAVE_TLS 270 rc = ldap_create( &slap_tls_ld ); 271 if ( rc ) { 272 MAIN_RETURN( rc ); 273 } 274 /* Library defaults to full certificate checking. This is correct when 275 * a client is verifying a server because all servers should have a 276 * valid cert. But few clients have valid certs, so we want our default 277 * to be no checking. The config file can override this as usual. 278 */ 279 rc = LDAP_OPT_X_TLS_NEVER; 280 (void) ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &rc ); 281 #endif 282 283 global_host = ldap_pvt_get_fqdn( NULL ); 284 ber_str2bv( global_host, 0, 0, &global_host_bv ); 285 286 serverName = lutil_progname( "slapd", argc, argv ); 287 288 if ( strcmp( serverName, "slapd" ) ) { 289 #ifdef DEBUG_CLOSE 290 extern void slapd_debug_close(); 291 slapd_debug_close(); 292 #endif 293 for (i=0; tools[i].name; i++) { 294 if ( !strcmp( serverName, tools[i].name ) ) { 295 rc = tools[i].func(argc, argv); 296 MAIN_RETURN(rc); 297 } 298 } 299 } 300 301 #ifdef HAVE_NT_SERVICE_MANAGER 302 { 303 int *ip; 304 char *newConfigFile; 305 char *newConfigDir; 306 char *newUrls; 307 char *regService = NULL; 308 309 if ( is_NT_Service ) { 310 lutil_CommenceStartupProcessing( serverName, slap_sig_shutdown ); 311 if ( strcmp(serverName, SERVICE_NAME) ) 312 regService = serverName; 313 } 314 315 ip = (int*)lutil_getRegParam( regService, "DebugLevel" ); 316 if ( ip != NULL ) { 317 slap_debug = *ip; 318 Debug( LDAP_DEBUG_ANY, 319 "new debug level from registry is: %d\n", slap_debug ); 320 } 321 322 newUrls = (char *) lutil_getRegParam(regService, "Urls"); 323 if (newUrls) { 324 urls = ch_strdup(newUrls); 325 Debug(LDAP_DEBUG_ANY, "new urls from registry: %s\n", 326 urls ); 327 } 328 329 newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" ); 330 if ( newConfigFile != NULL ) { 331 configfile = ch_strdup(newConfigFile); 332 Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile ); 333 } 334 335 newConfigDir = (char*)lutil_getRegParam( regService, "ConfigDir" ); 336 if ( newConfigDir != NULL ) { 337 configdir = ch_strdup(newConfigDir); 338 Debug ( LDAP_DEBUG_ANY, "new config dir from registry is: %s\n", configdir ); 339 } 340 } 341 #endif 342 343 while ( (i = getopt( argc, argv, 344 "c:d:f:F:h:n:o:s:tT:V" 345 #ifdef LDAP_PF_INET6 346 "46" 347 #endif 348 #ifdef HAVE_CHROOT 349 "r:" 350 #endif 351 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 352 "S:" 353 #ifdef LOG_LOCAL4 354 "l:" 355 #endif 356 #endif 357 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 358 "u:g:" 359 #endif 360 )) != EOF ) { 361 switch ( i ) { 362 case '4': 363 slap_inet4or6 = AF_INET; 364 break; 365 #ifdef LDAP_PF_INET6 366 case '6': 367 slap_inet4or6 = AF_INET6; 368 break; 369 #endif 370 371 case 'h': /* listen URLs */ 372 urls = optarg; 373 break; 374 375 case 'c': /* provide sync cookie, override if exist in consumer */ 376 scp = (struct sync_cookie *) ch_calloc( 1, 377 sizeof( struct sync_cookie )); 378 ber_str2bv( optarg, 0, 1, &scp->octet_str ); 379 380 /* This only parses out the rid at this point */ 381 slap_parse_sync_cookie( scp, NULL ); 382 383 if ( scp->rid == -1 ) { 384 Debug( LDAP_DEBUG_ANY, 385 "main: invalid cookie \"%s\"\n", 386 optarg ); 387 slap_sync_cookie_free( scp, 1 ); 388 goto destroy; 389 } 390 391 LDAP_STAILQ_FOREACH( scp_entry, &slap_sync_cookie, sc_next ) { 392 if ( scp->rid == scp_entry->rid ) { 393 Debug( LDAP_DEBUG_ANY, 394 "main: duplicated replica id in cookies\n" ); 395 slap_sync_cookie_free( scp, 1 ); 396 goto destroy; 397 } 398 } 399 LDAP_STAILQ_INSERT_TAIL( &slap_sync_cookie, scp, sc_next ); 400 break; 401 402 case 'd': { /* set debug level and 'do not detach' flag */ 403 int level = 0; 404 405 if ( strcmp( optarg, "?" ) == 0 ) { 406 check |= CHECK_LOGLEVEL; 407 break; 408 } 409 410 no_detach = 1; 411 if ( slap_parse_debug_level( optarg, &level, 0 ) ) { 412 goto destroy; 413 } 414 #ifdef LDAP_DEBUG 415 slap_debug |= level; 416 #else 417 if ( level != 0 ) 418 fputs( "must compile with LDAP_DEBUG for debugging\n", 419 stderr ); 420 #endif 421 } break; 422 423 case 'f': /* read config file */ 424 configfile = optarg; 425 break; 426 427 case 'F': /* use config dir */ 428 configdir = optarg; 429 break; 430 431 case 'o': { 432 char *val = strchr( optarg, '=' ); 433 struct berval opt; 434 435 opt.bv_val = optarg; 436 437 if ( val ) { 438 opt.bv_len = ( val - optarg ); 439 val++; 440 441 } else { 442 opt.bv_len = strlen( optarg ); 443 } 444 445 for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++ ) { 446 if ( ber_bvstrcasecmp( &option_helpers[i].oh_name, &opt ) == 0 ) { 447 assert( option_helpers[i].oh_fnc != NULL ); 448 if ( (*option_helpers[i].oh_fnc)( val, option_helpers[i].oh_arg ) == -1 ) { 449 /* we assume the option parsing helper 450 * issues appropriate and self-explanatory 451 * error messages... */ 452 goto stop; 453 } 454 break; 455 } 456 } 457 458 if ( BER_BVISNULL( &option_helpers[i].oh_name ) ) { 459 goto unhandled_option; 460 } 461 break; 462 } 463 464 case 's': /* set syslog level */ 465 if ( strcmp( optarg, "?" ) == 0 ) { 466 check |= CHECK_LOGLEVEL; 467 break; 468 } 469 470 if ( slap_parse_debug_level( optarg, &ldap_syslog, 1 ) ) { 471 goto destroy; 472 } 473 break; 474 475 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 476 case 'S': 477 if ( slap_parse_syslog_level( optarg, &ldap_syslog_level ) ) { 478 goto destroy; 479 } 480 break; 481 482 #ifdef LOG_LOCAL4 483 case 'l': /* set syslog local user */ 484 if ( slap_parse_syslog_user( optarg, &syslogUser ) ) { 485 goto destroy; 486 } 487 break; 488 #endif 489 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 490 491 #ifdef HAVE_CHROOT 492 case 'r': 493 sandbox = optarg; 494 break; 495 #endif 496 497 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 498 case 'u': /* user name */ 499 username = optarg; 500 break; 501 502 case 'g': /* group name */ 503 groupname = optarg; 504 break; 505 #endif /* SETUID && GETUID */ 506 507 case 'n': /* NT service name */ 508 serverName = optarg; 509 break; 510 511 case 't': 512 /* deprecated; use slaptest instead */ 513 fprintf( stderr, "option -t deprecated; " 514 "use slaptest command instead\n" ); 515 check |= CHECK_CONFIG; 516 break; 517 518 case 'V': 519 version++; 520 break; 521 522 case 'T': 523 if ( firstopt == 0 ) { 524 fprintf( stderr, "warning: \"-T %s\" " 525 "should be the first option.\n", 526 optarg ); 527 } 528 529 #ifdef DEBUG_CLOSE 530 extern void slapd_debug_close(); 531 slapd_debug_close(); 532 #endif 533 /* try full option string first */ 534 for ( i = 0; tools[i].name; i++ ) { 535 if ( strcmp( optarg, &tools[i].name[4] ) == 0 ) { 536 rc = tools[i].func( argc, argv ); 537 MAIN_RETURN( rc ); 538 } 539 } 540 541 /* try bits of option string (backward compatibility for single char) */ 542 l = strlen( optarg ); 543 for ( i = 0; tools[i].name; i++ ) { 544 if ( strncmp( optarg, &tools[i].name[4], l ) == 0 ) { 545 rc = tools[i].func( argc, argv ); 546 MAIN_RETURN( rc ); 547 } 548 } 549 550 /* issue error */ 551 serverName = optarg; 552 serverNamePrefix = "slap"; 553 fprintf( stderr, "program name \"%s%s\" unrecognized; " 554 "aborting...\n", serverNamePrefix, serverName ); 555 /* FALLTHRU */ 556 default: 557 unhandled_option:; 558 usage( argv[0] ); 559 rc = 1; 560 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 ); 561 goto stop; 562 } 563 564 if ( firstopt ) { 565 firstopt = 0; 566 } 567 } 568 569 if ( optind != argc ) 570 goto unhandled_option; 571 572 ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN, slap_debug_print); 573 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug); 574 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug); 575 ldif_debug = slap_debug; 576 slap_debug_orig = slap_debug; 577 578 if ( version ) { 579 fprintf( stderr, "%s\n", Versionstr ); 580 if ( version > 2 ) { 581 if ( slap_oinfo[0].ov_type ) { 582 fprintf( stderr, "Included static overlays:\n"); 583 for ( i= 0 ; slap_oinfo[i].ov_type; i++ ) { 584 fprintf( stderr, " %s\n", slap_oinfo[i].ov_type ); 585 } 586 } 587 if ( slap_binfo[0].bi_type ) { 588 fprintf( stderr, "Included static backends:\n"); 589 for ( i= 0 ; slap_binfo[i].bi_type; i++ ) { 590 fprintf( stderr, " %s\n", slap_binfo[i].bi_type ); 591 } 592 } 593 } 594 595 if ( version > 1 ) goto stop; 596 } 597 598 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 599 { 600 char *logName; 601 #ifdef HAVE_EBCDIC 602 logName = ch_strdup( serverName ); 603 __atoe( logName ); 604 #else 605 logName = serverName; 606 #endif 607 608 #ifdef LOG_LOCAL4 609 openlog( logName, OPENLOG_OPTIONS, syslogUser ); 610 #elif defined LOG_DEBUG 611 openlog( logName, OPENLOG_OPTIONS ); 612 #endif 613 #ifdef HAVE_EBCDIC 614 free( logName ); 615 #endif 616 } 617 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 618 619 Debug( LDAP_DEBUG_ANY, "%s", Versionstr ); 620 621 if( check == CHECK_NONE && slapd_daemon_init( urls ) != 0 ) { 622 rc = 1; 623 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 ); 624 goto stop; 625 } 626 627 #if defined(HAVE_CHROOT) 628 if ( sandbox ) { 629 if ( chdir( sandbox ) ) { 630 perror("chdir"); 631 rc = 1; 632 goto stop; 633 } 634 if ( chroot( sandbox ) ) { 635 perror("chroot"); 636 rc = 1; 637 goto stop; 638 } 639 if ( chdir( "/" ) ) { 640 perror("chdir"); 641 rc = 1; 642 goto stop; 643 } 644 } 645 #endif 646 647 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 648 if ( username != NULL || groupname != NULL ) { 649 slap_init_user( username, groupname ); 650 } 651 #endif 652 653 extops_init(); 654 lutil_passwd_init(); 655 656 rc = slap_init( serverMode, serverName ); 657 if ( rc ) { 658 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 ); 659 goto destroy; 660 } 661 662 if ( read_config( configfile, configdir ) != 0 ) { 663 rc = 1; 664 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 ); 665 666 if ( check & CHECK_CONFIG ) { 667 fprintf( stderr, "config check failed\n" ); 668 } 669 670 goto destroy; 671 } 672 673 rc = slap_parse_debug_unknowns(); 674 if ( rc ) 675 goto destroy; 676 677 if ( check & CHECK_LOGLEVEL ) { 678 rc = 0; 679 goto destroy; 680 } 681 682 if ( check & CHECK_CONFIG ) { 683 fprintf( stderr, "config check succeeded\n" ); 684 685 check &= ~CHECK_CONFIG; 686 if ( check == CHECK_NONE ) { 687 rc = 0; 688 goto destroy; 689 } 690 } 691 692 if ( glue_sub_attach( 0 ) != 0 ) { 693 Debug( LDAP_DEBUG_ANY, 694 "subordinate config error\n" ); 695 696 goto destroy; 697 } 698 699 if ( slap_schema_check( ) != 0 ) { 700 Debug( LDAP_DEBUG_ANY, 701 "schema prep error\n" ); 702 703 goto destroy; 704 } 705 706 #ifdef HAVE_TLS 707 rc = ldap_pvt_tls_init( 1 ); 708 if( rc != 0) { 709 Debug( LDAP_DEBUG_ANY, 710 "main: TLS init failed: %d\n", 711 rc ); 712 rc = 1; 713 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); 714 goto destroy; 715 } 716 717 { 718 int opt = 1; 719 720 /* Force new ctx to be created */ 721 rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt ); 722 if( rc == 0 ) { 723 /* The ctx's refcount is bumped up here */ 724 ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx ); 725 load_extop( &slap_EXOP_START_TLS, 0, starttls_extop ); 726 } else if ( rc != LDAP_NOT_SUPPORTED ) { 727 char *errmsg = NULL; 728 ldap_get_option( slap_tls_ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &errmsg ); 729 Debug( LDAP_DEBUG_ANY, 730 "main: TLS init def ctx failed: %d %s\n", 731 rc, errmsg ? errmsg : "" ); 732 ldap_memfree( errmsg ); 733 rc = 1; 734 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); 735 goto destroy; 736 } 737 } 738 #endif 739 740 #ifdef HAVE_CYRUS_SASL 741 if( sasl_host == NULL ) { 742 sasl_host = ch_strdup( global_host ); 743 } 744 #endif 745 746 (void) SIGNAL( LDAP_SIGUSR1, slap_sig_wake ); 747 (void) SIGNAL( LDAP_SIGUSR2, slap_sig_shutdown ); 748 749 #ifdef SIGPIPE 750 (void) SIGNAL( SIGPIPE, SIG_IGN ); 751 #endif 752 #ifdef SIGHUP 753 (void) SIGNAL( SIGHUP, slap_sig_shutdown ); 754 #endif 755 (void) SIGNAL( SIGINT, slap_sig_shutdown ); 756 (void) SIGNAL( SIGTERM, slap_sig_shutdown ); 757 #ifdef SIGTRAP 758 (void) SIGNAL( SIGTRAP, slap_sig_shutdown ); 759 #endif 760 #ifdef LDAP_SIGCHLD 761 (void) SIGNAL( LDAP_SIGCHLD, wait4child ); 762 #endif 763 #ifdef SIGBREAK 764 /* SIGBREAK is generated when Ctrl-Break is pressed. */ 765 (void) SIGNAL( SIGBREAK, slap_sig_shutdown ); 766 #endif 767 768 #ifndef HAVE_WINSOCK 769 if ( !no_detach ) { 770 if ( lutil_pair( waitfds ) < 0 ) { 771 Debug( LDAP_DEBUG_ANY, 772 "main: lutil_pair failed: %d\n", 773 0 ); 774 rc = 1; 775 goto destroy; 776 } 777 pid = lutil_detach( no_detach, 0 ); 778 if ( pid ) { 779 char buf[4]; 780 rc = EXIT_SUCCESS; 781 close( waitfds[1] ); 782 if ( read( waitfds[0], buf, 1 ) != 1 ) 783 rc = EXIT_FAILURE; 784 _exit( rc ); 785 } else { 786 close( waitfds[0] ); 787 } 788 } 789 #endif /* HAVE_WINSOCK */ 790 791 #ifdef CSRIMALLOC 792 mal_leaktrace(1); 793 #endif 794 795 if ( slapd_pid_file != NULL ) { 796 FILE *fp = fopen( slapd_pid_file, "w" ); 797 798 if ( fp == NULL ) { 799 char ebuf[128]; 800 int save_errno = errno; 801 802 Debug( LDAP_DEBUG_ANY, "unable to open pid file " 803 "\"%s\": %d (%s)\n", 804 slapd_pid_file, 805 save_errno, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) ); 806 807 free( slapd_pid_file ); 808 slapd_pid_file = NULL; 809 810 rc = 1; 811 goto destroy; 812 } 813 fprintf( fp, "%d\n", (int) getpid() ); 814 fclose( fp ); 815 slapd_pid_file_unlink = 1; 816 } 817 818 if ( slapd_args_file != NULL ) { 819 FILE *fp = fopen( slapd_args_file, "w" ); 820 821 if ( fp == NULL ) { 822 char ebuf[128]; 823 int save_errno = errno; 824 825 Debug( LDAP_DEBUG_ANY, "unable to open args file " 826 "\"%s\": %d (%s)\n", 827 slapd_args_file, 828 save_errno, AC_STRERROR_R( save_errno, ebuf, sizeof(ebuf) ) ); 829 830 free( slapd_args_file ); 831 slapd_args_file = NULL; 832 833 rc = 1; 834 goto destroy; 835 } 836 837 for ( i = 0; i < g_argc; i++ ) { 838 fprintf( fp, "%s ", g_argv[i] ); 839 } 840 fprintf( fp, "\n" ); 841 fclose( fp ); 842 slapd_args_file_unlink = 1; 843 } 844 845 /* 846 * FIXME: moved here from slapd_daemon_task() 847 * because back-monitor db_open() needs it 848 */ 849 time( &starttime ); 850 851 connections_init(); 852 853 if ( slap_startup( NULL ) != 0 ) { 854 rc = 1; 855 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 ); 856 goto shutdown; 857 } 858 859 Debug( LDAP_DEBUG_ANY, "slapd starting\n" ); 860 861 #ifndef HAVE_WINSOCK 862 if ( !no_detach ) { 863 write( waitfds[1], "1", 1 ); 864 close( waitfds[1] ); 865 } 866 #endif 867 868 #ifdef HAVE_NT_EVENT_LOG 869 if (is_NT_Service) 870 lutil_LogStartedEvent( serverName, slap_debug, configfile ? 871 configfile : SLAPD_DEFAULT_CONFIGFILE , urls ); 872 #endif 873 874 rc = slapd_daemon(); 875 876 #ifdef HAVE_NT_SERVICE_MANAGER 877 /* Throw away the event that we used during the startup process. */ 878 if ( is_NT_Service ) 879 ldap_pvt_thread_cond_destroy( &started_event ); 880 #endif 881 882 shutdown: 883 /* remember an error during shutdown */ 884 rc |= slap_shutdown( NULL ); 885 886 destroy: 887 if ( check & CHECK_LOGLEVEL ) { 888 (void)loglevel_print( stdout ); 889 } 890 /* remember an error during destroy */ 891 rc |= slap_destroy(); 892 893 while ( !LDAP_STAILQ_EMPTY( &slap_sync_cookie )) { 894 scp = LDAP_STAILQ_FIRST( &slap_sync_cookie ); 895 LDAP_STAILQ_REMOVE_HEAD( &slap_sync_cookie, sc_next ); 896 ch_free( scp ); 897 } 898 899 #ifdef SLAPD_MODULES 900 module_kill(); 901 #endif 902 903 extops_kill(); 904 905 supported_feature_destroy(); 906 entry_info_destroy(); 907 908 stop: 909 #ifdef HAVE_NT_EVENT_LOG 910 if (is_NT_Service) 911 lutil_LogStoppedEvent( serverName ); 912 #endif 913 914 Debug( LDAP_DEBUG_ANY, "slapd stopped.\n" ); 915 916 917 #ifdef HAVE_NT_SERVICE_MANAGER 918 lutil_ReportShutdownComplete(); 919 #endif 920 921 #ifdef LOG_DEBUG 922 closelog(); 923 #endif 924 slapd_daemon_destroy(); 925 926 controls_destroy(); 927 928 filter_destroy(); 929 930 schema_destroy(); 931 932 lutil_passwd_destroy(); 933 934 #ifdef HAVE_TLS 935 if ( slap_tls_ld ) { 936 ldap_pvt_tls_ctx_free( slap_tls_ctx ); 937 ldap_unbind_ext( slap_tls_ld, NULL, NULL ); 938 } 939 ldap_pvt_tls_destroy(); 940 #endif 941 942 slap_sasl_regexp_destroy(); 943 944 if ( slapd_pid_file_unlink ) { 945 unlink( slapd_pid_file ); 946 } 947 if ( slapd_args_file_unlink ) { 948 unlink( slapd_args_file ); 949 } 950 951 config_destroy(); 952 953 if ( global_host ) 954 ch_free( global_host ); 955 956 /* kludge, get symbols referenced */ 957 ldap_tavl_free( NULL, NULL ); 958 959 #ifdef CSRIMALLOC 960 mal_dumpleaktrace( leakfile ); 961 #endif 962 963 ldap_pvt_thread_mutex_destroy( &logfile_mutex ); 964 MAIN_RETURN(rc); 965 } 966 967 968 #ifdef LDAP_SIGCHLD 969 970 /* 971 * Catch and discard terminated child processes, to avoid zombies. 972 */ 973 974 static RETSIGTYPE 975 wait4child( int sig ) 976 { 977 int save_errno = errno; 978 979 #ifdef WNOHANG 980 do 981 errno = 0; 982 #ifdef HAVE_WAITPID 983 while ( waitpid( (pid_t)-1, NULL, WNOHANG ) > 0 || errno == EINTR ); 984 #else 985 while ( wait3( NULL, WNOHANG, NULL ) > 0 || errno == EINTR ); 986 #endif 987 #else 988 (void) wait( NULL ); 989 #endif 990 (void) SIGNAL_REINSTALL( sig, wait4child ); 991 errno = save_errno; 992 } 993 994 #endif /* LDAP_SIGCHLD */ 995