1 /* $NetBSD: main.c,v 1.2 2020/08/11 13:15:39 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2020 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.2 2020/08/11 13:15:39 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; 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 {"slappasswd", slappasswd}, 84 {"slapschema", slapschema}, 85 {"slaptest", slaptest}, 86 {"slapauth", slapauth}, 87 {"slapacl", slapacl}, 88 /* NOTE: new tools must be added in chronological order, 89 * not in alphabetical order, because for backwards 90 * compatibility name[4] is used to identify the 91 * tools; so name[4]=='a' must refer to "slapadd" and 92 * not to "slapauth". Alphabetical order can be used 93 * for tools whose name[4] is not used yet */ 94 {NULL, NULL} 95 }; 96 97 /* 98 * when more than one slapd is running on one machine, each one might have 99 * it's own LOCAL for syslogging and must have its own pid/args files 100 */ 101 102 #ifndef HAVE_MKVERSION 103 const char Versionstr[] = 104 OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Server (slapd)"; 105 #endif 106 107 extern OverlayInit slap_oinfo[]; 108 extern BackendInfo slap_binfo[]; 109 110 #define CHECK_NONE 0x00 111 #define CHECK_CONFIG 0x01 112 #define CHECK_LOGLEVEL 0x02 113 static int check = CHECK_NONE; 114 static int version = 0; 115 116 void *slap_tls_ctx; 117 LDAP *slap_tls_ld; 118 119 static int 120 slapd_opt_slp( const char *val, void *arg ) 121 { 122 #ifdef HAVE_SLP 123 /* NULL is default */ 124 if ( val == NULL || *val == '(' || strcasecmp( val, "on" ) == 0 ) { 125 slapd_register_slp = 1; 126 slapd_slp_attrs = (val != NULL && *val == '(') ? val : NULL; 127 128 } else if ( strcasecmp( val, "off" ) == 0 ) { 129 slapd_register_slp = 0; 130 131 /* NOTE: add support for URL specification? */ 132 133 } else { 134 fprintf(stderr, "unrecognized value \"%s\" for SLP option\n", val ); 135 return -1; 136 } 137 138 return 0; 139 140 #else 141 fputs( "slapd: SLP support is not available\n", stderr ); 142 return 0; 143 #endif 144 } 145 146 /* 147 * Option helper structure: 148 * 149 * oh_nam is left-hand part of <option>[=<value>] 150 * oh_fnc is handler function 151 * oh_arg is an optional arg to oh_fnc 152 * oh_usage is the one-line usage string related to the option, 153 * which is assumed to start with <option>[=<value>] 154 * 155 * please leave valid options in the structure, and optionally #ifdef 156 * their processing inside the helper, so that reasonable and helpful 157 * error messages can be generated if a disabled option is requested. 158 */ 159 struct option_helper { 160 struct berval oh_name; 161 int (*oh_fnc)(const char *val, void *arg); 162 void *oh_arg; 163 const char *oh_usage; 164 } option_helpers[] = { 165 { BER_BVC("slp"), slapd_opt_slp, NULL, "slp[={on|off|(attrs)}] enable/disable SLP using (attrs)" }, 166 { BER_BVNULL, 0, NULL, NULL } 167 }; 168 169 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 170 #ifdef LOG_LOCAL4 171 int 172 parse_syslog_user( const char *arg, int *syslogUser ) 173 { 174 static slap_verbmasks syslogUsers[] = { 175 { BER_BVC( "LOCAL0" ), LOG_LOCAL0 }, 176 { BER_BVC( "LOCAL1" ), LOG_LOCAL1 }, 177 { BER_BVC( "LOCAL2" ), LOG_LOCAL2 }, 178 { BER_BVC( "LOCAL3" ), LOG_LOCAL3 }, 179 { BER_BVC( "LOCAL4" ), LOG_LOCAL4 }, 180 { BER_BVC( "LOCAL5" ), LOG_LOCAL5 }, 181 { BER_BVC( "LOCAL6" ), LOG_LOCAL6 }, 182 { BER_BVC( "LOCAL7" ), LOG_LOCAL7 }, 183 #ifdef LOG_USER 184 { BER_BVC( "USER" ), LOG_USER }, 185 #endif /* LOG_USER */ 186 #ifdef LOG_DAEMON 187 { BER_BVC( "DAEMON" ), LOG_DAEMON }, 188 #endif /* LOG_DAEMON */ 189 { BER_BVNULL, 0 } 190 }; 191 int i = verb_to_mask( arg, syslogUsers ); 192 193 if ( BER_BVISNULL( &syslogUsers[ i ].word ) ) { 194 Debug( LDAP_DEBUG_ANY, 195 "unrecognized syslog user \"%s\".\n", 196 arg, 0, 0 ); 197 return 1; 198 } 199 200 *syslogUser = syslogUsers[ i ].mask; 201 202 return 0; 203 } 204 #endif /* LOG_LOCAL4 */ 205 206 int 207 parse_syslog_level( const char *arg, int *levelp ) 208 { 209 static slap_verbmasks str2syslog_level[] = { 210 { BER_BVC( "EMERG" ), LOG_EMERG }, 211 { BER_BVC( "ALERT" ), LOG_ALERT }, 212 { BER_BVC( "CRIT" ), LOG_CRIT }, 213 { BER_BVC( "ERR" ), LOG_ERR }, 214 { BER_BVC( "WARNING" ), LOG_WARNING }, 215 { BER_BVC( "NOTICE" ), LOG_NOTICE }, 216 { BER_BVC( "INFO" ), LOG_INFO }, 217 { BER_BVC( "DEBUG" ), LOG_DEBUG }, 218 { BER_BVNULL, 0 } 219 }; 220 int i = verb_to_mask( arg, str2syslog_level ); 221 if ( BER_BVISNULL( &str2syslog_level[ i ].word ) ) { 222 Debug( LDAP_DEBUG_ANY, 223 "unknown syslog level \"%s\".\n", 224 arg, 0, 0 ); 225 return 1; 226 } 227 228 *levelp = str2syslog_level[ i ].mask; 229 230 return 0; 231 } 232 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 233 234 int 235 parse_debug_unknowns( char **unknowns, int *levelp ) 236 { 237 int i, level, rc = 0; 238 239 for ( i = 0; unknowns[ i ] != NULL; i++ ) { 240 level = 0; 241 if ( str2loglevel( unknowns[ i ], &level )) { 242 fprintf( stderr, 243 "unrecognized log level \"%s\"\n", unknowns[ i ] ); 244 rc = 1; 245 } else { 246 *levelp |= level; 247 } 248 } 249 return rc; 250 } 251 252 int 253 parse_debug_level( const char *arg, int *levelp, char ***unknowns ) 254 { 255 int level; 256 257 if ( arg && arg[ 0 ] != '-' && !isdigit( (unsigned char) arg[ 0 ] ) ) 258 { 259 int i; 260 char **levels; 261 262 levels = ldap_str2charray( arg, "," ); 263 264 for ( i = 0; levels[ i ] != NULL; i++ ) { 265 level = 0; 266 267 if ( str2loglevel( levels[ i ], &level ) ) { 268 /* remember this for later */ 269 ldap_charray_add( unknowns, levels[ i ] ); 270 fprintf( stderr, 271 "unrecognized log level \"%s\" (deferred)\n", 272 levels[ i ] ); 273 } else { 274 *levelp |= level; 275 } 276 } 277 278 ldap_charray_free( levels ); 279 280 } else { 281 int rc; 282 283 if ( arg[0] == '-' ) { 284 rc = lutil_atoix( &level, arg, 0 ); 285 } else { 286 unsigned ulevel; 287 288 rc = lutil_atoux( &ulevel, arg, 0 ); 289 level = (int)ulevel; 290 } 291 292 if ( rc ) { 293 fprintf( stderr, 294 "unrecognized log level " 295 "\"%s\"\n", arg ); 296 return 1; 297 } 298 299 if ( level == 0 ) { 300 *levelp = 0; 301 302 } else { 303 *levelp |= level; 304 } 305 } 306 307 return 0; 308 } 309 310 static void 311 usage( char *name ) 312 { 313 fprintf( stderr, 314 "usage: %s options\n", name ); 315 fprintf( stderr, 316 "\t-4\t\tIPv4 only\n" 317 "\t-6\t\tIPv6 only\n" 318 "\t-T {acl|add|auth|cat|dn|index|passwd|test}\n" 319 "\t\t\tRun in Tool mode\n" 320 "\t-c cookie\tSync cookie of consumer\n" 321 "\t-d level\tDebug level" "\n" 322 "\t-f filename\tConfiguration file\n" 323 "\t-F dir\tConfiguration directory\n" 324 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 325 "\t-g group\tGroup (id or name) to run as\n" 326 #endif 327 "\t-h URLs\t\tList of URLs to serve\n" 328 #ifdef SLAP_DEFAULT_SYSLOG_USER 329 "\t-l facility\tSyslog facility (default: LOCAL4)\n" 330 #endif 331 "\t-n serverName\tService name\n" 332 "\t-o <opt>[=val] generic means to specify options" ); 333 if ( !BER_BVISNULL( &option_helpers[0].oh_name ) ) { 334 int i; 335 336 fprintf( stderr, "; supported options:\n" ); 337 for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++) { 338 fprintf( stderr, "\t\t%s\n", option_helpers[i].oh_usage ); 339 } 340 } else { 341 fprintf( stderr, "\n" ); 342 } 343 fprintf( stderr, 344 #ifdef HAVE_CHROOT 345 "\t-r directory\tSandbox directory to chroot to\n" 346 #endif 347 "\t-s level\tSyslog level\n" 348 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 349 "\t-u user\t\tUser (id or name) to run as\n" 350 #endif 351 "\t-V\t\tprint version info (-VV exit afterwards, -VVV print\n" 352 "\t\t\tinfo about static overlays and backends)\n" 353 ); 354 } 355 356 #ifdef HAVE_NT_SERVICE_MANAGER 357 void WINAPI ServiceMain( DWORD argc, LPTSTR *argv ) 358 #else 359 int main( int argc, char **argv ) 360 #endif 361 { 362 int i, no_detach = 0; 363 int rc = 1; 364 char *urls = NULL; 365 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 366 char *username = NULL; 367 char *groupname = NULL; 368 #endif 369 #if defined(HAVE_CHROOT) 370 char *sandbox = NULL; 371 #endif 372 #ifdef SLAP_DEFAULT_SYSLOG_USER 373 int syslogUser = SLAP_DEFAULT_SYSLOG_USER; 374 #endif 375 376 #ifndef HAVE_WINSOCK 377 int pid, waitfds[2]; 378 #endif 379 int g_argc = argc; 380 char **g_argv = argv; 381 382 char *configfile = NULL; 383 char *configdir = NULL; 384 char *serverName; 385 int serverMode = SLAP_SERVER_MODE; 386 387 struct sync_cookie *scp = NULL; 388 struct sync_cookie *scp_entry = NULL; 389 390 char **debug_unknowns = NULL; 391 char **syslog_unknowns = NULL; 392 393 char *serverNamePrefix = ""; 394 size_t l; 395 396 int slapd_pid_file_unlink = 0, slapd_args_file_unlink = 0; 397 int firstopt = 1; 398 399 #ifdef CSRIMALLOC 400 FILE *leakfile; 401 if( ( leakfile = fopen( "slapd.leak", "w" )) == NULL ) { 402 leakfile = stderr; 403 } 404 #endif 405 406 slap_sl_mem_init(); 407 408 409 (void) ldap_pvt_thread_initialize(); 410 411 serverName = lutil_progname( "slapd", argc, argv ); 412 413 if ( strcmp( serverName, "slapd" ) ) { 414 #ifdef DEBUG_CLOSE 415 extern void slapd_debug_close(); 416 slapd_debug_close(); 417 #endif 418 for (i=0; tools[i].name; i++) { 419 if ( !strcmp( serverName, tools[i].name ) ) { 420 rc = tools[i].func(argc, argv); 421 MAIN_RETURN(rc); 422 } 423 } 424 } 425 426 #ifdef HAVE_NT_SERVICE_MANAGER 427 { 428 int *ip; 429 char *newConfigFile; 430 char *newConfigDir; 431 char *newUrls; 432 char *regService = NULL; 433 434 if ( is_NT_Service ) { 435 lutil_CommenceStartupProcessing( serverName, slap_sig_shutdown ); 436 if ( strcmp(serverName, SERVICE_NAME) ) 437 regService = serverName; 438 } 439 440 ip = (int*)lutil_getRegParam( regService, "DebugLevel" ); 441 if ( ip != NULL ) { 442 slap_debug = *ip; 443 Debug( LDAP_DEBUG_ANY, 444 "new debug level from registry is: %d\n", slap_debug, 0, 0 ); 445 } 446 447 newUrls = (char *) lutil_getRegParam(regService, "Urls"); 448 if (newUrls) { 449 if (urls) 450 ch_free(urls); 451 452 urls = ch_strdup(newUrls); 453 Debug(LDAP_DEBUG_ANY, "new urls from registry: %s\n", 454 urls, 0, 0); 455 } 456 457 newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" ); 458 if ( newConfigFile != NULL ) { 459 configfile = ch_strdup(newConfigFile); 460 Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile, 0, 0 ); 461 } 462 463 newConfigDir = (char*)lutil_getRegParam( regService, "ConfigDir" ); 464 if ( newConfigDir != NULL ) { 465 configdir = ch_strdup(newConfigDir); 466 Debug ( LDAP_DEBUG_ANY, "new config dir from registry is: %s\n", configdir, 0, 0 ); 467 } 468 } 469 #endif 470 471 while ( (i = getopt( argc, argv, 472 "c:d:f:F:h:n:o:s:tT:V" 473 #ifdef LDAP_PF_INET6 474 "46" 475 #endif 476 #ifdef HAVE_CHROOT 477 "r:" 478 #endif 479 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 480 "S:" 481 #ifdef LOG_LOCAL4 482 "l:" 483 #endif 484 #endif 485 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 486 "u:g:" 487 #endif 488 )) != EOF ) { 489 switch ( i ) { 490 #ifdef LDAP_PF_INET6 491 case '4': 492 slap_inet4or6 = AF_INET; 493 break; 494 case '6': 495 slap_inet4or6 = AF_INET6; 496 break; 497 #endif 498 499 case 'h': /* listen URLs */ 500 if ( urls != NULL ) free( urls ); 501 urls = ch_strdup( optarg ); 502 break; 503 504 case 'c': /* provide sync cookie, override if exist in replica */ 505 scp = (struct sync_cookie *) ch_calloc( 1, 506 sizeof( struct sync_cookie )); 507 ber_str2bv( optarg, 0, 1, &scp->octet_str ); 508 509 /* This only parses out the rid at this point */ 510 slap_parse_sync_cookie( scp, NULL ); 511 512 if ( scp->rid == -1 ) { 513 Debug( LDAP_DEBUG_ANY, 514 "main: invalid cookie \"%s\"\n", 515 optarg, 0, 0 ); 516 slap_sync_cookie_free( scp, 1 ); 517 goto destroy; 518 } 519 520 LDAP_STAILQ_FOREACH( scp_entry, &slap_sync_cookie, sc_next ) { 521 if ( scp->rid == scp_entry->rid ) { 522 Debug( LDAP_DEBUG_ANY, 523 "main: duplicated replica id in cookies\n", 524 0, 0, 0 ); 525 slap_sync_cookie_free( scp, 1 ); 526 goto destroy; 527 } 528 } 529 LDAP_STAILQ_INSERT_TAIL( &slap_sync_cookie, scp, sc_next ); 530 break; 531 532 case 'd': { /* set debug level and 'do not detach' flag */ 533 int level = 0; 534 535 if ( strcmp( optarg, "?" ) == 0 ) { 536 check |= CHECK_LOGLEVEL; 537 break; 538 } 539 540 no_detach = 1; 541 if ( parse_debug_level( optarg, &level, &debug_unknowns ) ) { 542 goto destroy; 543 } 544 #ifdef LDAP_DEBUG 545 slap_debug |= level; 546 #else 547 if ( level != 0 ) 548 fputs( "must compile with LDAP_DEBUG for debugging\n", 549 stderr ); 550 #endif 551 } break; 552 553 case 'f': /* read config file */ 554 configfile = ch_strdup( optarg ); 555 break; 556 557 case 'F': /* use config dir */ 558 configdir = ch_strdup( optarg ); 559 break; 560 561 case 'o': { 562 char *val = strchr( optarg, '=' ); 563 struct berval opt; 564 565 opt.bv_val = optarg; 566 567 if ( val ) { 568 opt.bv_len = ( val - optarg ); 569 val++; 570 571 } else { 572 opt.bv_len = strlen( optarg ); 573 } 574 575 for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++ ) { 576 if ( ber_bvstrcasecmp( &option_helpers[i].oh_name, &opt ) == 0 ) { 577 assert( option_helpers[i].oh_fnc != NULL ); 578 if ( (*option_helpers[i].oh_fnc)( val, option_helpers[i].oh_arg ) == -1 ) { 579 /* we assume the option parsing helper 580 * issues appropriate and self-explanatory 581 * error messages... */ 582 goto stop; 583 } 584 break; 585 } 586 } 587 588 if ( BER_BVISNULL( &option_helpers[i].oh_name ) ) { 589 goto unhandled_option; 590 } 591 break; 592 } 593 594 case 's': /* set syslog level */ 595 if ( strcmp( optarg, "?" ) == 0 ) { 596 check |= CHECK_LOGLEVEL; 597 break; 598 } 599 600 if ( parse_debug_level( optarg, &ldap_syslog, &syslog_unknowns ) ) { 601 goto destroy; 602 } 603 break; 604 605 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 606 case 'S': 607 if ( parse_syslog_level( optarg, &ldap_syslog_level ) ) { 608 goto destroy; 609 } 610 break; 611 612 #ifdef LOG_LOCAL4 613 case 'l': /* set syslog local user */ 614 if ( parse_syslog_user( optarg, &syslogUser ) ) { 615 goto destroy; 616 } 617 break; 618 #endif 619 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 620 621 #ifdef HAVE_CHROOT 622 case 'r': 623 if( sandbox ) free(sandbox); 624 sandbox = ch_strdup( optarg ); 625 break; 626 #endif 627 628 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 629 case 'u': /* user name */ 630 if( username ) free(username); 631 username = ch_strdup( optarg ); 632 break; 633 634 case 'g': /* group name */ 635 if( groupname ) free(groupname); 636 groupname = ch_strdup( optarg ); 637 break; 638 #endif /* SETUID && GETUID */ 639 640 case 'n': /* NT service name */ 641 serverName = ch_strdup( optarg ); 642 break; 643 644 case 't': 645 /* deprecated; use slaptest instead */ 646 fprintf( stderr, "option -t deprecated; " 647 "use slaptest command instead\n" ); 648 check |= CHECK_CONFIG; 649 break; 650 651 case 'V': 652 version++; 653 break; 654 655 case 'T': 656 if ( firstopt == 0 ) { 657 fprintf( stderr, "warning: \"-T %s\" " 658 "should be the first option.\n", 659 optarg ); 660 } 661 662 #ifdef DEBUG_CLOSE 663 extern void slapd_debug_close(); 664 slapd_debug_close(); 665 #endif 666 /* try full option string first */ 667 for ( i = 0; tools[i].name; i++ ) { 668 if ( strcmp( optarg, &tools[i].name[4] ) == 0 ) { 669 rc = tools[i].func( argc, argv ); 670 MAIN_RETURN( rc ); 671 } 672 } 673 674 /* try bits of option string (backward compatibility for single char) */ 675 l = strlen( optarg ); 676 for ( i = 0; tools[i].name; i++ ) { 677 if ( strncmp( optarg, &tools[i].name[4], l ) == 0 ) { 678 rc = tools[i].func( argc, argv ); 679 MAIN_RETURN( rc ); 680 } 681 } 682 683 /* issue error */ 684 serverName = optarg; 685 serverNamePrefix = "slap"; 686 fprintf( stderr, "program name \"%s%s\" unrecognized; " 687 "aborting...\n", serverNamePrefix, serverName ); 688 /* FALLTHRU */ 689 default: 690 unhandled_option:; 691 usage( argv[0] ); 692 rc = 1; 693 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 ); 694 goto stop; 695 } 696 697 if ( firstopt ) { 698 firstopt = 0; 699 } 700 } 701 702 if ( optind != argc ) 703 goto unhandled_option; 704 705 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug); 706 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug); 707 ldif_debug = slap_debug; 708 709 if ( version ) { 710 fprintf( stderr, "%s\n", Versionstr ); 711 if ( version > 2 ) { 712 if ( slap_oinfo[0].ov_type ) { 713 fprintf( stderr, "Included static overlays:\n"); 714 for ( i= 0 ; slap_oinfo[i].ov_type; i++ ) { 715 fprintf( stderr, " %s\n", slap_oinfo[i].ov_type ); 716 } 717 } 718 if ( slap_binfo[0].bi_type ) { 719 fprintf( stderr, "Included static backends:\n"); 720 for ( i= 0 ; slap_binfo[i].bi_type; i++ ) { 721 fprintf( stderr, " %s\n", slap_binfo[i].bi_type ); 722 } 723 } 724 } 725 726 if ( version > 1 ) goto stop; 727 } 728 729 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 730 { 731 char *logName; 732 #ifdef HAVE_EBCDIC 733 logName = ch_strdup( serverName ); 734 __atoe( logName ); 735 #else 736 logName = serverName; 737 #endif 738 739 #ifdef LOG_LOCAL4 740 openlog( logName, OPENLOG_OPTIONS, syslogUser ); 741 #elif defined LOG_DEBUG 742 openlog( logName, OPENLOG_OPTIONS ); 743 #endif 744 #ifdef HAVE_EBCDIC 745 free( logName ); 746 #endif 747 } 748 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 749 750 Debug( LDAP_DEBUG_ANY, "%s", Versionstr, 0, 0 ); 751 752 global_host = ldap_pvt_get_fqdn( NULL ); 753 ber_str2bv( global_host, 0, 0, &global_host_bv ); 754 755 if( check == CHECK_NONE && slapd_daemon_init( urls ) != 0 ) { 756 rc = 1; 757 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 ); 758 goto stop; 759 } 760 761 #if defined(HAVE_CHROOT) 762 if ( sandbox ) { 763 if ( chdir( sandbox ) ) { 764 perror("chdir"); 765 rc = 1; 766 goto stop; 767 } 768 if ( chroot( sandbox ) ) { 769 perror("chroot"); 770 rc = 1; 771 goto stop; 772 } 773 if ( chdir( "/" ) ) { 774 perror("chdir"); 775 rc = 1; 776 goto stop; 777 } 778 } 779 #endif 780 781 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 782 if ( username != NULL || groupname != NULL ) { 783 slap_init_user( username, groupname ); 784 } 785 #endif 786 787 extops_init(); 788 lutil_passwd_init(); 789 790 #ifdef HAVE_TLS 791 rc = ldap_create( &slap_tls_ld ); 792 if ( rc ) { 793 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); 794 goto destroy; 795 } 796 /* Library defaults to full certificate checking. This is correct when 797 * a client is verifying a server because all servers should have a 798 * valid cert. But few clients have valid certs, so we want our default 799 * to be no checking. The config file can override this as usual. 800 */ 801 rc = LDAP_OPT_X_TLS_NEVER; 802 (void) ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &rc ); 803 #endif 804 805 rc = slap_init( serverMode, serverName ); 806 if ( rc ) { 807 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 ); 808 goto destroy; 809 } 810 811 if ( read_config( configfile, configdir ) != 0 ) { 812 rc = 1; 813 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 ); 814 815 if ( check & CHECK_CONFIG ) { 816 fprintf( stderr, "config check failed\n" ); 817 } 818 819 goto destroy; 820 } 821 822 if ( debug_unknowns ) { 823 rc = parse_debug_unknowns( debug_unknowns, &slap_debug ); 824 ldap_charray_free( debug_unknowns ); 825 debug_unknowns = NULL; 826 if ( rc ) 827 goto destroy; 828 } 829 if ( syslog_unknowns ) { 830 rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog ); 831 ldap_charray_free( syslog_unknowns ); 832 syslog_unknowns = NULL; 833 if ( rc ) 834 goto destroy; 835 } 836 837 if ( check & CHECK_LOGLEVEL ) { 838 rc = 0; 839 goto destroy; 840 } 841 842 if ( check & CHECK_CONFIG ) { 843 fprintf( stderr, "config check succeeded\n" ); 844 845 check &= ~CHECK_CONFIG; 846 if ( check == CHECK_NONE ) { 847 rc = 0; 848 goto destroy; 849 } 850 } 851 852 if ( glue_sub_attach( 0 ) != 0 ) { 853 Debug( LDAP_DEBUG_ANY, 854 "subordinate config error\n", 855 0, 0, 0 ); 856 857 goto destroy; 858 } 859 860 if ( slap_schema_check( ) != 0 ) { 861 Debug( LDAP_DEBUG_ANY, 862 "schema prep error\n", 863 0, 0, 0 ); 864 865 goto destroy; 866 } 867 868 #ifdef HAVE_TLS 869 rc = ldap_pvt_tls_init(); 870 if( rc != 0) { 871 Debug( LDAP_DEBUG_ANY, 872 "main: TLS init failed: %d\n", 873 rc, 0, 0 ); 874 rc = 1; 875 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); 876 goto destroy; 877 } 878 879 { 880 int opt = 1; 881 882 /* Force new ctx to be created */ 883 rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt ); 884 if( rc == 0 ) { 885 /* The ctx's refcount is bumped up here */ 886 ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx ); 887 load_extop( &slap_EXOP_START_TLS, 0, starttls_extop ); 888 } else if ( rc != LDAP_NOT_SUPPORTED ) { 889 Debug( LDAP_DEBUG_ANY, 890 "main: TLS init def ctx failed: %d\n", 891 rc, 0, 0 ); 892 rc = 1; 893 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); 894 goto destroy; 895 } 896 } 897 #endif 898 899 #ifdef HAVE_CYRUS_SASL 900 if( sasl_host == NULL ) { 901 sasl_host = ch_strdup( global_host ); 902 } 903 #endif 904 905 (void) SIGNAL( LDAP_SIGUSR1, slap_sig_wake ); 906 (void) SIGNAL( LDAP_SIGUSR2, slap_sig_shutdown ); 907 908 #ifdef SIGPIPE 909 (void) SIGNAL( SIGPIPE, SIG_IGN ); 910 #endif 911 #ifdef SIGHUP 912 (void) SIGNAL( SIGHUP, slap_sig_shutdown ); 913 #endif 914 (void) SIGNAL( SIGINT, slap_sig_shutdown ); 915 (void) SIGNAL( SIGTERM, slap_sig_shutdown ); 916 #ifdef SIGTRAP 917 (void) SIGNAL( SIGTRAP, slap_sig_shutdown ); 918 #endif 919 #ifdef LDAP_SIGCHLD 920 (void) SIGNAL( LDAP_SIGCHLD, wait4child ); 921 #endif 922 #ifdef SIGBREAK 923 /* SIGBREAK is generated when Ctrl-Break is pressed. */ 924 (void) SIGNAL( SIGBREAK, slap_sig_shutdown ); 925 #endif 926 927 #ifndef HAVE_WINSOCK 928 if ( !no_detach ) { 929 if ( lutil_pair( waitfds ) < 0 ) { 930 Debug( LDAP_DEBUG_ANY, 931 "main: lutil_pair failed: %d\n", 932 0, 0, 0 ); 933 rc = 1; 934 goto destroy; 935 } 936 pid = lutil_detach( no_detach, 0 ); 937 if ( pid ) { 938 char buf[4]; 939 rc = EXIT_SUCCESS; 940 close( waitfds[1] ); 941 if ( read( waitfds[0], buf, 1 ) != 1 ) 942 rc = EXIT_FAILURE; 943 _exit( rc ); 944 } else { 945 close( waitfds[0] ); 946 } 947 } 948 #endif /* HAVE_WINSOCK */ 949 950 #ifdef CSRIMALLOC 951 mal_leaktrace(1); 952 #endif 953 954 if ( slapd_pid_file != NULL ) { 955 FILE *fp = fopen( slapd_pid_file, "w" ); 956 957 if ( fp == NULL ) { 958 int save_errno = errno; 959 960 Debug( LDAP_DEBUG_ANY, "unable to open pid file " 961 "\"%s\": %d (%s)\n", 962 slapd_pid_file, 963 save_errno, strerror( save_errno ) ); 964 965 free( slapd_pid_file ); 966 slapd_pid_file = NULL; 967 968 rc = 1; 969 goto destroy; 970 } 971 fprintf( fp, "%d\n", (int) getpid() ); 972 fclose( fp ); 973 slapd_pid_file_unlink = 1; 974 } 975 976 if ( slapd_args_file != NULL ) { 977 FILE *fp = fopen( slapd_args_file, "w" ); 978 979 if ( fp == NULL ) { 980 int save_errno = errno; 981 982 Debug( LDAP_DEBUG_ANY, "unable to open args file " 983 "\"%s\": %d (%s)\n", 984 slapd_args_file, 985 save_errno, strerror( save_errno ) ); 986 987 free( slapd_args_file ); 988 slapd_args_file = NULL; 989 990 rc = 1; 991 goto destroy; 992 } 993 994 for ( i = 0; i < g_argc; i++ ) { 995 fprintf( fp, "%s ", g_argv[i] ); 996 } 997 fprintf( fp, "\n" ); 998 fclose( fp ); 999 slapd_args_file_unlink = 1; 1000 } 1001 1002 /* 1003 * FIXME: moved here from slapd_daemon_task() 1004 * because back-monitor db_open() needs it 1005 */ 1006 time( &starttime ); 1007 1008 connections_init(); 1009 1010 if ( slap_startup( NULL ) != 0 ) { 1011 rc = 1; 1012 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 ); 1013 goto shutdown; 1014 } 1015 1016 Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 ); 1017 1018 #ifndef HAVE_WINSOCK 1019 if ( !no_detach ) { 1020 write( waitfds[1], "1", 1 ); 1021 close( waitfds[1] ); 1022 } 1023 #endif 1024 1025 #ifdef HAVE_NT_EVENT_LOG 1026 if (is_NT_Service) 1027 lutil_LogStartedEvent( serverName, slap_debug, configfile ? 1028 configfile : SLAPD_DEFAULT_CONFIGFILE , urls ); 1029 #endif 1030 1031 rc = slapd_daemon(); 1032 1033 #ifdef HAVE_NT_SERVICE_MANAGER 1034 /* Throw away the event that we used during the startup process. */ 1035 if ( is_NT_Service ) 1036 ldap_pvt_thread_cond_destroy( &started_event ); 1037 #endif 1038 1039 shutdown: 1040 /* remember an error during shutdown */ 1041 rc |= slap_shutdown( NULL ); 1042 1043 destroy: 1044 if ( check & CHECK_LOGLEVEL ) { 1045 (void)loglevel_print( stdout ); 1046 } 1047 /* remember an error during destroy */ 1048 rc |= slap_destroy(); 1049 1050 while ( !LDAP_STAILQ_EMPTY( &slap_sync_cookie )) { 1051 scp = LDAP_STAILQ_FIRST( &slap_sync_cookie ); 1052 LDAP_STAILQ_REMOVE_HEAD( &slap_sync_cookie, sc_next ); 1053 ch_free( scp ); 1054 } 1055 1056 #ifdef SLAPD_MODULES 1057 module_kill(); 1058 #endif 1059 1060 extops_kill(); 1061 1062 supported_feature_destroy(); 1063 entry_info_destroy(); 1064 1065 stop: 1066 #ifdef HAVE_NT_EVENT_LOG 1067 if (is_NT_Service) 1068 lutil_LogStoppedEvent( serverName ); 1069 #endif 1070 1071 Debug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 ); 1072 1073 1074 #ifdef HAVE_NT_SERVICE_MANAGER 1075 lutil_ReportShutdownComplete(); 1076 #endif 1077 1078 #ifdef LOG_DEBUG 1079 closelog(); 1080 #endif 1081 slapd_daemon_destroy(); 1082 1083 controls_destroy(); 1084 1085 filter_destroy(); 1086 1087 schema_destroy(); 1088 1089 lutil_passwd_destroy(); 1090 1091 #ifdef HAVE_TLS 1092 if ( slap_tls_ld ) { 1093 ldap_pvt_tls_ctx_free( slap_tls_ctx ); 1094 ldap_unbind_ext( slap_tls_ld, NULL, NULL ); 1095 } 1096 ldap_pvt_tls_destroy(); 1097 #endif 1098 1099 slap_sasl_regexp_destroy(); 1100 1101 if ( slapd_pid_file_unlink ) { 1102 unlink( slapd_pid_file ); 1103 } 1104 if ( slapd_args_file_unlink ) { 1105 unlink( slapd_args_file ); 1106 } 1107 1108 config_destroy(); 1109 1110 if ( configfile ) 1111 ch_free( configfile ); 1112 if ( configdir ) 1113 ch_free( configdir ); 1114 if ( urls ) 1115 ch_free( urls ); 1116 if ( global_host ) 1117 ch_free( global_host ); 1118 1119 /* kludge, get symbols referenced */ 1120 tavl_free( NULL, NULL ); 1121 1122 #ifdef CSRIMALLOC 1123 mal_dumpleaktrace( leakfile ); 1124 #endif 1125 1126 MAIN_RETURN(rc); 1127 } 1128 1129 1130 #ifdef LDAP_SIGCHLD 1131 1132 /* 1133 * Catch and discard terminated child processes, to avoid zombies. 1134 */ 1135 1136 static RETSIGTYPE 1137 wait4child( int sig ) 1138 { 1139 int save_errno = errno; 1140 1141 #ifdef WNOHANG 1142 do 1143 errno = 0; 1144 #ifdef HAVE_WAITPID 1145 while ( waitpid( (pid_t)-1, NULL, WNOHANG ) > 0 || errno == EINTR ); 1146 #else 1147 while ( wait3( NULL, WNOHANG, NULL ) > 0 || errno == EINTR ); 1148 #endif 1149 #else 1150 (void) wait( NULL ); 1151 #endif 1152 (void) SIGNAL_REINSTALL( sig, wait4child ); 1153 errno = save_errno; 1154 } 1155 1156 #endif /* LDAP_SIGCHLD */ 1157