1 /* $NetBSD: main.c,v 1.1.1.7 2018/02/06 01:53:13 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1998-2017 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.1.1.7 2018/02/06 01:53:13 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 (void) ldap_pvt_thread_initialize(); 409 410 serverName = lutil_progname( "slapd", argc, argv ); 411 412 if ( strcmp( serverName, "slapd" ) ) { 413 for (i=0; tools[i].name; i++) { 414 if ( !strcmp( serverName, tools[i].name ) ) { 415 rc = tools[i].func(argc, argv); 416 MAIN_RETURN(rc); 417 } 418 } 419 } 420 421 #ifdef HAVE_NT_SERVICE_MANAGER 422 { 423 int *ip; 424 char *newConfigFile; 425 char *newConfigDir; 426 char *newUrls; 427 char *regService = NULL; 428 429 if ( is_NT_Service ) { 430 lutil_CommenceStartupProcessing( serverName, slap_sig_shutdown ); 431 if ( strcmp(serverName, SERVICE_NAME) ) 432 regService = serverName; 433 } 434 435 ip = (int*)lutil_getRegParam( regService, "DebugLevel" ); 436 if ( ip != NULL ) { 437 slap_debug = *ip; 438 Debug( LDAP_DEBUG_ANY, 439 "new debug level from registry is: %d\n", slap_debug, 0, 0 ); 440 } 441 442 newUrls = (char *) lutil_getRegParam(regService, "Urls"); 443 if (newUrls) { 444 if (urls) 445 ch_free(urls); 446 447 urls = ch_strdup(newUrls); 448 Debug(LDAP_DEBUG_ANY, "new urls from registry: %s\n", 449 urls, 0, 0); 450 } 451 452 newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" ); 453 if ( newConfigFile != NULL ) { 454 configfile = ch_strdup(newConfigFile); 455 Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile, 0, 0 ); 456 } 457 458 newConfigDir = (char*)lutil_getRegParam( regService, "ConfigDir" ); 459 if ( newConfigDir != NULL ) { 460 configdir = ch_strdup(newConfigDir); 461 Debug ( LDAP_DEBUG_ANY, "new config dir from registry is: %s\n", configdir, 0, 0 ); 462 } 463 } 464 #endif 465 466 while ( (i = getopt( argc, argv, 467 "c:d:f:F:h:n:o:s:tT:V" 468 #ifdef LDAP_PF_INET6 469 "46" 470 #endif 471 #ifdef HAVE_CHROOT 472 "r:" 473 #endif 474 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 475 "S:" 476 #ifdef LOG_LOCAL4 477 "l:" 478 #endif 479 #endif 480 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 481 "u:g:" 482 #endif 483 )) != EOF ) { 484 switch ( i ) { 485 #ifdef LDAP_PF_INET6 486 case '4': 487 slap_inet4or6 = AF_INET; 488 break; 489 case '6': 490 slap_inet4or6 = AF_INET6; 491 break; 492 #endif 493 494 case 'h': /* listen URLs */ 495 if ( urls != NULL ) free( urls ); 496 urls = ch_strdup( optarg ); 497 break; 498 499 case 'c': /* provide sync cookie, override if exist in replica */ 500 scp = (struct sync_cookie *) ch_calloc( 1, 501 sizeof( struct sync_cookie )); 502 ber_str2bv( optarg, 0, 1, &scp->octet_str ); 503 504 /* This only parses out the rid at this point */ 505 slap_parse_sync_cookie( scp, NULL ); 506 507 if ( scp->rid == -1 ) { 508 Debug( LDAP_DEBUG_ANY, 509 "main: invalid cookie \"%s\"\n", 510 optarg, 0, 0 ); 511 slap_sync_cookie_free( scp, 1 ); 512 goto destroy; 513 } 514 515 LDAP_STAILQ_FOREACH( scp_entry, &slap_sync_cookie, sc_next ) { 516 if ( scp->rid == scp_entry->rid ) { 517 Debug( LDAP_DEBUG_ANY, 518 "main: duplicated replica id in cookies\n", 519 0, 0, 0 ); 520 slap_sync_cookie_free( scp, 1 ); 521 goto destroy; 522 } 523 } 524 LDAP_STAILQ_INSERT_TAIL( &slap_sync_cookie, scp, sc_next ); 525 break; 526 527 case 'd': { /* set debug level and 'do not detach' flag */ 528 int level = 0; 529 530 if ( strcmp( optarg, "?" ) == 0 ) { 531 check |= CHECK_LOGLEVEL; 532 break; 533 } 534 535 no_detach = 1; 536 if ( parse_debug_level( optarg, &level, &debug_unknowns ) ) { 537 goto destroy; 538 } 539 #ifdef LDAP_DEBUG 540 slap_debug |= level; 541 #else 542 if ( level != 0 ) 543 fputs( "must compile with LDAP_DEBUG for debugging\n", 544 stderr ); 545 #endif 546 } break; 547 548 case 'f': /* read config file */ 549 configfile = ch_strdup( optarg ); 550 break; 551 552 case 'F': /* use config dir */ 553 configdir = ch_strdup( optarg ); 554 break; 555 556 case 'o': { 557 char *val = strchr( optarg, '=' ); 558 struct berval opt; 559 560 opt.bv_val = optarg; 561 562 if ( val ) { 563 opt.bv_len = ( val - optarg ); 564 val++; 565 566 } else { 567 opt.bv_len = strlen( optarg ); 568 } 569 570 for ( i = 0; !BER_BVISNULL( &option_helpers[i].oh_name ); i++ ) { 571 if ( ber_bvstrcasecmp( &option_helpers[i].oh_name, &opt ) == 0 ) { 572 assert( option_helpers[i].oh_fnc != NULL ); 573 if ( (*option_helpers[i].oh_fnc)( val, option_helpers[i].oh_arg ) == -1 ) { 574 /* we assume the option parsing helper 575 * issues appropriate and self-explanatory 576 * error messages... */ 577 goto stop; 578 } 579 break; 580 } 581 } 582 583 if ( BER_BVISNULL( &option_helpers[i].oh_name ) ) { 584 goto unhandled_option; 585 } 586 break; 587 } 588 589 case 's': /* set syslog level */ 590 if ( strcmp( optarg, "?" ) == 0 ) { 591 check |= CHECK_LOGLEVEL; 592 break; 593 } 594 595 if ( parse_debug_level( optarg, &ldap_syslog, &syslog_unknowns ) ) { 596 goto destroy; 597 } 598 break; 599 600 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 601 case 'S': 602 if ( parse_syslog_level( optarg, &ldap_syslog_level ) ) { 603 goto destroy; 604 } 605 break; 606 607 #ifdef LOG_LOCAL4 608 case 'l': /* set syslog local user */ 609 if ( parse_syslog_user( optarg, &syslogUser ) ) { 610 goto destroy; 611 } 612 break; 613 #endif 614 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 615 616 #ifdef HAVE_CHROOT 617 case 'r': 618 if( sandbox ) free(sandbox); 619 sandbox = ch_strdup( optarg ); 620 break; 621 #endif 622 623 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 624 case 'u': /* user name */ 625 if( username ) free(username); 626 username = ch_strdup( optarg ); 627 break; 628 629 case 'g': /* group name */ 630 if( groupname ) free(groupname); 631 groupname = ch_strdup( optarg ); 632 break; 633 #endif /* SETUID && GETUID */ 634 635 case 'n': /* NT service name */ 636 serverName = ch_strdup( optarg ); 637 break; 638 639 case 't': 640 /* deprecated; use slaptest instead */ 641 fprintf( stderr, "option -t deprecated; " 642 "use slaptest command instead\n" ); 643 check |= CHECK_CONFIG; 644 break; 645 646 case 'V': 647 version++; 648 break; 649 650 case 'T': 651 if ( firstopt == 0 ) { 652 fprintf( stderr, "warning: \"-T %s\" " 653 "should be the first option.\n", 654 optarg ); 655 } 656 657 /* try full option string first */ 658 for ( i = 0; tools[i].name; i++ ) { 659 if ( strcmp( optarg, &tools[i].name[4] ) == 0 ) { 660 rc = tools[i].func( argc, argv ); 661 MAIN_RETURN( rc ); 662 } 663 } 664 665 /* try bits of option string (backward compatibility for single char) */ 666 l = strlen( optarg ); 667 for ( i = 0; tools[i].name; i++ ) { 668 if ( strncmp( optarg, &tools[i].name[4], l ) == 0 ) { 669 rc = tools[i].func( argc, argv ); 670 MAIN_RETURN( rc ); 671 } 672 } 673 674 /* issue error */ 675 serverName = optarg; 676 serverNamePrefix = "slap"; 677 fprintf( stderr, "program name \"%s%s\" unrecognized; " 678 "aborting...\n", serverNamePrefix, serverName ); 679 /* FALLTHRU */ 680 default: 681 unhandled_option:; 682 usage( argv[0] ); 683 rc = 1; 684 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 ); 685 goto stop; 686 } 687 688 if ( firstopt ) { 689 firstopt = 0; 690 } 691 } 692 693 if ( optind != argc ) 694 goto unhandled_option; 695 696 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug); 697 ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug); 698 ldif_debug = slap_debug; 699 700 if ( version ) { 701 fprintf( stderr, "%s\n", Versionstr ); 702 if ( version > 2 ) { 703 if ( slap_oinfo[0].ov_type ) { 704 fprintf( stderr, "Included static overlays:\n"); 705 for ( i= 0 ; slap_oinfo[i].ov_type; i++ ) { 706 fprintf( stderr, " %s\n", slap_oinfo[i].ov_type ); 707 } 708 } 709 if ( slap_binfo[0].bi_type ) { 710 fprintf( stderr, "Included static backends:\n"); 711 for ( i= 0 ; slap_binfo[i].bi_type; i++ ) { 712 fprintf( stderr, " %s\n", slap_binfo[i].bi_type ); 713 } 714 } 715 } 716 717 if ( version > 1 ) goto stop; 718 } 719 720 #if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG) 721 { 722 char *logName; 723 #ifdef HAVE_EBCDIC 724 logName = ch_strdup( serverName ); 725 __atoe( logName ); 726 #else 727 logName = serverName; 728 #endif 729 730 #ifdef LOG_LOCAL4 731 openlog( logName, OPENLOG_OPTIONS, syslogUser ); 732 #elif defined LOG_DEBUG 733 openlog( logName, OPENLOG_OPTIONS ); 734 #endif 735 #ifdef HAVE_EBCDIC 736 free( logName ); 737 #endif 738 } 739 #endif /* LDAP_DEBUG && LDAP_SYSLOG */ 740 741 Debug( LDAP_DEBUG_ANY, "%s", Versionstr, 0, 0 ); 742 743 global_host = ldap_pvt_get_fqdn( NULL ); 744 ber_str2bv( global_host, 0, 0, &global_host_bv ); 745 746 if( check == CHECK_NONE && slapd_daemon_init( urls ) != 0 ) { 747 rc = 1; 748 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 ); 749 goto stop; 750 } 751 752 #if defined(HAVE_CHROOT) 753 if ( sandbox ) { 754 if ( chdir( sandbox ) ) { 755 perror("chdir"); 756 rc = 1; 757 goto stop; 758 } 759 if ( chroot( sandbox ) ) { 760 perror("chroot"); 761 rc = 1; 762 goto stop; 763 } 764 if ( chdir( "/" ) ) { 765 perror("chdir"); 766 rc = 1; 767 goto stop; 768 } 769 } 770 #endif 771 772 #if defined(HAVE_SETUID) && defined(HAVE_SETGID) 773 if ( username != NULL || groupname != NULL ) { 774 slap_init_user( username, groupname ); 775 } 776 #endif 777 778 extops_init(); 779 lutil_passwd_init(); 780 781 #ifdef HAVE_TLS 782 rc = ldap_create( &slap_tls_ld ); 783 if ( rc ) { 784 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); 785 goto destroy; 786 } 787 /* Library defaults to full certificate checking. This is correct when 788 * a client is verifying a server because all servers should have a 789 * valid cert. But few clients have valid certs, so we want our default 790 * to be no checking. The config file can override this as usual. 791 */ 792 rc = LDAP_OPT_X_TLS_NEVER; 793 (void) ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &rc ); 794 #endif 795 796 rc = slap_init( serverMode, serverName ); 797 if ( rc ) { 798 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 ); 799 goto destroy; 800 } 801 802 if ( read_config( configfile, configdir ) != 0 ) { 803 rc = 1; 804 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 ); 805 806 if ( check & CHECK_CONFIG ) { 807 fprintf( stderr, "config check failed\n" ); 808 } 809 810 goto destroy; 811 } 812 813 if ( debug_unknowns ) { 814 rc = parse_debug_unknowns( debug_unknowns, &slap_debug ); 815 ldap_charray_free( debug_unknowns ); 816 debug_unknowns = NULL; 817 if ( rc ) 818 goto destroy; 819 } 820 if ( syslog_unknowns ) { 821 rc = parse_debug_unknowns( syslog_unknowns, &ldap_syslog ); 822 ldap_charray_free( syslog_unknowns ); 823 syslog_unknowns = NULL; 824 if ( rc ) 825 goto destroy; 826 } 827 828 if ( check & CHECK_LOGLEVEL ) { 829 rc = 0; 830 goto destroy; 831 } 832 833 if ( check & CHECK_CONFIG ) { 834 fprintf( stderr, "config check succeeded\n" ); 835 836 check &= ~CHECK_CONFIG; 837 if ( check == CHECK_NONE ) { 838 rc = 0; 839 goto destroy; 840 } 841 } 842 843 if ( glue_sub_attach( 0 ) != 0 ) { 844 Debug( LDAP_DEBUG_ANY, 845 "subordinate config error\n", 846 0, 0, 0 ); 847 848 goto destroy; 849 } 850 851 if ( slap_schema_check( ) != 0 ) { 852 Debug( LDAP_DEBUG_ANY, 853 "schema prep error\n", 854 0, 0, 0 ); 855 856 goto destroy; 857 } 858 859 #ifdef HAVE_TLS 860 rc = ldap_pvt_tls_init(); 861 if( rc != 0) { 862 Debug( LDAP_DEBUG_ANY, 863 "main: TLS init failed: %d\n", 864 rc, 0, 0 ); 865 rc = 1; 866 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); 867 goto destroy; 868 } 869 870 { 871 int opt = 1; 872 873 /* Force new ctx to be created */ 874 rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt ); 875 if( rc == 0 ) { 876 /* The ctx's refcount is bumped up here */ 877 ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx ); 878 load_extop( &slap_EXOP_START_TLS, 0, starttls_extop ); 879 } else if ( rc != LDAP_NOT_SUPPORTED ) { 880 Debug( LDAP_DEBUG_ANY, 881 "main: TLS init def ctx failed: %d\n", 882 rc, 0, 0 ); 883 rc = 1; 884 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 ); 885 goto destroy; 886 } 887 } 888 #endif 889 890 #ifdef HAVE_CYRUS_SASL 891 if( sasl_host == NULL ) { 892 sasl_host = ch_strdup( global_host ); 893 } 894 #endif 895 896 (void) SIGNAL( LDAP_SIGUSR1, slap_sig_wake ); 897 (void) SIGNAL( LDAP_SIGUSR2, slap_sig_shutdown ); 898 899 #ifdef SIGPIPE 900 (void) SIGNAL( SIGPIPE, SIG_IGN ); 901 #endif 902 #ifdef SIGHUP 903 (void) SIGNAL( SIGHUP, slap_sig_shutdown ); 904 #endif 905 (void) SIGNAL( SIGINT, slap_sig_shutdown ); 906 (void) SIGNAL( SIGTERM, slap_sig_shutdown ); 907 #ifdef SIGTRAP 908 (void) SIGNAL( SIGTRAP, slap_sig_shutdown ); 909 #endif 910 #ifdef LDAP_SIGCHLD 911 (void) SIGNAL( LDAP_SIGCHLD, wait4child ); 912 #endif 913 #ifdef SIGBREAK 914 /* SIGBREAK is generated when Ctrl-Break is pressed. */ 915 (void) SIGNAL( SIGBREAK, slap_sig_shutdown ); 916 #endif 917 918 #ifndef HAVE_WINSOCK 919 if ( !no_detach ) { 920 if ( lutil_pair( waitfds ) < 0 ) { 921 Debug( LDAP_DEBUG_ANY, 922 "main: lutil_pair failed: %d\n", 923 0, 0, 0 ); 924 rc = 1; 925 goto destroy; 926 } 927 pid = lutil_detach( no_detach, 0 ); 928 if ( pid ) { 929 char buf[4]; 930 rc = EXIT_SUCCESS; 931 close( waitfds[1] ); 932 if ( read( waitfds[0], buf, 1 ) != 1 ) 933 rc = EXIT_FAILURE; 934 _exit( rc ); 935 } else { 936 close( waitfds[0] ); 937 } 938 } 939 #endif /* HAVE_WINSOCK */ 940 941 #ifdef CSRIMALLOC 942 mal_leaktrace(1); 943 #endif 944 945 if ( slapd_pid_file != NULL ) { 946 FILE *fp = fopen( slapd_pid_file, "w" ); 947 948 if ( fp == NULL ) { 949 int save_errno = errno; 950 951 Debug( LDAP_DEBUG_ANY, "unable to open pid file " 952 "\"%s\": %d (%s)\n", 953 slapd_pid_file, 954 save_errno, strerror( save_errno ) ); 955 956 free( slapd_pid_file ); 957 slapd_pid_file = NULL; 958 959 rc = 1; 960 goto destroy; 961 } 962 fprintf( fp, "%d\n", (int) getpid() ); 963 fclose( fp ); 964 slapd_pid_file_unlink = 1; 965 } 966 967 if ( slapd_args_file != NULL ) { 968 FILE *fp = fopen( slapd_args_file, "w" ); 969 970 if ( fp == NULL ) { 971 int save_errno = errno; 972 973 Debug( LDAP_DEBUG_ANY, "unable to open args file " 974 "\"%s\": %d (%s)\n", 975 slapd_args_file, 976 save_errno, strerror( save_errno ) ); 977 978 free( slapd_args_file ); 979 slapd_args_file = NULL; 980 981 rc = 1; 982 goto destroy; 983 } 984 985 for ( i = 0; i < g_argc; i++ ) { 986 fprintf( fp, "%s ", g_argv[i] ); 987 } 988 fprintf( fp, "\n" ); 989 fclose( fp ); 990 slapd_args_file_unlink = 1; 991 } 992 993 /* 994 * FIXME: moved here from slapd_daemon_task() 995 * because back-monitor db_open() needs it 996 */ 997 time( &starttime ); 998 999 connections_init(); 1000 1001 if ( slap_startup( NULL ) != 0 ) { 1002 rc = 1; 1003 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 ); 1004 goto shutdown; 1005 } 1006 1007 Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 ); 1008 1009 #ifndef HAVE_WINSOCK 1010 if ( !no_detach ) { 1011 write( waitfds[1], "1", 1 ); 1012 close( waitfds[1] ); 1013 } 1014 #endif 1015 1016 #ifdef HAVE_NT_EVENT_LOG 1017 if (is_NT_Service) 1018 lutil_LogStartedEvent( serverName, slap_debug, configfile ? 1019 configfile : SLAPD_DEFAULT_CONFIGFILE , urls ); 1020 #endif 1021 1022 rc = slapd_daemon(); 1023 1024 #ifdef HAVE_NT_SERVICE_MANAGER 1025 /* Throw away the event that we used during the startup process. */ 1026 if ( is_NT_Service ) 1027 ldap_pvt_thread_cond_destroy( &started_event ); 1028 #endif 1029 1030 shutdown: 1031 /* remember an error during shutdown */ 1032 rc |= slap_shutdown( NULL ); 1033 1034 destroy: 1035 if ( check & CHECK_LOGLEVEL ) { 1036 (void)loglevel_print( stdout ); 1037 } 1038 /* remember an error during destroy */ 1039 rc |= slap_destroy(); 1040 1041 while ( !LDAP_STAILQ_EMPTY( &slap_sync_cookie )) { 1042 scp = LDAP_STAILQ_FIRST( &slap_sync_cookie ); 1043 LDAP_STAILQ_REMOVE_HEAD( &slap_sync_cookie, sc_next ); 1044 ch_free( scp ); 1045 } 1046 1047 #ifdef SLAPD_MODULES 1048 module_kill(); 1049 #endif 1050 1051 extops_kill(); 1052 1053 supported_feature_destroy(); 1054 entry_info_destroy(); 1055 1056 stop: 1057 #ifdef HAVE_NT_EVENT_LOG 1058 if (is_NT_Service) 1059 lutil_LogStoppedEvent( serverName ); 1060 #endif 1061 1062 Debug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 ); 1063 1064 1065 #ifdef HAVE_NT_SERVICE_MANAGER 1066 lutil_ReportShutdownComplete(); 1067 #endif 1068 1069 #ifdef LOG_DEBUG 1070 closelog(); 1071 #endif 1072 slapd_daemon_destroy(); 1073 1074 controls_destroy(); 1075 1076 filter_destroy(); 1077 1078 schema_destroy(); 1079 1080 lutil_passwd_destroy(); 1081 1082 #ifdef HAVE_TLS 1083 if ( slap_tls_ld ) { 1084 ldap_pvt_tls_ctx_free( slap_tls_ctx ); 1085 ldap_unbind_ext( slap_tls_ld, NULL, NULL ); 1086 } 1087 ldap_pvt_tls_destroy(); 1088 #endif 1089 1090 slap_sasl_regexp_destroy(); 1091 1092 if ( slapd_pid_file_unlink ) { 1093 unlink( slapd_pid_file ); 1094 } 1095 if ( slapd_args_file_unlink ) { 1096 unlink( slapd_args_file ); 1097 } 1098 1099 config_destroy(); 1100 1101 if ( configfile ) 1102 ch_free( configfile ); 1103 if ( configdir ) 1104 ch_free( configdir ); 1105 if ( urls ) 1106 ch_free( urls ); 1107 if ( global_host ) 1108 ch_free( global_host ); 1109 1110 /* kludge, get symbols referenced */ 1111 tavl_free( NULL, NULL ); 1112 1113 #ifdef CSRIMALLOC 1114 mal_dumpleaktrace( leakfile ); 1115 #endif 1116 1117 MAIN_RETURN(rc); 1118 } 1119 1120 1121 #ifdef LDAP_SIGCHLD 1122 1123 /* 1124 * Catch and discard terminated child processes, to avoid zombies. 1125 */ 1126 1127 static RETSIGTYPE 1128 wait4child( int sig ) 1129 { 1130 int save_errno = errno; 1131 1132 #ifdef WNOHANG 1133 do 1134 errno = 0; 1135 #ifdef HAVE_WAITPID 1136 while ( waitpid( (pid_t)-1, NULL, WNOHANG ) > 0 || errno == EINTR ); 1137 #else 1138 while ( wait3( NULL, WNOHANG, NULL ) > 0 || errno == EINTR ); 1139 #endif 1140 #else 1141 (void) wait( NULL ); 1142 #endif 1143 (void) SIGNAL_REINSTALL( sig, wait4child ); 1144 errno = save_errno; 1145 } 1146 1147 #endif /* LDAP_SIGCHLD */ 1148