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