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