1 /*
2    Unix SMB/Netbios implementation.
3    Version 3.0
4    printing backend routines
5    Copyright (C) Andrew Tridgell 1992-2000
6    Copyright (C) Jeremy Allison 2002
7    Copyright (C) Simo Sorce 2011
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 #include "includes.h"
24 #include "smbd/globals.h"
25 #include "include/messages.h"
26 #include "lib/util/util_process.h"
27 #include "printing.h"
28 #include "printing/pcap.h"
29 #include "printing/queue_process.h"
30 #include "locking/proto.h"
31 #include "smbd/smbd.h"
32 #include "rpc_server/rpc_config.h"
33 #include "printing/load.h"
34 #include "printing/spoolssd.h"
35 #include "rpc_server/spoolss/srv_spoolss_nt.h"
36 #include "auth.h"
37 #include "nt_printing.h"
38 #include "util_event.h"
39 
40 /**
41  * @brief Purge stale printers and reload from pre-populated pcap cache.
42  *
43  * This function should normally only be called as a callback on a successful
44  * pcap_cache_reload().
45  *
46  * This function can cause DELETION of printers and drivers from our registry,
47  * so calling it on a failed pcap reload may REMOVE permanently all printers
48  * and drivers.
49  *
50  * @param[in] ev        The event context.
51  *
52  * @param[in] msg_ctx   The messaging context.
53  */
delete_and_reload_printers_full(struct tevent_context * ev,struct messaging_context * msg_ctx)54 static void delete_and_reload_printers_full(struct tevent_context *ev,
55 					    struct messaging_context *msg_ctx)
56 {
57 	struct auth_session_info *session_info = NULL;
58 	struct spoolss_PrinterInfo2 *pinfo2 = NULL;
59 	const struct loadparm_substitution *lp_sub =
60 		loadparm_s3_global_substitution();
61 	int n_services;
62 	int pnum;
63 	int snum;
64 	const char *pname;
65 	const char *sname;
66 	NTSTATUS status;
67 
68 	n_services = lp_numservices();
69 	pnum = lp_servicenumber(PRINTERS_NAME);
70 
71 	status = make_session_info_system(talloc_tos(), &session_info);
72 	if (!NT_STATUS_IS_OK(status)) {
73 		DEBUG(3, ("reload_printers: "
74 			  "Could not create system session_info\n"));
75 		/* can't remove stale printers before we
76 		 * are fully initilized */
77 		return;
78 	}
79 
80 	/*
81 	 * Add default config for printers added to smb.conf file and remove
82 	 * stale printers
83 	 */
84 	for (snum = 0; snum < n_services; snum++) {
85 		/* avoid removing PRINTERS_NAME */
86 		if (snum == pnum) {
87 			continue;
88 		}
89 
90 		/* skip no-printer services */
91 		if (!snum_is_shared_printer(snum)) {
92 			continue;
93 		}
94 
95 		sname = lp_const_servicename(snum);
96 		pname = lp_printername(session_info, lp_sub, snum);
97 
98 		/* check printer, but avoid removing non-autoloaded printers */
99 		if (lp_autoloaded(snum) && !pcap_printername_ok(pname)) {
100 			DEBUG(3, ("removing stale printer %s\n", pname));
101 
102 			if (is_printer_published(session_info, session_info,
103 						 msg_ctx,
104 						 NULL,
105 						 lp_servicename(session_info,
106 								lp_sub,
107 								snum),
108 						 &pinfo2)) {
109 				nt_printer_publish(session_info,
110 						   session_info,
111 						   msg_ctx,
112 						   pinfo2,
113 						   DSPRINT_UNPUBLISH);
114 				TALLOC_FREE(pinfo2);
115 			}
116 			nt_printer_remove(session_info, session_info, msg_ctx,
117 					  pname);
118 		} else {
119 			DEBUG(8, ("Adding default registry entry for printer "
120 				  "[%s], if it doesn't exist.\n", sname));
121 			nt_printer_add(session_info, session_info, msg_ctx,
122 				       sname);
123 		}
124 	}
125 
126 	/* finally, purge old snums */
127 	delete_and_reload_printers();
128 
129 	TALLOC_FREE(session_info);
130 }
131 
132 
133 /****************************************************************************
134  Notify smbds of new printcap data
135 **************************************************************************/
reload_pcap_change_notify(struct tevent_context * ev,struct messaging_context * msg_ctx)136 static void reload_pcap_change_notify(struct tevent_context *ev,
137 			       struct messaging_context *msg_ctx)
138 {
139 	/*
140 	 * Reload the printers first in the background process so that
141 	 * newly added printers get default values created in the registry.
142 	 *
143 	 * This will block the process for some time (~1 sec per printer), but
144 	 * it doesn't block smbd's servering clients.
145 	 */
146 	delete_and_reload_printers_full(ev, msg_ctx);
147 
148 	messaging_send_all(msg_ctx, MSG_PRINTER_PCAP, NULL, 0);
149 }
150 
151 struct bq_state {
152 	struct tevent_context *ev;
153 	struct messaging_context *msg;
154 	struct idle_event *housekeep;
155 };
156 
print_queue_housekeeping(const struct timeval * now,void * pvt)157 static bool print_queue_housekeeping(const struct timeval *now, void *pvt)
158 {
159 	struct bq_state *state;
160 
161 	state = talloc_get_type_abort(pvt, struct bq_state);
162 
163 	DEBUG(5, ("print queue housekeeping\n"));
164 	pcap_cache_reload(state->ev, state->msg, &reload_pcap_change_notify);
165 
166 	return true;
167 }
168 
printing_subsystem_queue_tasks(struct bq_state * state)169 static bool printing_subsystem_queue_tasks(struct bq_state *state)
170 {
171 	uint32_t housekeeping_period = lp_printcap_cache_time();
172 
173 	/* cancel any existing housekeeping event */
174 	TALLOC_FREE(state->housekeep);
175 
176 	if ((housekeeping_period == 0) || !lp_load_printers()) {
177 		DEBUG(4, ("background print queue housekeeping disabled\n"));
178 		return true;
179 	}
180 
181 	state->housekeep = event_add_idle(state->ev, NULL,
182 					  timeval_set(housekeeping_period, 0),
183 					  "print_queue_housekeeping",
184 					  print_queue_housekeeping, state);
185 	if (state->housekeep == NULL) {
186 		DEBUG(0,("Could not add print_queue_housekeeping event\n"));
187 		return false;
188 	}
189 
190 	return true;
191 }
192 
bq_reopen_logs(char * logfile)193 static void bq_reopen_logs(char *logfile)
194 {
195 	if (logfile) {
196 		lp_set_logfile(logfile);
197 	}
198 	reopen_logs();
199 }
200 
bq_sig_term_handler(struct tevent_context * ev,struct tevent_signal * se,int signum,int count,void * siginfo,void * private_data)201 static void bq_sig_term_handler(struct tevent_context *ev,
202 				struct tevent_signal *se,
203 				int signum,
204 				int count,
205 				void *siginfo,
206 				void *private_data)
207 {
208 	exit_server_cleanly("termination signal");
209 }
210 
bq_setup_sig_term_handler(void)211 static void bq_setup_sig_term_handler(void)
212 {
213 	struct tevent_signal *se;
214 
215 	se = tevent_add_signal(global_event_context(),
216 			       global_event_context(),
217 			       SIGTERM, 0,
218 			       bq_sig_term_handler,
219 			       NULL);
220 	if (!se) {
221 		exit_server("failed to setup SIGTERM handler");
222 	}
223 }
224 
bq_sig_hup_handler(struct tevent_context * ev,struct tevent_signal * se,int signum,int count,void * siginfo,void * pvt)225 static void bq_sig_hup_handler(struct tevent_context *ev,
226 				struct tevent_signal *se,
227 				int signum,
228 				int count,
229 				void *siginfo,
230 				void *pvt)
231 {
232 	struct bq_state *state;
233 
234 	state = talloc_get_type_abort(pvt, struct bq_state);
235 	change_to_root_user();
236 
237 	DEBUG(1, ("Reloading pcap cache after SIGHUP\n"));
238 	pcap_cache_reload(state->ev, state->msg,
239 			  &reload_pcap_change_notify);
240 	printing_subsystem_queue_tasks(state);
241 	bq_reopen_logs(NULL);
242 }
243 
bq_setup_sig_hup_handler(struct bq_state * state)244 static void bq_setup_sig_hup_handler(struct bq_state *state)
245 {
246 	struct tevent_signal *se;
247 
248 	se = tevent_add_signal(state->ev, state->ev, SIGHUP, 0,
249 			       bq_sig_hup_handler, state);
250 	if (!se) {
251 		exit_server("failed to setup SIGHUP handler");
252 	}
253 }
254 
bq_sig_chld_handler(struct tevent_context * ev_ctx,struct tevent_signal * se,int signum,int count,void * siginfo,void * pvt)255 static void bq_sig_chld_handler(struct tevent_context *ev_ctx,
256 				struct tevent_signal *se,
257 				int signum, int count,
258 				void *siginfo, void *pvt)
259 {
260 	int status;
261 	pid_t pid;
262 
263 	pid = waitpid(-1, &status, WNOHANG);
264 	if (WIFEXITED(status)) {
265 		DEBUG(6, ("Bq child process %d terminated with %d\n",
266 			  (int)pid, WEXITSTATUS(status)));
267 	} else {
268 		DEBUG(3, ("Bq child process %d terminated abnormally\n",
269 			  (int)pid));
270 	}
271 }
272 
bq_setup_sig_chld_handler(struct tevent_context * ev_ctx)273 static void bq_setup_sig_chld_handler(struct tevent_context *ev_ctx)
274 {
275 	struct tevent_signal *se;
276 
277 	se = tevent_add_signal(ev_ctx, ev_ctx, SIGCHLD, 0,
278 				bq_sig_chld_handler, NULL);
279 	if (!se) {
280 		exit_server("failed to setup SIGCHLD handler");
281 	}
282 }
283 
bq_smb_conf_updated(struct messaging_context * msg_ctx,void * private_data,uint32_t msg_type,struct server_id server_id,DATA_BLOB * data)284 static void bq_smb_conf_updated(struct messaging_context *msg_ctx,
285 				void *private_data,
286 				uint32_t msg_type,
287 				struct server_id server_id,
288 				DATA_BLOB *data)
289 {
290 	struct bq_state *state;
291 
292 	state = talloc_get_type_abort(private_data, struct bq_state);
293 
294 	DEBUG(10,("smb_conf_updated: Got message saying smb.conf was "
295 		  "updated. Reloading.\n"));
296 	change_to_root_user();
297 	pcap_cache_reload(state->ev, msg_ctx, &reload_pcap_change_notify);
298 	printing_subsystem_queue_tasks(state);
299 }
300 
printing_pause_fd_handler(struct tevent_context * ev,struct tevent_fd * fde,uint16_t flags,void * private_data)301 static void printing_pause_fd_handler(struct tevent_context *ev,
302 				      struct tevent_fd *fde,
303 				      uint16_t flags,
304 				      void *private_data)
305 {
306 	/*
307 	 * If pause_pipe[1] is closed it means the parent smbd
308 	 * and children exited or aborted.
309 	 */
310 	exit_server_cleanly(NULL);
311 }
312 
313 /****************************************************************************
314 main thread of the background lpq updater
315 ****************************************************************************/
start_background_queue(struct tevent_context * ev,struct messaging_context * msg_ctx,char * logfile)316 pid_t start_background_queue(struct tevent_context *ev,
317 			     struct messaging_context *msg_ctx,
318 			     char *logfile)
319 {
320 	pid_t pid;
321 	struct bq_state *state;
322 
323 	/* Use local variables for this as we don't
324 	 * need to save the parent side of this, just
325 	 * ensure it closes when the process exits.
326 	 */
327 	int pause_pipe[2];
328 
329 	DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
330 
331 	if (pipe(pause_pipe) == -1) {
332 		DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) ));
333 		exit(1);
334 	}
335 
336 	/*
337 	 * Block signals before forking child as it will have to
338 	 * set its own handlers. Child will re-enable SIGHUP as
339 	 * soon as the handlers are set up.
340 	 */
341 	BlockSignals(true, SIGTERM);
342 	BlockSignals(true, SIGHUP);
343 
344 	pid = fork();
345 
346 	/* parent or error */
347 	if (pid != 0) {
348 		/* Re-enable SIGHUP before returnig */
349 		BlockSignals(false, SIGTERM);
350 		BlockSignals(false, SIGHUP);
351 		return pid;
352 	}
353 
354 	if (pid == -1) {
355 		DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) ));
356 		exit(1);
357 	}
358 
359 	if (pid == 0) {
360 		struct tevent_fd *fde;
361 		int ret;
362 		NTSTATUS status;
363 
364 		/* Child. */
365 		DEBUG(5,("start_background_queue: background LPQ thread started\n"));
366 
367 		close(pause_pipe[0]);
368 		pause_pipe[0] = -1;
369 
370 		status = smbd_reinit_after_fork(msg_ctx, ev, true, "lpqd");
371 
372 		if (!NT_STATUS_IS_OK(status)) {
373 			DEBUG(0,("reinit_after_fork() failed\n"));
374 			smb_panic("reinit_after_fork() failed");
375 		}
376 
377 		state = talloc_zero(NULL, struct bq_state);
378 		if (state == NULL) {
379 			exit(1);
380 		}
381 		state->ev = ev;
382 		state->msg = msg_ctx;
383 
384 		bq_reopen_logs(logfile);
385 		bq_setup_sig_term_handler();
386 		bq_setup_sig_hup_handler(state);
387 		bq_setup_sig_chld_handler(ev);
388 
389 		BlockSignals(false, SIGTERM);
390 		BlockSignals(false, SIGHUP);
391 
392 		if (!printing_subsystem_queue_tasks(state)) {
393 			exit(1);
394 		}
395 
396 		if (!locking_init()) {
397 			exit(1);
398 		}
399 		messaging_register(msg_ctx, state, MSG_SMB_CONF_UPDATED,
400 				   bq_smb_conf_updated);
401 		messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
402 				   print_queue_receive);
403 		/* Remove previous forwarder message set in parent. */
404 		messaging_deregister(msg_ctx, MSG_PRINTER_DRVUPGRADE, NULL);
405 
406 		messaging_register(msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE,
407 				   do_drv_upgrade_printer);
408 
409 		fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ,
410 				    printing_pause_fd_handler,
411 				    NULL);
412 		if (!fde) {
413 			DEBUG(0,("tevent_add_fd() failed for pause_pipe\n"));
414 			smb_panic("tevent_add_fd() failed for pause_pipe");
415 		}
416 
417 		pcap_cache_reload(ev, msg_ctx, &reload_pcap_change_notify);
418 
419 		DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
420 		ret = tevent_loop_wait(ev);
421 		/* should not be reached */
422 		DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
423 			 ret, (ret == 0) ? "out of events" : strerror(errno)));
424 		exit(1);
425 	}
426 
427 	close(pause_pipe[1]);
428 
429 	return pid;
430 }
431 
432 /* Run before the parent forks */
printing_subsystem_init(struct tevent_context * ev_ctx,struct messaging_context * msg_ctx,bool start_daemons,bool background_queue)433 bool printing_subsystem_init(struct tevent_context *ev_ctx,
434 			     struct messaging_context *msg_ctx,
435 			     bool start_daemons,
436 			     bool background_queue)
437 {
438 	pid_t pid = -1;
439 
440 	if (!print_backend_init(msg_ctx)) {
441 		return false;
442 	}
443 
444 	/* start spoolss daemon */
445 	/* start as a separate daemon only if enabled */
446 	if (start_daemons && rpc_spoolss_daemon() == RPC_DAEMON_FORK) {
447 
448 		pid = start_spoolssd(ev_ctx, msg_ctx);
449 
450 	} else if (start_daemons && background_queue) {
451 
452 		pid = start_background_queue(ev_ctx, msg_ctx, NULL);
453 
454 	} else {
455 		bool ret;
456 		struct bq_state *state;
457 
458 		state = talloc_zero(NULL, struct bq_state);
459 		if (state == NULL) {
460 			exit(1);
461 		}
462 		state->ev = ev_ctx;
463 		state->msg = msg_ctx;
464 
465 		ret = printing_subsystem_queue_tasks(state);
466 
467 		/* Publish nt printers, this requires a working winreg pipe */
468 		pcap_cache_reload(ev_ctx, msg_ctx,
469 				  &delete_and_reload_printers_full);
470 
471 		return ret;
472 	}
473 
474 	if (pid == -1) {
475 		return false;
476 	}
477 	background_lpq_updater_pid = pid;
478 
479 	return true;
480 }
481 
printing_subsystem_update(struct tevent_context * ev_ctx,struct messaging_context * msg_ctx,bool force)482 void printing_subsystem_update(struct tevent_context *ev_ctx,
483 			       struct messaging_context *msg_ctx,
484 			       bool force)
485 {
486 	if (background_lpq_updater_pid != -1) {
487 		load_printers();
488 		if (force) {
489 			/* Send a sighup to the background process.
490 			 * this will force it to reload printers */
491 			kill(background_lpq_updater_pid, SIGHUP);
492 		}
493 		return;
494 	}
495 
496 	pcap_cache_reload(ev_ctx, msg_ctx,
497 			  &delete_and_reload_printers_full);
498 }
499