1/*
2   Unix SMB/CIFS implementation.
3
4   Main SMB server routines
5
6   Copyright (C) Andrew Tridgell		1992-2005
7   Copyright (C) Martin Pool			2002
8   Copyright (C) Jelmer Vernooij		2002
9   Copyright (C) James J Myers 			2003 <myersjj@samba.org>
10
11   This program is free software; you can redistribute it and/or modify
12   it under the terms of the GNU General Public License as published by
13   the Free Software Foundation; either version 3 of the License, or
14   (at your option) any later version.
15
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20
21   You should have received a copy of the GNU General Public License
22   along with this program.  If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include "includes.h"
26#include "lib/events/events.h"
27#include "version.h"
28#include "lib/cmdline/popt_common.h"
29#include "system/dir.h"
30#include "system/filesys.h"
31#include "ntvfs/ntvfs.h"
32#include "ntptr/ntptr.h"
33#include "auth/gensec/gensec.h"
34#include "smbd/process_model.h"
35#include "param/secrets.h"
36#include "smbd/pidfile.h"
37#include "param/param.h"
38#include "dsdb/samdb/samdb.h"
39#include "auth/session.h"
40#include "lib/messaging/irpc.h"
41#include "librpc/gen_ndr/ndr_irpc.h"
42#include "cluster/cluster.h"
43
44/*
45  recursively delete a directory tree
46*/
47static void recursive_delete(const char *path)
48{
49	DIR *dir;
50	struct dirent *de;
51
52	dir = opendir(path);
53	if (!dir) {
54		return;
55	}
56
57	for (de=readdir(dir);de;de=readdir(dir)) {
58		char *fname;
59		struct stat st;
60
61		if (ISDOT(de->d_name) || ISDOTDOT(de->d_name)) {
62			continue;
63		}
64
65		fname = talloc_asprintf(path, "%s/%s", path, de->d_name);
66		if (stat(fname, &st) != 0) {
67			continue;
68		}
69		if (S_ISDIR(st.st_mode)) {
70			recursive_delete(fname);
71			talloc_free(fname);
72			continue;
73		}
74		if (unlink(fname) != 0) {
75			DEBUG(0,("Unabled to delete '%s' - %s\n",
76				 fname, strerror(errno)));
77			smb_panic("unable to cleanup tmp files");
78		}
79		talloc_free(fname);
80	}
81	closedir(dir);
82}
83
84/*
85  cleanup temporary files. This is the new alternative to
86  TDB_CLEAR_IF_FIRST. Unfortunately TDB_CLEAR_IF_FIRST is not
87  efficient on unix systems due to the lack of scaling of the byte
88  range locking system. So instead of putting the burden on tdb to
89  cleanup tmp files, this function deletes them.
90*/
91static void cleanup_tmp_files(struct loadparm_context *lp_ctx)
92{
93	char *path;
94	TALLOC_CTX *mem_ctx = talloc_new(NULL);
95
96	path = smbd_tmp_path(mem_ctx, lp_ctx, NULL);
97
98	recursive_delete(path);
99	talloc_free(mem_ctx);
100}
101
102static void sig_hup(int sig)
103{
104	debug_schedule_reopen_logs();
105}
106
107static void sig_term(int sig)
108{
109#if HAVE_GETPGRP
110	static int done_sigterm;
111	if (done_sigterm == 0 && getpgrp() == getpid()) {
112		DEBUG(0,("SIGTERM: killing children\n"));
113		done_sigterm = 1;
114		kill(-getpgrp(), SIGTERM);
115	}
116#endif
117	DEBUG(0,("Exiting pid %d on SIGTERM\n", (int)getpid()));
118	exit(0);
119}
120
121/*
122  setup signal masks
123*/
124static void setup_signals(void)
125{
126	/* we are never interested in SIGPIPE */
127	BlockSignals(true,SIGPIPE);
128
129#if defined(SIGFPE)
130	/* we are never interested in SIGFPE */
131	BlockSignals(true,SIGFPE);
132#endif
133
134	/* We are no longer interested in USR1 */
135	BlockSignals(true, SIGUSR1);
136
137#if defined(SIGUSR2)
138	/* We are no longer interested in USR2 */
139	BlockSignals(true,SIGUSR2);
140#endif
141
142	/* POSIX demands that signals are inherited. If the invoking process has
143	 * these signals masked, we will have problems, as we won't recieve them. */
144	BlockSignals(false, SIGHUP);
145	BlockSignals(false, SIGTERM);
146
147	CatchSignal(SIGHUP, sig_hup);
148	CatchSignal(SIGTERM, sig_term);
149}
150
151/*
152  handle io on stdin
153*/
154static void server_stdin_handler(struct tevent_context *event_ctx, struct tevent_fd *fde,
155				 uint16_t flags, void *private_data)
156{
157	const char *binary_name = (const char *)private_data;
158	uint8_t c;
159	if (read(0, &c, 1) == 0) {
160		DEBUG(0,("%s: EOF on stdin - terminating\n", binary_name));
161#if HAVE_GETPGRP
162		if (getpgrp() == getpid()) {
163			DEBUG(0,("Sending SIGTERM from pid %d\n", (int)getpid()));
164			kill(-getpgrp(), SIGTERM);
165		}
166#endif
167		exit(0);
168	}
169}
170
171/*
172  die if the user selected maximum runtime is exceeded
173*/
174_NORETURN_ static void max_runtime_handler(struct tevent_context *ev,
175					   struct tevent_timer *te,
176					   struct timeval t, void *private_data)
177{
178	const char *binary_name = (const char *)private_data;
179	DEBUG(0,("%s: maximum runtime exceeded - terminating\n", binary_name));
180	exit(0);
181}
182
183/*
184  pre-open the sam ldb to ensure the schema has been loaded. This
185  saves a lot of time in child processes
186 */
187static void prime_samdb_schema(struct tevent_context *event_ctx)
188{
189	TALLOC_CTX *samdb_context;
190	samdb_context = talloc_new(event_ctx);
191	samdb_connect(samdb_context, event_ctx, cmdline_lp_ctx, system_session(samdb_context, cmdline_lp_ctx));
192	talloc_free(samdb_context);
193}
194
195
196/*
197  called when a fatal condition occurs in a child task
198 */
199static NTSTATUS samba_terminate(struct irpc_message *msg,
200				struct samba_terminate *r)
201{
202	DEBUG(0,("samba_terminate: %s\n", r->in.reason));
203	exit(1);
204}
205
206/*
207  setup messaging for the top level samba (parent) task
208 */
209static NTSTATUS setup_parent_messaging(struct tevent_context *event_ctx,
210				       struct loadparm_context *lp_ctx)
211{
212	struct messaging_context *msg;
213	NTSTATUS status;
214
215	msg = messaging_init(talloc_autofree_context(),
216			     lp_messaging_path(event_ctx, lp_ctx),
217			     cluster_id(0, SAMBA_PARENT_TASKID),
218			     lp_iconv_convenience(lp_ctx),
219			     event_ctx);
220	NT_STATUS_HAVE_NO_MEMORY(msg);
221
222	irpc_add_name(msg, "samba");
223
224	status = IRPC_REGISTER(msg, irpc, SAMBA_TERMINATE,
225			       samba_terminate, NULL);
226
227	return status;
228}
229
230
231
232/*
233 main server.
234*/
235static int binary_smbd_main(const char *binary_name, int argc, const char *argv[])
236{
237	bool opt_daemon = false;
238	bool opt_interactive = false;
239	int opt;
240	poptContext pc;
241	extern NTSTATUS server_service_wrepl_init(void);
242	extern NTSTATUS server_service_kdc_init(void);
243	extern NTSTATUS server_service_ldap_init(void);
244	extern NTSTATUS server_service_web_init(void);
245	extern NTSTATUS server_service_ldap_init(void);
246	extern NTSTATUS server_service_winbind_init(void);
247	extern NTSTATUS server_service_nbtd_init(void);
248	extern NTSTATUS server_service_auth_init(void);
249	extern NTSTATUS server_service_cldapd_init(void);
250	extern NTSTATUS server_service_smb_init(void);
251	extern NTSTATUS server_service_drepl_init(void);
252	extern NTSTATUS server_service_kcc_init(void);
253	extern NTSTATUS server_service_rpc_init(void);
254	extern NTSTATUS server_service_ntp_signd_init(void);
255	extern NTSTATUS server_service_samba3_smb_init(void);
256	init_module_fn static_init[] = { STATIC_service_MODULES };
257	init_module_fn *shared_init;
258	struct tevent_context *event_ctx;
259	uint16_t stdin_event_flags;
260	NTSTATUS status;
261	const char *model = "standard";
262	int max_runtime = 0;
263	enum {
264		OPT_DAEMON = 1000,
265		OPT_INTERACTIVE,
266		OPT_PROCESS_MODEL
267	};
268	struct poptOption long_options[] = {
269		POPT_AUTOHELP
270		{"daemon", 'D', POPT_ARG_NONE, NULL, OPT_DAEMON,
271		 "Become a daemon (default)", NULL },
272		{"interactive",	'i', POPT_ARG_NONE, NULL, OPT_INTERACTIVE,
273		 "Run interactive (not a daemon)", NULL},
274		{"model", 'M', POPT_ARG_STRING,	NULL, OPT_PROCESS_MODEL,
275		 "Select process model", "MODEL"},
276		{"maximum-runtime",0, POPT_ARG_INT, &max_runtime, 0,
277		 "set maximum runtime of the server process, till autotermination", "seconds"},
278		POPT_COMMON_SAMBA
279		POPT_COMMON_VERSION
280		{ NULL }
281	};
282
283	pc = poptGetContext(binary_name, argc, argv, long_options, 0);
284	while((opt = poptGetNextOpt(pc)) != -1) {
285		switch(opt) {
286		case OPT_DAEMON:
287			opt_daemon = true;
288			break;
289		case OPT_INTERACTIVE:
290			opt_interactive = true;
291			break;
292		case OPT_PROCESS_MODEL:
293			model = poptGetOptArg(pc);
294			break;
295		default:
296			fprintf(stderr, "\nInvalid option %s: %s\n\n",
297				  poptBadOption(pc, 0), poptStrerror(opt));
298			poptPrintUsage(pc, stderr, 0);
299			exit(1);
300		}
301	}
302
303	if (opt_daemon && opt_interactive) {
304		fprintf(stderr,"\nERROR: "
305			  "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
306		poptPrintUsage(pc, stderr, 0);
307		exit(1);
308	} else if (!opt_interactive) {
309		/* default is --daemon */
310		opt_daemon = true;
311	}
312
313	poptFreeContext(pc);
314
315	setup_logging(binary_name, opt_interactive?DEBUG_STDOUT:DEBUG_FILE);
316	setup_signals();
317
318	/* we want total control over the permissions on created files,
319	   so set our umask to 0 */
320	umask(0);
321
322	DEBUG(0,("%s version %s started.\n", binary_name, SAMBA_VERSION_STRING));
323	DEBUGADD(0,("Copyright Andrew Tridgell and the Samba Team 1992-2009\n"));
324
325	if (sizeof(uint16_t) < 2 || sizeof(uint32_t) < 4 || sizeof(uint64_t) < 8) {
326		DEBUG(0,("ERROR: Samba is not configured correctly for the word size on your machine\n"));
327		DEBUGADD(0,("sizeof(uint16_t) = %u, sizeof(uint32_t) %u, sizeof(uint64_t) = %u\n",
328			    (unsigned int)sizeof(uint16_t), (unsigned int)sizeof(uint32_t), (unsigned int)sizeof(uint64_t)));
329		exit(1);
330	}
331
332	if (opt_daemon) {
333		DEBUG(3,("Becoming a daemon.\n"));
334		become_daemon(true, false);
335	}
336
337	cleanup_tmp_files(cmdline_lp_ctx);
338
339	if (!directory_exist(lp_lockdir(cmdline_lp_ctx))) {
340		mkdir(lp_lockdir(cmdline_lp_ctx), 0755);
341	}
342
343	pidfile_create(lp_piddir(cmdline_lp_ctx), binary_name);
344
345	/* Do *not* remove this, until you have removed
346	 * passdb/secrets.c, and proved that Samba still builds... */
347	/* Setup the SECRETS subsystem */
348	if (secrets_init(talloc_autofree_context(), cmdline_lp_ctx) == NULL) {
349		exit(1);
350	}
351
352	gensec_init(cmdline_lp_ctx); /* FIXME: */
353
354	ntptr_init(cmdline_lp_ctx);	/* FIXME: maybe run this in the initialization function
355						of the spoolss RPC server instead? */
356
357	ntvfs_init(cmdline_lp_ctx); 	/* FIXME: maybe run this in the initialization functions
358						of the SMB[,2] server instead? */
359
360	process_model_init(cmdline_lp_ctx);
361
362	shared_init = load_samba_modules(NULL, cmdline_lp_ctx, "service");
363
364	run_init_functions(static_init);
365	run_init_functions(shared_init);
366
367	talloc_free(shared_init);
368
369	/* the event context is the top level structure in smbd. Everything else
370	   should hang off that */
371	event_ctx = s4_event_context_init(talloc_autofree_context());
372
373	if (event_ctx == NULL) {
374		DEBUG(0,("Initializing event context failed\n"));
375		return 1;
376	}
377
378	if (opt_interactive) {
379		/* terminate when stdin goes away */
380		stdin_event_flags = TEVENT_FD_READ;
381	} else {
382		/* stay alive forever */
383		stdin_event_flags = 0;
384	}
385
386	/* catch EOF on stdin */
387#ifdef SIGTTIN
388	signal(SIGTTIN, SIG_IGN);
389#endif
390	tevent_add_fd(event_ctx, event_ctx, 0, stdin_event_flags,
391		      server_stdin_handler,
392		      discard_const(binary_name));
393
394	if (max_runtime) {
395		tevent_add_timer(event_ctx, event_ctx,
396				 timeval_current_ofs(max_runtime, 0),
397				 max_runtime_handler,
398				 discard_const(binary_name));
399	}
400
401	prime_samdb_schema(event_ctx);
402
403	status = setup_parent_messaging(event_ctx, cmdline_lp_ctx);
404	if (!NT_STATUS_IS_OK(status)) {
405		DEBUG(0,("Failed to setup parent messaging - %s\n", nt_errstr(status)));
406		return 1;
407	}
408
409	DEBUG(0,("%s: using '%s' process model\n", binary_name, model));
410
411	status = server_service_startup(event_ctx, cmdline_lp_ctx, model,
412					lp_server_services(cmdline_lp_ctx));
413	if (!NT_STATUS_IS_OK(status)) {
414		DEBUG(0,("Starting Services failed - %s\n", nt_errstr(status)));
415		return 1;
416	}
417
418	/* wait for events - this is where smbd sits for most of its
419	   life */
420	tevent_loop_wait(event_ctx);
421
422	/* as everything hangs off this event context, freeing it
423	   should initiate a clean shutdown of all services */
424	talloc_free(event_ctx);
425
426	return 0;
427}
428
429int main(int argc, const char *argv[])
430{
431	return binary_smbd_main("samba", argc, argv);
432}
433