]> git.sur5r.net Git - openldap/blob - servers/slapd/main.c
Initialize the TLS environment *after* reading the config files.
[openldap] / servers / slapd / main.c
1 #include "portable.h"
2
3 #include <stdio.h>
4
5 #include <ac/signal.h>
6 #include <ac/socket.h>
7 #include <ac/string.h>
8 #include <ac/time.h>
9 #include <ac/unistd.h>
10 #include <ac/wait.h>
11 #include <ac/signal.h>
12 #include <ac/errno.h>
13
14 #include "ldap_defaults.h"
15 #include "slap.h"
16 #include "lutil.h"
17
18 #ifdef LDAP_SIGCHLD
19 static RETSIGTYPE wait4child( int sig );
20 #endif
21
22 #ifdef HAVE_WINSOCK
23 #define MAIN_RETURN(x) return
24 struct sockaddr_in      bind_addr;
25
26 /* in nt_main.c */
27 extern SERVICE_STATUS                   SLAPDServiceStatus;
28 extern SERVICE_STATUS_HANDLE    hSLAPDServiceStatus;
29 extern ldap_pvt_thread_cond_t   started_event,          stopped_event;
30 extern int        is_NT_Service;
31
32 void LogSlapdStartedEvent( char *svc, int slap_debug, char *configfile, short port, int udp );
33 void LogSlapdStoppedEvent( char *svc );
34
35 void CommenceStartupProcessing( LPCTSTR serviceName,
36                                                            void(*stopper)(int));
37 void ReportSlapdShutdownComplete( void );
38 void *getRegParam( char *svc, char *value );
39
40 #define SERVICE_EXIT( e, n ) \
41                 if ( is_NT_Service ) \
42 { \
43                         SLAPDServiceStatus.dwWin32ExitCode                              = e; \
44                         SLAPDServiceStatus.dwServiceSpecificExitCode    = n; \
45
46 #else
47 #define SERVICE_EXIT( e, n )
48 #define MAIN_RETURN(x) return(x)
49 #endif
50
51 short port = LDAP_PORT;
52 #ifdef HAVE_TLS
53 short tls_port = LDAP_TLS_PORT;
54 #endif
55 /*
56  * when more than one slapd is running on one machine, each one might have
57  * it's own LOCAL for syslogging and must have its own pid/args files
58  */
59
60 #ifndef HAVE_MKVERSION
61 const char Versionstr[] =
62         OPENLDAP_PACKAGE " " OPENLDAP_VERSION " Standalone LDAP Server (slapd)";
63 #endif
64
65 #ifdef LOG_LOCAL4
66
67 #define DEFAULT_SYSLOG_USER  LOG_LOCAL4
68
69 typedef struct _str2intDispatch {
70         char    *stringVal;
71         int      abbr;
72         int      intVal;
73 } STRDISP, *STRDISP_P;
74
75
76 /* table to compute syslog-options to integer */
77 static STRDISP  syslog_types[] = {
78     { "LOCAL0",         6, LOG_LOCAL0 },
79     { "LOCAL1",         6, LOG_LOCAL1 },
80     { "LOCAL2",         6, LOG_LOCAL2 },
81     { "LOCAL3",         6, LOG_LOCAL3 },
82     { "LOCAL4",         6, LOG_LOCAL4 },
83     { "LOCAL5",         6, LOG_LOCAL5 },
84     { "LOCAL6",         6, LOG_LOCAL6 },
85     { "LOCAL7",         6, LOG_LOCAL7 },
86     { NULL }
87 };
88
89 static int   cnvt_str2int( char *, STRDISP_P, int );
90
91 #endif  /* LOG_LOCAL4 */
92
93
94 static void
95 usage( char *name )
96 {
97         fprintf( stderr, "usage: %s [-d ?|debuglevel] [-f configfile] [-p portnumber] [-s sysloglevel]", name );
98     fprintf( stderr, "\n        [-a bind-address] [-i] [-u]" );
99 #ifdef HAVE_WINSOCK
100         fprintf( stderr, " [-n NTserviceName]" );
101 #endif
102 #if LDAP_CONNECTIONLESS
103         fprintf( stderr, " [-c]" );
104 #endif
105 #ifdef SLAPD_BDB2
106     fprintf( stderr, " [-t]" );
107 #endif
108 #ifdef LOG_LOCAL4
109     fprintf( stderr, " [-l sysloguser]" );
110 #endif
111 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
112     fprintf( stderr, " [-u user] [-g group]" );
113 #endif
114     fprintf( stderr, "\n" );
115 }
116
117 time_t starttime;
118 struct sockaddr_in      bind_addr;
119 ber_int_t tcps;
120 #ifdef HAVE_TLS
121 struct sockaddr_in      tls_bind_addr;
122 ber_int_t tls_tcps;
123 #endif
124
125 #ifdef HAVE_WINSOCK
126 void WINAPI ServiceMain( DWORD argc, LPTSTR *argv )
127 #else
128 int main( int argc, char **argv )
129 #endif
130 {
131         int             i;
132         int             inetd = 0;
133         int             rc;
134         struct slapd_args args;
135         int             udp;
136 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
137         char *username = NULL;
138         char *groupname = NULL;
139 #endif
140 #ifdef LOG_LOCAL4
141     int     syslogUser = DEFAULT_SYSLOG_USER;
142 #endif
143 #ifdef HAVE_WINSOCK
144         char        *NTservice  = SERVICE_NAME;
145         char            *configfile = ".\\slapd.conf";
146 #else
147         char            *configfile = SLAPD_DEFAULT_CONFIGFILE;
148 #endif
149         char        *serverName;
150         int         serverMode = SLAP_SERVER_MODE;
151         int             use_tls_port = 0;
152
153         (void) memset( (void*) &bind_addr, '\0', sizeof(bind_addr));
154         bind_addr.sin_family = AF_INET;
155         bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
156         bind_addr.sin_port = htons(port);
157 #ifdef HAVE_TLS
158         tls_bind_addr.sin_family = AF_INET;
159         tls_bind_addr.sin_addr.s_addr = htonl(INADDR_ANY);
160         tls_bind_addr.sin_port = htons(tls_port);
161 #endif
162
163         g_argc = argc;
164         g_argv = argv;
165
166 #ifdef HAVE_WINSOCK
167         {
168                 int *newPort;
169                 int *newDebugLevel;
170                 char *newConfigFile;
171                 ldap_debug = 0xffff;
172                 if ( is_NT_Service ) CommenceStartupProcessing( NTservice, slap_set_shutdown );
173                 newPort = (int*)getRegParam( NULL, "Port" );
174                 if ( newPort != NULL )
175                 {
176                         port = *newPort;
177                         bind_addr.sin_port = htons(port);
178                         Debug ( LDAP_DEBUG_ANY, "new port from registry is: %d\n", port, 0, 0 );
179                 }
180                 newDebugLevel = (int*)getRegParam( NULL, "DebugLevel" );
181                 if ( newDebugLevel != NULL ) 
182                 {
183                         slap_debug = *newDebugLevel;
184                         Debug( LDAP_DEBUG_ANY, "new debug level from registry is: %d\n", slap_debug, 0, 0 );
185                 }
186                 newConfigFile = (char*)getRegParam( NULL, "ConfigFile" );
187                 if ( newConfigFile != NULL ) 
188                 {
189                         configfile = newConfigFile;
190                         Debug ( LDAP_DEBUG_ANY, "new config file from registry is: %s\n", configfile, 0, 0 );
191                 }
192         }
193 #endif
194
195         while ( (i = getopt( argc, argv,
196                              "d:f:ia:p:s:u"
197 #ifdef LOG_LOCAL4
198                              "l:"
199 #endif
200 #ifdef SLAPD_BDB2
201                              "t"
202 #endif
203 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
204                              "u:g:"
205 #endif
206 #ifdef LDAP_CONNECTIONLESS
207                                  "c"
208 #endif
209 #ifdef HAVE_WINSOCK
210                                  "n:"
211 #endif
212 #ifdef HAVE_TLS
213                              "P:T"
214 #endif
215                              )) != EOF ) {
216                 switch ( i ) {
217                 case 'a':       /* bind address */
218 #ifdef HAVE_WINSOCK
219                         if(!(bind_addr.sin_addr.S_un.S_addr = inet_addr(optarg)))
220 #else
221                         if(!inet_aton(optarg, &bind_addr.sin_addr))
222 #endif
223                         {
224                                 fprintf(stderr, "invalid address (%s) for -a option", optarg);
225                         }
226 #ifdef HAVE_TLS
227 #ifdef HAVE_WINSOCK
228                         tls_bind_addr.sin_addr.S_un.S_addr = inet_addr(optarg);
229 #else
230                         inet_aton(optarg, &tls_bind_addr.sin_addr);
231 #endif
232 #endif
233             break;
234
235 #ifdef LDAP_DEBUG
236                 case 'd':       /* turn on debugging */
237                         if ( optarg[0] == '?' ) {
238                                 printf( "Debug levels:\n" );
239                                 printf( "\tLDAP_DEBUG_TRACE\t%d\n",
240                                     LDAP_DEBUG_TRACE );
241                                 printf( "\tLDAP_DEBUG_PACKETS\t%d\n",
242                                     LDAP_DEBUG_PACKETS );
243                                 printf( "\tLDAP_DEBUG_ARGS\t\t%d\n",
244                                     LDAP_DEBUG_ARGS );
245                                 printf( "\tLDAP_DEBUG_CONNS\t%d\n",
246                                     LDAP_DEBUG_CONNS );
247                                 printf( "\tLDAP_DEBUG_BER\t\t%d\n",
248                                     LDAP_DEBUG_BER );
249                                 printf( "\tLDAP_DEBUG_FILTER\t%d\n",
250                                     LDAP_DEBUG_FILTER );
251                                 printf( "\tLDAP_DEBUG_CONFIG\t%d\n",
252                                     LDAP_DEBUG_CONFIG );
253                                 printf( "\tLDAP_DEBUG_ACL\t\t%d\n",
254                                     LDAP_DEBUG_ACL );
255                                 printf( "\tLDAP_DEBUG_STATS\t%d\n",
256                                     LDAP_DEBUG_STATS );
257                                 printf( "\tLDAP_DEBUG_STATS2\t%d\n",
258                                     LDAP_DEBUG_STATS2 );
259                                 printf( "\tLDAP_DEBUG_SHELL\t%d\n",
260                                     LDAP_DEBUG_SHELL );
261                                 printf( "\tLDAP_DEBUG_PARSE\t%d\n",
262                                     LDAP_DEBUG_PARSE );
263                                 printf( "\tLDAP_DEBUG_ANY\t\t%d\n",
264                                     LDAP_DEBUG_ANY );
265                                 exit( 0 );
266                         } else {
267                                 slap_debug |= atoi( optarg );
268                         }
269                         break;
270 #else
271                 case 'd':       /* turn on debugging */
272                         fprintf( stderr,
273                             "must compile with LDAP_DEBUG for debugging\n" );
274                         break;
275 #endif
276
277                 case 'f':       /* read config file */
278                         configfile = ch_strdup( optarg );
279                         break;
280
281                 case 'i':       /* run from inetd */
282                         inetd = 1;
283                         break;
284
285                 case 'p': {     /* port on which to listen */
286                                 port = (short)atoi( optarg );
287                                 if(! port ) {
288                                         fprintf(stderr, "-p %s must be numeric\n", optarg);
289                                 } else {
290                                         bind_addr.sin_port = htons(port);
291                                 }
292                         } break;
293
294 #ifdef HAVE_TLS
295                 case 'P': {     /* port on which to listen for TLS */
296                                 tls_port = (short)atoi( optarg );
297                                 if(! tls_port ) {
298                                         fprintf(stderr, "-P %s must be numeric\n", optarg);
299                                 } else {
300                                         tls_bind_addr.sin_port = htons(tls_port);
301                                 }
302                         } break;
303 #endif
304
305                 case 's':       /* set syslog level */
306                         ldap_syslog = atoi( optarg );
307                         break;
308
309 #ifdef LOG_LOCAL4
310                 case 'l':       /* set syslog local user */
311                         syslogUser = cnvt_str2int( optarg, syslog_types,
312                                            DEFAULT_SYSLOG_USER );
313                         break;
314 #endif
315
316 #ifdef LDAP_CONNECTIONLESS
317                 case 'c':       /* do connectionless (udp) */
318                         udp = 1;
319                         break;
320 #endif
321
322 #ifdef SLAPD_BDB2
323                 case 't':  /* timed server */
324                         serverMode = SLAP_TIMEDSERVER_MODE;
325                         break;
326 #endif
327
328 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
329                 case 'u':       /* user name */
330                         if( username ) free(username);
331                         username = ch_strdup( optarg );
332                         break;
333
334                 case 'g':       /* group name */
335                         if( groupname ) free(groupname);
336                         groupname = ch_strdup( optarg );
337                         break;
338 #endif /* SETUID && GETUID */
339 #ifdef HAVE_WINSOCK
340                 case 'n':  /* NT service name */
341                         NTservice = ch_strdup( optarg );
342                         break;
343 #endif
344 #ifdef HAVE_TLS
345                 case 'T':  /* Bind on TLS port */
346                         use_tls_port = 1;
347                         break;
348 #endif
349                 default:
350                         usage( argv[0] );
351                         rc = 1;
352                         SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 15 );
353                         goto stop;
354                 }
355         }
356
357         ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, &slap_debug);
358         ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, &slap_debug);
359         ldif_debug = slap_debug;
360
361         Debug( LDAP_DEBUG_TRACE, "%s", Versionstr, 0, 0 );
362
363         if ( (serverName = strrchr( argv[0], *LDAP_DIRSEP )) == NULL ) {
364                 serverName = ch_strdup( argv[0] );
365         } else {
366                 serverName = ch_strdup( serverName + 1 );
367         }
368
369 #ifdef LOG_LOCAL4
370         openlog( serverName, OPENLOG_OPTIONS, syslogUser );
371 #else
372         openlog( serverName, OPENLOG_OPTIONS );
373 #endif
374
375 #if defined(HAVE_SETUID) && defined(HAVE_SETGID)
376         if ( username != NULL || groupname != NULL )
377                 slap_init_user( username, groupname );
378 #endif
379
380         if ( slap_init( serverMode, serverName ) != 0 ) {
381                 rc = 1;
382                 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 18 );
383                 goto destroy;
384         }
385
386         if ( read_config( configfile ) != 0 ) {
387                 rc = 1;
388                 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 19 );
389                 goto destroy;
390         }
391
392 #ifdef HAVE_TLS
393         ldap_pvt_tls_init();
394         ldap_pvt_tls_init_def_ctx();
395 #endif
396
397         tcps = set_socket( inetd ? NULL : &bind_addr );
398         if ( tcps == -1 )
399                 goto destroy;
400 #ifdef HAVE_TLS
401         if ( use_tls_port ) {
402                 tls_tcps = set_socket( inetd ? NULL : &tls_bind_addr );
403                 if ( tls_tcps == -1 )
404                         goto destroy;
405         } else {
406                 tls_tcps = -1;
407         }
408 #endif
409
410         (void) SIGNAL( LDAP_SIGUSR1, slap_do_nothing );
411         (void) SIGNAL( LDAP_SIGUSR2, slap_set_shutdown );
412 #ifdef SIGPIPE
413         (void) SIGNAL( SIGPIPE, SIG_IGN );
414 #endif
415 #ifdef SIGHUP
416         (void) SIGNAL( SIGHUP, slap_set_shutdown );
417 #endif
418         (void) SIGNAL( SIGINT, slap_set_shutdown );
419         (void) SIGNAL( SIGTERM, slap_set_shutdown );
420 #ifdef LDAP_SIGCHLD
421         (void) SIGNAL( LDAP_SIGCHLD, wait4child );
422 #endif
423 #ifdef SIGBREAK
424         /* SIGBREAK is generated when Ctrl-Break is pressed. */
425         (void) SIGNAL( SIGBREAK, slap_set_shutdown );
426 #endif
427
428 #ifndef HAVE_WINSOCK
429         if(!inetd) {
430 #ifdef LDAP_DEBUG
431                 lutil_detach( ldap_debug, 0 );
432 #else
433                 lutil_detach( 0, 0 );
434 #endif
435         }
436 #endif /* HAVE_WINSOC */
437
438         if ( slap_startup(-1)  != 0 ) {
439                 rc = 1;
440                 SERVICE_EXIT( ERROR_SERVICE_SPECIFIC_ERROR, 20 );
441                 goto shutdown;
442         }
443
444         if(!inetd) {
445                 FILE *fp;
446
447                 args.addr = &bind_addr;
448 #ifdef HAVE_TLS
449                 args.tls_addr = &tls_bind_addr;
450 #endif
451
452                 Debug( LDAP_DEBUG_ANY, "slapd starting\n", 0, 0, 0 );
453
454                 if (( slapd_pid_file != NULL ) &&
455                         (( fp = fopen( slapd_pid_file, "w" )) != NULL ))
456                 {
457                         fprintf( fp, "%d\n", (int) getpid() );
458                         fclose( fp );
459                 }
460
461                 if (( slapd_args_file != NULL ) &&
462                         (( fp = fopen( slapd_args_file, "w" )) != NULL ))
463                 {
464                         for ( i = 0; i < g_argc; i++ ) {
465                                 fprintf( fp, "%s ", g_argv[i] );
466                         }
467                         fprintf( fp, "\n" );
468                         fclose( fp );
469                 }
470
471         } else {
472                 args.addr = NULL;
473 #ifdef HAVE_TLS
474                 args.tls_addr = NULL;
475 #endif
476         }
477         args.tcps = tcps;
478 #ifdef HAVE_TLS
479         args.tls_tcps = tls_tcps;
480 #endif
481
482         time( &starttime );
483 #ifdef HAVE_WINSOCK
484         LogSlapdStartedEvent( NTservice, slap_debug, configfile, port, udp );
485 #endif
486
487         rc = slapd_daemon( &args );
488
489 #ifdef HAVE_WINSOCK
490         /* Throw away the event that we used during the startup process. */
491         if ( is_NT_Service )
492                 ldap_pvt_thread_cond_destroy( &started_event );
493 #endif
494
495 shutdown:
496         /* remember an error during shutdown */
497         rc |= slap_shutdown(-1);
498 destroy:
499         /* remember an error during destroy */
500         rc |= slap_destroy();
501
502 stop:
503 #ifdef HAVE_WINSOCK
504         LogSlapdStoppedEvent( NTservice );
505 #endif
506         Debug( LDAP_DEBUG_ANY, "slapd stopped.\n", 0, 0, 0 );
507 #ifdef HAVE_WINSOCK
508         ReportSlapdShutdownComplete();
509 #endif
510
511     closelog();
512
513         MAIN_RETURN(rc);
514 }
515
516
517 #ifdef LDAP_SIGCHLD
518
519 /*
520  *  Catch and discard terminated child processes, to avoid zombies.
521  */
522
523 static RETSIGTYPE
524 wait4child( int sig )
525 {
526     int save_errno = errno;
527
528 #ifdef WNOHANG
529     errno = 0;
530 #ifdef HAVE_WAITPID
531     while ( waitpid( (pid_t)-1, NULL, WNOHANG ) >= 0 || errno == EINTR )
532         ;       /* NULL */
533 #else
534     while ( wait3( NULL, WNOHANG, NULL ) >= 0 || errno == EINTR )
535         ;       /* NULL */
536 #endif
537 #else
538     (void) wait( NULL );
539 #endif
540     (void) SIGNAL( sig, wait4child );
541     errno = save_errno;
542 }
543
544 #endif /* SIGCHLD || SIGCLD */
545
546
547 #ifdef LOG_LOCAL4
548
549 /*
550  *  Convert a string to an integer by means of a dispatcher table
551  *  if the string is not in the table return the default
552  */
553
554 static int
555 cnvt_str2int( char *stringVal, STRDISP_P dispatcher, int defaultVal )
556 {
557     int        retVal = defaultVal;
558     STRDISP_P  disp;
559
560     for (disp = dispatcher; disp->stringVal; disp++) {
561
562         if (!strncasecmp (stringVal, disp->stringVal, disp->abbr)) {
563
564             retVal = disp->intVal;
565             break;
566
567         }
568     }
569
570     return (retVal);
571
572 } /* cnvt_str2int */
573
574 #endif  /* LOG_LOCAL4 */