]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/main.c
dn2id fixes, slapadd working
[openldap] / servers / slapd / main.c
index 76f30adf45729f19e83df3deaafcd10881dc1dc2..a70698f2f449dee3663350ad2dc8a321858e4074 100644 (file)
@@ -1,7 +1,7 @@
 /* $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
@@ -65,7 +65,7 @@ static struct sockaddr_in     bind_addr;
 
 typedef int (MainFunc) LDAP_P(( int argc, char *argv[] ));
 extern MainFunc slapadd, slapcat, slapdn, slapindex, slappasswd,
-       slaptest, slapauth, slapacl;
+       slaptest, slapauth, slapacl, slapschema, slapmodify;
 
 static struct {
        char *name;
@@ -75,7 +75,9 @@ static struct {
        {"slapcat", slapcat},
        {"slapdn", slapdn},
        {"slapindex", slapindex},
+       {"slapmodify", slapmodify},
        {"slappasswd", slappasswd},
+       {"slapschema", slapschema},
        {"slaptest", slaptest},
        {"slapauth", slapauth},
        {"slapacl", slapacl},
@@ -98,25 +100,26 @@ const char Versionstr[] =
        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;
 LDAP *slap_tls_ld;
 
-#ifdef LOG_LOCAL4
-#define DEFAULT_SYSLOG_USER    LOG_LOCAL4
-#endif /* LOG_LOCAL4 */
-
 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;
@@ -155,12 +158,13 @@ struct option_helper {
        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[] = {
@@ -180,12 +184,12 @@ parse_syslog_user( const char *arg, int *syslogUser )
 #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;
        }
 
@@ -195,7 +199,7 @@ parse_syslog_user( const char *arg, int *syslogUser )
 }
 #endif /* LOG_LOCAL4 */
 
-static int
+int
 parse_syslog_level( const char *arg, int *levelp )
 {
        static slap_verbmasks   str2syslog_level[] = {
@@ -221,6 +225,7 @@ parse_syslog_level( const char *arg, int *levelp )
 
        return 0;
 }
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
 int
 parse_debug_unknowns( char **unknowns, int *levelp )
@@ -269,7 +274,18 @@ parse_debug_level( const char *arg, int *levelp, char ***unknowns )
                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 );
@@ -295,7 +311,7 @@ usage( char *name )
        fprintf( stderr,
                "\t-4\t\tIPv4 only\n"
                "\t-6\t\tIPv6 only\n"
-               "\t-T {acl|add|auth|cat|dn|index|passwd|test}\n"
+               "\t-T {acl|add|auth|cat|dn|index|modify|passwd|test}\n"
                "\t\t\tRun in Tool mode\n"
                "\t-c cookie\tSync cookie of consumer\n"
                "\t-d level\tDebug level" "\n"
@@ -305,7 +321,7 @@ usage( char *name )
                "\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"
@@ -328,7 +344,8 @@ usage( char *name )
 #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"
     );
 }
 
@@ -348,10 +365,13 @@ int main( int argc, char **argv )
 #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;
 
@@ -370,6 +390,7 @@ int main( int argc, char **argv )
        size_t  l;
 
        int slapd_pid_file_unlink = 0, slapd_args_file_unlink = 0;
+       int firstopt = 1;
 
 #ifdef CSRIMALLOC
        FILE *leakfile;
@@ -395,7 +416,7 @@ int main( int argc, char **argv )
 
 #ifdef HAVE_NT_SERVICE_MANAGER
        {
-               int *i;
+               int *ip;
                char *newConfigFile;
                char *newConfigDir;
                char *newUrls;
@@ -407,9 +428,9 @@ int main( int argc, char **argv )
                            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 );
                }
@@ -426,13 +447,13 @@ int main( int argc, char **argv )
 
                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 );
                }
        }
@@ -440,18 +461,18 @@ int main( int argc, char **argv )
 
        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
@@ -502,6 +523,11 @@ int main( int argc, char **argv )
                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;
@@ -526,7 +552,6 @@ int main( int argc, char **argv )
                case 'o': {
                        char            *val = strchr( optarg, '=' );
                        struct berval   opt;
-                       int             i;
 
                        opt.bv_val = optarg;
                        
@@ -558,6 +583,11 @@ int main( int argc, char **argv )
                }
 
                case 's':       /* set syslog level */
+                       if ( strcmp( optarg, "?" ) == 0 ) {
+                               check |= CHECK_LOGLEVEL;
+                               break;
+                       }
+
                        if ( parse_debug_level( optarg, &ldap_syslog, &syslog_unknowns ) ) {
                                goto destroy;
                        }
@@ -569,7 +599,6 @@ int main( int argc, char **argv )
                                goto destroy;
                        }
                        break;
-#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
 #ifdef LOG_LOCAL4
                case 'l':       /* set syslog local user */
@@ -578,6 +607,7 @@ int main( int argc, char **argv )
                        }
                        break;
 #endif
+#endif /* LDAP_DEBUG && LDAP_SYSLOG */
 
 #ifdef HAVE_CHROOT
                case 'r':
@@ -614,6 +644,12 @@ int main( int argc, char **argv )
                        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 ) {
@@ -644,17 +680,40 @@ unhandled_option:;
                        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
@@ -666,16 +725,20 @@ unhandled_option:;
 
 #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 );
@@ -705,7 +768,6 @@ unhandled_option:;
 
        extops_init();
        lutil_passwd_init();
-       slap_op_init();
 
 #ifdef HAVE_TLS
        rc = ldap_create( &slap_tls_ld );
@@ -713,6 +775,13 @@ unhandled_option:;
                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 );
@@ -745,6 +814,11 @@ unhandled_option:;
                syslog_unknowns = NULL;
                if ( rc )
                        goto destroy;
+       }       
+
+       if ( check & CHECK_LOGLEVEL ) {
+               rc = 0;
+               goto destroy;
        }
 
        if ( check & CHECK_CONFIG ) {
@@ -757,7 +831,7 @@ unhandled_option:;
                }
        }
 
-       if ( glue_sub_attach( ) != 0 ) {
+       if ( glue_sub_attach( ) != 0 ) {
                Debug( LDAP_DEBUG_ANY,
                    "subordinate config error\n",
                    0, 0, 0 );
@@ -778,7 +852,7 @@ unhandled_option:;
        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;
@@ -804,6 +878,12 @@ unhandled_option:;
        }
 #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 );
 
@@ -827,7 +907,26 @@ unhandled_option:;
 #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
@@ -888,6 +987,8 @@ unhandled_option:;
         */
        time( &starttime );
 
+       connections_init();
+
        if ( slap_startup( NULL ) != 0 ) {
                rc = 1;
                SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 21 );
@@ -896,6 +997,13 @@ unhandled_option:;
 
        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 ?
@@ -915,6 +1023,9 @@ shutdown:
        rc |= slap_shutdown( NULL );
 
 destroy:
+       if ( check & CHECK_LOGLEVEL ) {
+               (void)loglevel_print( stdout );
+       }
        /* remember an error during destroy */
        rc |= slap_destroy();
 
@@ -928,8 +1039,6 @@ destroy:
        module_kill();
 #endif
 
-       slap_op_destroy();
-
        extops_kill();
 
        supported_feature_destroy();
@@ -955,21 +1064,22 @@ stop:
 
        controls_destroy();
 
+       filter_destroy();
+
        schema_destroy();
 
        lutil_passwd_destroy();
 
 #ifdef HAVE_TLS
-       /* Setting it to itself decreases refcount, allowing it to be freed
-        * when the LD is freed.
-        */
        if ( slap_tls_ld ) {
-               ldap_pvt_tls_set_option( slap_tls_ld, LDAP_OPT_X_TLS_CTX, slap_tls_ctx );
-               ldap_unbind( 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 );
        }
@@ -985,6 +1095,11 @@ stop:
                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 );
@@ -1006,13 +1121,12 @@ wait4child( int sig )
     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 );
@@ -1022,4 +1136,3 @@ wait4child( int sig )
 }
 
 #endif /* LDAP_SIGCHLD */
-