the first independent msrpc daemon - lsarpcd.
[kai/samba-autobuild/.git] / source3 / lsarpcd / lsarpcd.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    Main SMB server routines
5    Copyright (C) Andrew Tridgell 1992-1998
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "trans2.h"
24
25 pstring servicesf = CONFIGFILE;
26 extern pstring debugf;
27 extern pstring global_myname;
28
29 int am_parent = 1;
30
31 /* the last message the was processed */
32 int last_message = -1;
33
34 /* a useful macro to debug the last message processed */
35 #define LAST_MESSAGE() smb_fn_name(last_message)
36
37 extern pstring scope;
38 extern int DEBUGLEVEL;
39
40 extern fstring remote_machine;
41 extern pstring myhostname;
42
43
44 /****************************************************************************
45   when exiting, take the whole family
46 ****************************************************************************/
47 static void *dflt_sig(void)
48 {
49         exit_server("caught signal");
50         return NULL;
51 }
52
53 /****************************************************************************
54   Send a SIGTERM to our process group.
55 *****************************************************************************/
56 static void  killkids(void)
57 {
58         if(am_parent) kill(0,SIGTERM);
59 }
60
61
62 /****************************************************************************
63   open and listen to a socket
64 ****************************************************************************/
65 static int open_server_socket(void)
66 {
67         int s;
68         fstring dir;
69         fstring path;
70
71         slprintf(dir, sizeof(dir)-1, "/tmp/.msrpc");
72         slprintf(path, sizeof(path)-1, "%s/lsarpc", dir);
73
74         s = create_pipe_socket(dir, 0777, path, 0777);
75
76         if (s == -1)
77                 return -1;
78                 /* ready to listen */
79         if (listen(s, 5) == -1) {
80                 DEBUG(0,("listen: %s\n", strerror(errno)));
81                 close(s);
82                 return -1;
83         }
84         return s;
85 }
86
87 /****************************************************************************
88   open the socket communication
89 ****************************************************************************/
90 static BOOL open_sockets(BOOL is_daemon)
91 {
92         extern int Client;
93         int num_interfaces = iface_count();
94         int fd_listenset;
95         fd_set listen_set;
96         int s;
97
98         memset(&fd_listenset, 0, sizeof(fd_listenset));
99
100 #ifdef HAVE_ATEXIT
101         {
102                 static int atexit_set;
103                 if(atexit_set == 0) {
104                         atexit_set=1;
105                         atexit(killkids);
106                 }
107         }
108 #endif
109
110         /* Stop zombies */
111         CatchChild();
112                 
113                 
114         FD_ZERO(&listen_set);
115
116         /* Just bind to 0.0.0.0 - accept connections
117            from anywhere. */
118         num_interfaces = 1;
119         
120         /* open an incoming socket */
121         s = open_server_socket();
122         if (s == -1)
123                 return(False);
124         fd_listenset = s;
125         FD_SET(s,&listen_set);
126
127         /* now accept incoming connections - forking a new process
128            for each incoming connection */
129         DEBUG(2,("waiting for a connection\n"));
130         while (1)
131         {
132                 struct sockaddr_un addr;
133                 int in_addrlen = sizeof(addr);
134                 fd_set lfds;
135                 int num;
136                 
137                 memcpy((char *)&lfds, (char *)&listen_set, 
138                        sizeof(listen_set));
139                 
140                 num = sys_select(256,&lfds,NULL, NULL);
141                 
142                 if (num == -1 && errno == EINTR)
143                         continue;
144                 
145                 /* Find the sockets that are read-ready -
146                    accept on these. */
147                         
148                 s = -1;
149                 if(FD_ISSET(fd_listenset,&lfds))
150                 {
151                         s = fd_listenset;
152                 }
153
154                 /* Clear this so we don't look at it again. */
155                 FD_CLR(s,&lfds);
156
157                 Client = accept(s,(struct sockaddr*)&addr,&in_addrlen);
158                 
159                 if (Client == -1 && errno == EINTR)
160                         continue;
161                 
162                 if (Client == -1)
163                 {
164                         DEBUG(0,("open_sockets: accept: %s\n",
165                                  strerror(errno)));
166                         continue;
167                 }
168                 
169                 if (Client != -1 && fork()==0)
170                 {
171                         /* Child code ... */
172                         
173                         /* close the listening socket(s) */
174                         close(fd_listenset);
175                         
176                         /* close our standard file
177                            descriptors */
178                         close_low_fds();
179                         am_parent = 0;
180                         
181                         /* Reset global variables in util.c so
182                            that client substitutions will be
183                            done correctly in the process.  */
184                         reset_globals_after_fork();
185
186                         /*
187                          * Ensure this child has kernel oplock
188                          * capabilities, but not it's children.
189                          */
190                         set_process_capability(KERNEL_OPLOCK_CAPABILITY, True);
191                         set_inherited_process_capability(KERNEL_OPLOCK_CAPABILITY, False);
192
193                         return True; 
194                 }
195                 /* The parent doesn't need this socket */
196                 close(Client); 
197
198                 /* Force parent to check log size after
199                  * spawning child.  Fix from
200                  * klausr@ITAP.Physik.Uni-Stuttgart.De.  The
201                  * parent lsarpcd will log to logserver.smb.  It
202                  * writes only two messages for each child
203                  * started/finished. But each child writes,
204                  * say, 50 messages also in logserver.smb,
205                  * begining with the debug_count of the
206                  * parent, before the child opens its own log
207                  * file logserver.client. In a worst case
208                  * scenario the size of logserver.smb would be
209                  * checked after about 50*50=2500 messages
210                  * (ca. 100kb).
211                  * */
212                 force_check_log_size();
213
214         } /* end while 1 */
215
216 /* NOTREACHED   return True; */
217 }
218
219 /****************************************************************************
220   reload the services file
221   **************************************************************************/
222 BOOL reload_services(BOOL test)
223 {
224         BOOL ret;
225
226         if (lp_loaded()) {
227                 pstring fname;
228                 pstrcpy(fname,lp_configfile());
229                 if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) {
230                         pstrcpy(servicesf,fname);
231                         test = False;
232                 }
233         }
234
235         reopen_logs();
236
237         if (test && !lp_file_list_changed())
238                 return(True);
239
240         lp_killunused(NULL);
241
242         ret = lp_load(servicesf,False,False,True);
243
244         load_printers();
245
246         /* perhaps the config filename is now set */
247         if (!test)
248                 reload_services(True);
249
250         reopen_logs();
251
252         load_interfaces();
253
254         return(ret);
255 }
256
257
258
259 /****************************************************************************
260 this prevents zombie child processes
261 ****************************************************************************/
262 BOOL reload_after_sighup = False;
263
264 static void sig_hup(int sig)
265 {
266         BlockSignals(True,SIGHUP);
267         DEBUG(0,("Got SIGHUP\n"));
268
269         /*
270          * Fix from <branko.cibej@hermes.si> here.
271          * We used to reload in the signal handler - this
272          * is a *BIG* no-no.
273          */
274
275         reload_after_sighup = True;
276         BlockSignals(False,SIGHUP);
277 }
278
279
280
281 #if DUMP_CORE
282 /*******************************************************************
283 prepare to dump a core file - carefully!
284 ********************************************************************/
285 static BOOL dump_core(void)
286 {
287         char *p;
288         pstring dname;
289         pstrcpy(dname,debugf);
290         if ((p=strrchr(dname,'/'))) *p=0;
291         pstrcat(dname,"/corefiles");
292         mkdir(dname,0700);
293         sys_chown(dname,getuid(),getgid());
294         chmod(dname,0700);
295         if (chdir(dname)) return(False);
296         umask(~(0700));
297
298 #ifdef HAVE_GETRLIMIT
299 #ifdef RLIMIT_CORE
300         {
301                 struct rlimit rlp;
302                 getrlimit(RLIMIT_CORE, &rlp);
303                 rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
304                 setrlimit(RLIMIT_CORE, &rlp);
305                 getrlimit(RLIMIT_CORE, &rlp);
306                 DEBUG(3,("Core limits now %d %d\n",
307                          (int)rlp.rlim_cur,(int)rlp.rlim_max));
308         }
309 #endif
310 #endif
311
312
313         DEBUG(0,("Dumping core in %s\n",dname));
314         abort();
315         return(True);
316 }
317 #endif
318
319
320 /****************************************************************************
321 exit the server
322 ****************************************************************************/
323 void exit_server(char *reason)
324 {
325         static int firsttime=1;
326         extern char *last_inbuf;
327
328
329         if (!firsttime) exit(0);
330         firsttime = 0;
331
332         unbecome_user();
333         DEBUG(2,("Closing connections\n"));
334
335 #ifdef WITH_DFS
336         if (dcelogin_atmost_once) {
337                 dfs_unlogin();
338         }
339 #endif
340
341         if (!reason) {   
342                 int oldlevel = DEBUGLEVEL;
343                 DEBUGLEVEL = 10;
344                 if (last_inbuf)
345                         show_msg(last_inbuf);
346                 DEBUGLEVEL = oldlevel;
347                 DEBUG(0,("===============================================================\n"));
348 #if DUMP_CORE
349                 if (dump_core()) return;
350 #endif
351         }    
352
353         locking_end();
354
355         DEBUG(3,("Server exit (%s)\n", (reason ? reason : "")));
356 #ifdef MEM_MAN
357         {
358                 extern FILE *dbf;
359                 smb_mem_write_verbose(dbf);
360                 dbgflush();
361         }
362 #endif
363         exit(0);
364 }
365
366
367
368 /****************************************************************************
369   initialise connect, service and file structs
370 ****************************************************************************/
371 static void init_structs(void)
372 {
373 #if 0
374         conn_init();
375 #endif
376         init_rpc_pipe_hnd(); /* for RPC pipes */
377         if (!init_policy_hnd(MAX_SERVER_POLICY_HANDLES)) 
378         {
379                 exit_server("could not allocate policy handles\n");
380         }
381 }
382
383 /****************************************************************************
384 usage on the program
385 ****************************************************************************/
386 static void usage(char *pname)
387 {
388         DEBUG(0,("Incorrect program usage - are you sure the command line is correct?\n"));
389
390         printf("Usage: %s [-D] [-p port] [-d debuglevel] ", pname);
391         printf("[-l log basename] [-s services file]\n" );
392         printf("Version %s\n",VERSION);
393         printf("\t-D                    become a daemon\n");
394         printf("\t-p port               listen on the specified port\n");
395         printf("\t-d debuglevel         set the debuglevel\n");
396         printf("\t-l log basename.      Basename for log/debug files\n");
397         printf("\t-s services file.     Filename of services file\n");
398         printf("\t-P                    passive only\n");
399         printf("\t-a                    append to log file (default)\n");
400         printf("\t-o                    overwrite log file, don't append\n");
401         printf("\t-i scope              NetBIOS scope to use (default none)\n");
402         printf("\n");
403 }
404
405
406 /****************************************************************************
407   main program
408 ****************************************************************************/
409  int main(int argc,char *argv[])
410 {
411         extern BOOL append_log;
412         /* shall I run as a daemon */
413         BOOL is_daemon = False;
414         int opt;
415         extern char *optarg;
416         
417 #ifdef HAVE_SET_AUTH_PARAMETERS
418         set_auth_parameters(argc,argv);
419 #endif
420
421 #ifdef HAVE_SETLUID
422         /* needed for SecureWare on SCO */
423         setluid(0);
424 #endif
425
426         append_log = True;
427
428         TimeInit();
429
430         pstrcpy(debugf,LSARPCLOGFILE);  
431
432         pstrcpy(remote_machine, "lsarpcd");
433
434         setup_logging(argv[0],False);
435
436         charset_initialise();
437
438         /* make absolutely sure we run as root - to handle cases where people
439            are crazy enough to have it setuid */
440 #ifdef HAVE_SETRESUID
441         setresuid(0,0,0);
442 #else
443         setuid(0);
444         seteuid(0);
445         setuid(0);
446         seteuid(0);
447 #endif
448
449         fault_setup((void (*)(void *))exit_server);
450         CatchSignal(SIGTERM , SIGNAL_CAST dflt_sig);
451
452         /* we are never interested in SIGPIPE */
453         BlockSignals(True,SIGPIPE);
454
455         /* we want total control over the permissions on created files,
456            so set our umask to 0 */
457         umask(0);
458
459         init_uid();
460
461         /* this is for people who can't start the program correctly */
462         while (argc > 1 && (*argv[1] != '-')) {
463                 argv++;
464                 argc--;
465         }
466
467         while ( EOF != (opt = getopt(argc, argv, "i:l:s:d:Dh?Paof:")) )
468                 switch (opt)  {
469                 case 'i':
470                         pstrcpy(scope,optarg);
471                         break;
472
473                 case 'P':
474                         {
475                                 extern BOOL passive;
476                                 passive = True;
477                         }
478                         break;  
479
480                 case 's':
481                         pstrcpy(servicesf,optarg);
482                         break;
483
484                 case 'l':
485                         pstrcpy(debugf,optarg);
486                         break;
487
488                 case 'a':
489                         append_log = True;
490                         break;
491
492                 case 'o':
493                         append_log = False;
494                         break;
495
496                 case 'D':
497                         is_daemon = True;
498                         break;
499
500                 case 'd':
501                         if (*optarg == 'A')
502                                 DEBUGLEVEL = 10000;
503                         else
504                                 DEBUGLEVEL = atoi(optarg);
505                         break;
506
507                 case 'h':
508                 case '?':
509                         usage(argv[0]);
510                         exit(0);
511                         break;
512
513                 default:
514                         usage(argv[0]);
515                         exit(1);
516                 }
517
518         reopen_logs();
519
520         DEBUG(1,( "lsarpcd version %s started.\n", VERSION));
521         DEBUGADD(1,( "Copyright Andrew Tridgell 1992-1999\n"));
522
523         DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
524                  (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));
525
526         if (sizeof(uint16) < 2 || sizeof(uint32) < 4) {
527                 DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
528                 exit(1);
529         }
530
531         get_myname(myhostname,NULL);
532
533         if (!reload_services(False))
534                 return(-1);     
535
536         init_structs();
537
538 #ifdef WITH_PROFILE
539         if (!profile_setup(False)) {
540                 DEBUG(0,("ERROR: failed to setup profiling\n"));
541                 return -1;
542         }
543 #endif
544
545         /*
546          * Set the machine NETBIOS name if not already
547          * set from the config file.
548          */
549         if (!*global_myname)
550         {
551                 fstrcpy(global_myname, dns_to_netbios_name(myhostname));
552         }
553         strupper(global_myname);
554
555         add_msrpc_command_processor( "lsarpc",   argv[0],   api_ntlsa_rpc );
556
557         codepage_initialise(lp_client_code_page());
558
559         if (!pwdb_initialise(True))
560         {
561                 exit(1);
562         }
563
564         if(!initialise_sam_password_db())
565         {
566                 exit(1);
567         }
568
569         if(!initialise_passgrp_db())
570         {
571                 exit(1);
572         }
573
574         if(!initialise_group_db())
575         {
576                 exit(1);
577         }
578
579         if(!initialise_alias_db())
580         {
581                 exit(1);
582         }
583
584         if(!initialise_builtin_db())
585         {
586                 exit(1);
587         }
588
589         if (!get_member_domain_sid())
590         {
591                 DEBUG(0,("ERROR: Samba cannot obtain PDC SID from PDC(s) %s.\n",
592                           lp_passwordserver()));
593                 exit(1);
594         }
595
596         CatchSignal(SIGHUP,SIGNAL_CAST sig_hup);
597         
598         /* Setup the signals that allow the debug log level
599            to by dynamically changed. */
600  
601         /* If we are using the malloc debug code we can't use
602            SIGUSR1 and SIGUSR2 to do debug level changes. */
603         
604 #ifndef MEM_MAN
605 #if defined(SIGUSR1)
606         CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 );
607 #endif /* SIGUSR1 */
608    
609 #if defined(SIGUSR2)
610         CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 );
611 #endif /* SIGUSR2 */
612 #endif /* MEM_MAN */
613
614         DEBUG(3,( "loaded services\n"));
615
616         if (!is_daemon && !is_a_socket(0)) {
617                 DEBUG(0,("standard input is not a socket, assuming -D option\n"));
618                 is_daemon = True;
619         }
620
621         if (is_daemon) {
622                 DEBUG( 3, ( "Becoming a daemon.\n" ) );
623                 become_daemon();
624         }
625
626         if (!directory_exist(lp_lockdir(), NULL)) {
627                 mkdir(lp_lockdir(), 0755);
628         }
629
630         if (is_daemon) {
631                 pidfile_create("lsarpcd");
632         }
633
634         if (!open_sockets(is_daemon))
635                 exit(1);
636
637         if (!locking_init(0))
638                 exit(1);
639
640         /* possibly reload the services file. */
641         reload_services(True);
642         
643         if (*lp_rootdir()) {
644                 if (sys_chroot(lp_rootdir()) == 0)
645                         DEBUG(2,("Changed root to %s\n", lp_rootdir()));
646         }
647
648         lsarpcd_process();
649         close_sockets();
650         
651         exit_server("normal exit");
652         return(0);
653 }