/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
- * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Copyright 1998-2011 The OpenLDAP Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
typedef int (MainFunc) LDAP_P(( int argc, char *argv[] ));
extern MainFunc slapadd, slapcat, slapdn, slapindex, slappasswd,
- slaptest, slapauth, slapacl;
+ slaptest, slapauth, slapacl, slapschema;
static struct {
char *name;
{"slapdn", slapdn},
{"slapindex", slapindex},
{"slappasswd", slappasswd},
+ {"slapschema", slapschema},
{"slaptest", slaptest},
{"slapauth", slapauth},
{"slapacl", slapacl},
OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Server (slapd)";
#endif
-#define CHECK_NONE 0x00
-#define CHECK_CONFIG 0x01
+extern OverlayInit slap_oinfo[];
+extern BackendInfo slap_binfo[];
+
+#define CHECK_NONE 0x00
+#define CHECK_CONFIG 0x01
+#define CHECK_LOGLEVEL 0x02
static int check = CHECK_NONE;
static int version = 0;
void *slap_tls_ctx;
-
-#ifdef LOG_LOCAL4
-#define DEFAULT_SYSLOG_USER LOG_LOCAL4
-#endif /* LOG_LOCAL4 */
+LDAP *slap_tls_ld;
static int
slapd_opt_slp( const char *val, void *arg )
{
#ifdef HAVE_SLP
/* NULL is default */
- if ( val == NULL || strcasecmp( val, "on" ) == 0 ) {
+ if ( val == NULL || *val == '(' || strcasecmp( val, "on" ) == 0 ) {
slapd_register_slp = 1;
+ slapd_slp_attrs = (val != NULL && *val == '(') ? val : NULL;
} else if ( strcasecmp( val, "off" ) == 0 ) {
slapd_register_slp = 0;
void *oh_arg;
const char *oh_usage;
} option_helpers[] = {
- { BER_BVC("slp"), slapd_opt_slp, NULL, "slp[={on|off}] enable/disable SLP" },
+ { BER_BVC("slp"), slapd_opt_slp, NULL, "slp[={on|off|(attrs)}] enable/disable SLP using (attrs)" },
{ BER_BVNULL, 0, NULL, NULL }
};
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
#ifdef LOG_LOCAL4
-static int
+int
parse_syslog_user( const char *arg, int *syslogUser )
{
static slap_verbmasks syslogUsers[] = {
#endif /* LOG_DAEMON */
{ BER_BVNULL, 0 }
};
- int i = verb_to_mask( optarg, syslogUsers );
+ int i = verb_to_mask( arg, syslogUsers );
if ( BER_BVISNULL( &syslogUsers[ i ].word ) ) {
Debug( LDAP_DEBUG_ANY,
"unrecognized syslog user \"%s\".\n",
- optarg, 0, 0 );
+ arg, 0, 0 );
return 1;
}
}
#endif /* LOG_LOCAL4 */
-static int
+int
parse_syslog_level( const char *arg, int *levelp )
{
static slap_verbmasks str2syslog_level[] = {
return 0;
}
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
int
parse_debug_unknowns( char **unknowns, int *levelp )
{
int level;
- if ( arg != NULL && arg[ 0 ] != '-' && !isdigit( arg[ 0 ] ) )
+ if ( arg && arg[ 0 ] != '-' && !isdigit( (unsigned char) arg[ 0 ] ) )
{
int i;
char **levels;
ldap_charray_free( levels );
} else {
- if ( lutil_atoix( &level, arg, 0 ) != 0 ) {
+ int rc;
+
+ if ( arg[0] == '-' ) {
+ rc = lutil_atoix( &level, arg, 0 );
+ } else {
+ unsigned ulevel;
+
+ rc = lutil_atoux( &ulevel, arg, 0 );
+ level = (int)ulevel;
+ }
+
+ if ( rc ) {
fprintf( stderr,
"unrecognized log level "
"\"%s\"\n", arg );
"\t-g group\tGroup (id or name) to run as\n"
#endif
"\t-h URLs\t\tList of URLs to serve\n"
-#ifdef LOG_LOCAL4
+#ifdef SLAP_DEFAULT_SYSLOG_USER
"\t-l facility\tSyslog facility (default: LOCAL4)\n"
#endif
"\t-n serverName\tService name\n"
#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
"\t-u user\t\tUser (id or name) to run as\n"
#endif
- "\t-V\t\tprint version info (-VV only)\n"
+ "\t-V\t\tprint version info (-VV exit afterwards, -VVV print\n"
+ "\t\t\tinfo about static overlays and backends)\n"
);
}
#if defined(HAVE_CHROOT)
char *sandbox = NULL;
#endif
-#ifdef LOG_LOCAL4
- int syslogUser = DEFAULT_SYSLOG_USER;
+#ifdef SLAP_DEFAULT_SYSLOG_USER
+ int syslogUser = SLAP_DEFAULT_SYSLOG_USER;
#endif
+#ifndef HAVE_WINSOCK
+ int pid, waitfds[2];
+#endif
int g_argc = argc;
char **g_argv = argv;
size_t l;
int slapd_pid_file_unlink = 0, slapd_args_file_unlink = 0;
+ int firstopt = 1;
#ifdef CSRIMALLOC
FILE *leakfile;
#ifdef HAVE_NT_SERVICE_MANAGER
{
- int *i;
+ int *ip;
char *newConfigFile;
char *newConfigDir;
char *newUrls;
regService = serverName;
}
- i = (int*)lutil_getRegParam( regService, "DebugLevel" );
- if ( i != NULL ) {
- slap_debug = *i;
+ ip = (int*)lutil_getRegParam( regService, "DebugLevel" );
+ if ( ip != NULL ) {
+ slap_debug = *ip;
Debug( LDAP_DEBUG_ANY,
"new debug level from registry is: %d\n", slap_debug, 0, 0 );
}
newConfigFile = (char*)lutil_getRegParam( regService, "ConfigFile" );
if ( newConfigFile != NULL ) {
- configfile = newConfigFile;
+ configfile = ch_strdup(newConfigFile);
Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile, 0, 0 );
}
newConfigDir = (char*)lutil_getRegParam( regService, "ConfigDir" );
if ( newConfigDir != NULL ) {
- configdir = newConfigDir;
+ configdir = ch_strdup(newConfigDir);
Debug ( LDAP_DEBUG_ANY, "new config dir from registry is: %s\n", configdir, 0, 0 );
}
}
while ( (i = getopt( argc, argv,
"c:d:f:F:h:n:o:s:tT:V"
-#if LDAP_PF_INET6
+#ifdef LDAP_PF_INET6
"46"
#endif
#ifdef HAVE_CHROOT
"r:"
#endif
-#ifdef LDAP_SYSLOG
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
"S:"
-#endif
#ifdef LOG_LOCAL4
"l:"
#endif
+#endif
#if defined(HAVE_SETUID) && defined(HAVE_SETGID)
"u:g:"
#endif
case 'd': { /* set debug level and 'do not detach' flag */
int level = 0;
+ if ( strcmp( optarg, "?" ) == 0 ) {
+ check |= CHECK_LOGLEVEL;
+ break;
+ }
+
no_detach = 1;
if ( parse_debug_level( optarg, &level, &debug_unknowns ) ) {
goto destroy;
case 'o': {
char *val = strchr( optarg, '=' );
struct berval opt;
- int i;
opt.bv_val = optarg;
}
case 's': /* set syslog level */
+ if ( strcmp( optarg, "?" ) == 0 ) {
+ check |= CHECK_LOGLEVEL;
+ break;
+ }
+
if ( parse_debug_level( optarg, &ldap_syslog, &syslog_unknowns ) ) {
goto destroy;
}
goto destroy;
}
break;
-#endif /* LDAP_DEBUG && LDAP_SYSLOG */
#ifdef LOG_LOCAL4
case 'l': /* set syslog local user */
}
break;
#endif
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
#ifdef HAVE_CHROOT
case 'r':
break;
case 'T':
+ if ( firstopt == 0 ) {
+ fprintf( stderr, "warning: \"-T %s\" "
+ "should be the first option.\n",
+ optarg );
+ }
+
/* try full option string first */
for ( i = 0; tools[i].name; i++ ) {
if ( strcmp( optarg, &tools[i].name[4] ) == 0 ) {
SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 );
goto stop;
}
+
+ if ( firstopt ) {
+ firstopt = 0;
+ }
}
+ if ( optind != argc )
+ goto unhandled_option;
+
ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
ldif_debug = slap_debug;
if ( version ) {
fprintf( stderr, "%s\n", Versionstr );
+ if ( version > 2 ) {
+ if ( slap_oinfo[0].ov_type ) {
+ fprintf( stderr, "Included static overlays:\n");
+ for ( i= 0 ; slap_oinfo[i].ov_type; i++ ) {
+ fprintf( stderr, " %s\n", slap_oinfo[i].ov_type );
+ }
+ }
+ if ( slap_binfo[0].bi_type ) {
+ fprintf( stderr, "Included static backends:\n");
+ for ( i= 0 ; slap_binfo[i].bi_type; i++ ) {
+ fprintf( stderr, " %s\n", slap_binfo[i].bi_type );
+ }
+ }
+ }
+
if ( version > 1 ) goto stop;
}
+#if defined(LDAP_DEBUG) && defined(LDAP_SYSLOG)
{
char *logName;
#ifdef HAVE_EBCDIC
#ifdef LOG_LOCAL4
openlog( logName, OPENLOG_OPTIONS, syslogUser );
-#elif LOG_DEBUG
+#elif defined LOG_DEBUG
openlog( logName, OPENLOG_OPTIONS );
#endif
#ifdef HAVE_EBCDIC
free( logName );
#endif
}
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
Debug( LDAP_DEBUG_ANY, "%s", Versionstr, 0, 0 );
+ global_host = ldap_pvt_get_fqdn( NULL );
+ ber_str2bv( global_host, 0, 0, &global_host_bv );
+
if( check == CHECK_NONE && slapd_daemon_init( urls ) != 0 ) {
rc = 1;
SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 16 );
extops_init();
lutil_passwd_init();
- slap_op_init();
+
+#ifdef HAVE_TLS
+ rc = ldap_create( &slap_tls_ld );
+ if ( rc ) {
+ SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
+ goto destroy;
+ }
+ /* Library defaults to full certificate checking. This is correct when
+ * a client is verifying a server because all servers should have a
+ * valid cert. But few clients have valid certs, so we want our default
+ * to be no checking. The config file can override this as usual.
+ */
+ rc = LDAP_OPT_X_TLS_NEVER;
+ (void) ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &rc );
+#endif
rc = slap_init( serverMode, serverName );
if ( rc ) {
syslog_unknowns = NULL;
if ( rc )
goto destroy;
+ }
+
+ if ( check & CHECK_LOGLEVEL ) {
+ rc = 0;
+ goto destroy;
}
if ( check & CHECK_CONFIG ) {
}
}
- if ( glue_sub_attach( ) != 0 ) {
+ if ( glue_sub_attach( 0 ) != 0 ) {
Debug( LDAP_DEBUG_ANY,
"subordinate config error\n",
0, 0, 0 );
if( rc != 0) {
Debug( LDAP_DEBUG_ANY,
"main: TLS init failed: %d\n",
- 0, 0, 0 );
+ rc, 0, 0 );
rc = 1;
SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
goto destroy;
}
{
- void *def_ctx = NULL;
-
- /* Save existing default ctx, if any */
- ldap_pvt_tls_get_option( NULL, LDAP_OPT_X_TLS_CTX, &def_ctx );
+ int opt = 1;
/* Force new ctx to be created */
- ldap_pvt_tls_set_option( NULL, LDAP_OPT_X_TLS_CTX, NULL );
-
- rc = ldap_pvt_tls_init_def_ctx( 1 );
+ rc = ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_NEWCTX, &opt );
if( rc == 0 ) {
- ldap_pvt_tls_get_option( NULL, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx );
- /* Restore previous ctx */
- ldap_pvt_tls_set_option( NULL, LDAP_OPT_X_TLS_CTX, def_ctx );
+ /* The ctx's refcount is bumped up here */
+ ldap_pvt_tls_get_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, &slap_tls_ctx );
load_extop( &slap_EXOP_START_TLS, 0, starttls_extop );
} else if ( rc != LDAP_NOT_SUPPORTED ) {
Debug( LDAP_DEBUG_ANY,
}
#endif
+#ifdef HAVE_CYRUS_SASL
+ if( sasl_host == NULL ) {
+ sasl_host = ch_strdup( global_host );
+ }
+#endif
+
(void) SIGNAL( LDAP_SIGUSR1, slap_sig_wake );
(void) SIGNAL( LDAP_SIGUSR2, slap_sig_shutdown );
#endif
#ifndef HAVE_WINSOCK
- lutil_detach( no_detach, 0 );
+ if ( !no_detach ) {
+ if ( lutil_pair( waitfds ) < 0 ) {
+ Debug( LDAP_DEBUG_ANY,
+ "main: lutil_pair failed: %d\n",
+ 0, 0, 0 );
+ rc = 1;
+ goto destroy;
+ }
+ pid = lutil_detach( no_detach, 0 );
+ if ( pid ) {
+ char buf[4];
+ rc = EXIT_SUCCESS;
+ close( waitfds[1] );
+ if ( read( waitfds[0], buf, 1 ) != 1 )
+ rc = EXIT_FAILURE;
+ _exit( rc );
+ } else {
+ close( waitfds[0] );
+ }
+ }
#endif /* HAVE_WINSOCK */
#ifdef CSRIMALLOC
*/
time( &starttime );
+ connections_init();
+
if ( slap_startup( NULL ) != 0 ) {
rc = 1;
SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 );
Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
+#ifndef HAVE_WINSOCK
+ if ( !no_detach ) {
+ write( waitfds[1], "1", 1 );
+ close( waitfds[1] );
+ }
+#endif
+
#ifdef HAVE_NT_EVENT_LOG
if (is_NT_Service)
lutil_LogStartedEvent( serverName, slap_debug, configfile ?
rc |= slap_shutdown( NULL );
destroy:
+ if ( check & CHECK_LOGLEVEL ) {
+ (void)loglevel_print( stdout );
+ }
/* remember an error during destroy */
rc |= slap_destroy();
module_kill();
#endif
- slap_op_destroy();
-
extops_kill();
supported_feature_destroy();
controls_destroy();
+ filter_destroy();
+
schema_destroy();
lutil_passwd_destroy();
#ifdef HAVE_TLS
+ if ( slap_tls_ld ) {
+ ldap_pvt_tls_ctx_free( slap_tls_ctx );
+ ldap_unbind_ext( slap_tls_ld, NULL, NULL );
+ }
ldap_pvt_tls_destroy();
#endif
+ slap_sasl_regexp_destroy();
+
if ( slapd_pid_file_unlink ) {
unlink( slapd_pid_file );
}
ch_free( configdir );
if ( urls )
ch_free( urls );
+ if ( global_host )
+ ch_free( global_host );
+
+ /* kludge, get symbols referenced */
+ tavl_free( NULL, NULL );
#ifdef CSRIMALLOC
mal_dumpleaktrace( leakfile );
int save_errno = errno;
#ifdef WNOHANG
- errno = 0;
+ do
+ errno = 0;
#ifdef HAVE_WAITPID
- while ( waitpid( (pid_t)-1, NULL, WNOHANG ) > 0 || errno == EINTR )
- ; /* NULL */
+ while ( waitpid( (pid_t)-1, NULL, WNOHANG ) > 0 || errno == EINTR );
#else
- while ( wait3( NULL, WNOHANG, NULL ) > 0 || errno == EINTR )
- ; /* NULL */
+ while ( wait3( NULL, WNOHANG, NULL ) > 0 || errno == EINTR );
#endif
#else
(void) wait( NULL );
}
#endif /* LDAP_SIGCHLD */
-