s3:libads: Allocate ads->auth.password under ADS_STRUCT talloc context
[samba.git] / source3 / printing / samba-bgqd.c
1 /*
2  *  Printing background queue helper
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "replace.h"
19 #include "system/filesys.h"
20 #include "lib/util/server_id.h"
21 #include "source3/locking/share_mode_lock.h"
22 #include "source3/param/loadparm.h"
23 #include "source3/param/param_proto.h"
24 #include "lib/cmdline/cmdline.h"
25 #include "lib/cmdline/closefrom_except.h"
26 #include "lib/util/talloc_stack.h"
27 #include "lib/util/debug.h"
28 #include "lib/util/signal.h"
29 #include "lib/util/fault.h"
30 #include "lib/util/become_daemon.h"
31 #include "lib/util/charset/charset.h"
32 #include "lib/util/samba_util.h"
33 #include "lib/util/sys_rw.h"
34 #include "lib/util/pidfile.h"
35 #include "lib/async_req/async_sock.h"
36 #include "dynconfig/dynconfig.h"
37 #include "source3/lib/global_contexts.h"
38 #include "messages.h"
39 #include "nsswitch/winbind_client.h"
40 #include "source3/include/auth.h"
41 #include "source3/lib/util_procid.h"
42 #include "source3/auth/proto.h"
43 #include "source3/printing/queue_process.h"
44 #include "source3/lib/substitute.h"
45
46 static void watch_handler(struct tevent_req *req)
47 {
48         bool *pdone = tevent_req_callback_data_void(req);
49         *pdone = true;
50 }
51
52 static void bgqd_sig_term_handler(
53         struct tevent_context *ev,
54         struct tevent_signal *se,
55         int signum,
56         int count,
57         void *siginfo,
58         void *private_data)
59 {
60         bool *pdone = private_data;
61         *pdone = true;
62 }
63
64 static bool ready_signal_filter(
65         struct messaging_rec *rec, void *private_data)
66 {
67         pid_t pid = getpid();
68         ssize_t written;
69
70         if (rec->msg_type != MSG_DAEMON_READY_FD) {
71                 return false;
72         }
73         if (rec->num_fds != 1) {
74                 return false;
75         }
76
77         written = sys_write(rec->fds[0], &pid, sizeof(pid));
78         if (written != sizeof(pid)) {
79                 DBG_ERR("Could not write pid: %s\n", strerror(errno));
80         }
81
82         return false;
83 }
84
85 static int samba_bgqd_pidfile_create(
86         struct messaging_context *msg_ctx,
87         const char *progname,
88         int ready_signal_fd)
89 {
90         const char *piddir = lp_pid_directory();
91         size_t len = strlen(piddir) + strlen(progname) + 6;
92         char pidFile[len];
93         pid_t existing_pid;
94         int fd, ret;
95
96         snprintf(pidFile,
97                  sizeof(pidFile),
98                  "%s/%s.pid",
99                  piddir, progname);
100
101         ret = pidfile_path_create(pidFile, &fd, &existing_pid);
102         if (ret == 0) {
103                 struct tevent_req *ready_signal_req = NULL;
104
105                 /*
106                  * Listen for fd's sent via MSG_DAEMON_READY_FD:
107                  * Multiple instances of this process might have raced
108                  * for creating the pidfile. Make sure the parent does
109                  * not suffer from this race, reply on behalf of the
110                  * loser of this race.
111                  */
112
113                 ready_signal_req = messaging_filtered_read_send(
114                         msg_ctx,
115                         messaging_tevent_context(msg_ctx),
116                         msg_ctx,
117                         ready_signal_filter,
118                         NULL);
119                 if (ready_signal_req == NULL) {
120                         DBG_DEBUG("messaging_filtered_read_send failed\n");
121                         pidfile_unlink(piddir, progname);
122                         pidfile_fd_close(fd);
123                         return ENOMEM;
124                 }
125
126                 /* leak fd */
127                 return 0;
128         }
129
130         if (ret != EAGAIN) {
131                 DBG_DEBUG("pidfile_path_create() failed: %s\n",
132                           strerror(ret));
133                 return ret;
134         }
135
136         DBG_DEBUG("%s pid %d exists\n", progname, (int)existing_pid);
137
138         if (ready_signal_fd != -1) {
139                 /*
140                  * We lost the race for the pidfile, but someone else
141                  * can report readiness on our behalf.
142                  */
143                 NTSTATUS status = messaging_send_iov(
144                         msg_ctx,
145                         pid_to_procid(existing_pid),
146                         MSG_DAEMON_READY_FD,
147                         NULL,
148                         0,
149                         &ready_signal_fd,
150                         1);
151                 if (!NT_STATUS_IS_OK(status)) {
152                         DBG_DEBUG("Could not send ready_signal_fd: %s\n",
153                                   nt_errstr(status));
154                 }
155         }
156
157         return EAGAIN;
158 }
159
160 int main(int argc, const char *argv[])
161 {
162         struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
163         const struct loadparm_substitution *lp_sub =
164                 loadparm_s3_global_substitution();
165         const char *progname = getprogname();
166         TALLOC_CTX *frame = NULL;
167         poptContext pc;
168         struct messaging_context *msg_ctx = NULL;
169         struct tevent_context *ev = NULL;
170         struct tevent_req *watch_req = NULL;
171         struct tevent_signal *sigterm_handler = NULL;
172         struct bq_state *bq = NULL;
173         int log_stdout = 0;
174         int ready_signal_fd = -1;
175         int watch_fd = -1;
176         NTSTATUS status;
177         int ret;
178         bool ok;
179         bool done = false;
180         int exitcode = 1;
181
182         struct poptOption long_options[] = {
183                 POPT_AUTOHELP
184                 POPT_COMMON_SAMBA
185                 POPT_COMMON_DAEMON
186
187                 /*
188                  * File descriptor to write the PID of the helper
189                  * process to
190                  */
191                 {
192                         .longName   = "ready-signal-fd",
193                         .argInfo    = POPT_ARG_INT,
194                         .arg        = &ready_signal_fd,
195                         .descrip    = "Fd to signal readiness to" ,
196                 },
197
198                 /*
199                  * Read end of a pipe held open by the parent
200                  * smbd. Exit this process when it becomes readable.
201                  */
202                 {
203                         .longName   = "parent-watch-fd",
204                         .argInfo    = POPT_ARG_INT,
205                         .arg        = &watch_fd,
206                         .descrip    = "Fd to watch for exiting",
207                 },
208                 POPT_TABLEEND
209         };
210
211         {
212                 const char *fd_params[] = {
213                         "ready-signal-fd", "parent-watch-fd",
214                 };
215
216                 closefrom_except_fd_params(
217                         3, ARRAY_SIZE(fd_params), fd_params, argc, argv);
218         }
219
220         talloc_enable_null_tracking();
221         frame = talloc_stackframe();
222         umask(0);
223         set_remote_machine_name("smbd-bgqd", true);
224
225         ok = samba_cmdline_init(frame,
226                                 SAMBA_CMDLINE_CONFIG_SERVER,
227                                 true /* require_smbconf */);
228         if (!ok) {
229                 DBG_ERR("Failed to setup cmdline parser!\n");
230                 exit(ENOMEM);
231         }
232
233         cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
234
235         pc = samba_popt_get_context(progname,
236                                     argc,
237                                     argv,
238                                     long_options,
239                                     0);
240         if (pc == NULL) {
241                 DBG_ERR("Failed to get popt context!\n");
242                 exit(ENOMEM);
243         }
244
245         ret = poptGetNextOpt(pc);
246         if (ret < -1) {
247                 fprintf(stderr, "invalid options: %s\n", poptStrerror(ret));
248                 goto done;
249         }
250
251         poptFreeContext(pc);
252
253         log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
254
255         /* main process will notify systemd */
256         daemon_sd_notifications(false);
257
258         if (!cmdline_daemon_cfg->fork) {
259                 daemon_status(progname, "Starting process ... ");
260         } else {
261                 become_daemon(true,
262                               cmdline_daemon_cfg->no_process_group,
263                               log_stdout);
264         }
265
266         BlockSignals(true, SIGPIPE);
267
268         smb_init_locale();
269         dump_core_setup(progname, lp_logfile(frame, lp_sub));
270
271         msg_ctx = global_messaging_context();
272         if (msg_ctx == NULL) {
273                 DBG_ERR("messaging_init() failed\n");
274                 goto done;
275         }
276         ev = messaging_tevent_context(msg_ctx);
277
278         ret = samba_bgqd_pidfile_create(msg_ctx, progname, ready_signal_fd);
279         if (ret != 0) {
280                 goto done;
281         }
282
283         if (watch_fd != -1) {
284                 watch_req = wait_for_read_send(ev, ev, watch_fd, true);
285                 if (watch_req == NULL) {
286                         fprintf(stderr, "tevent_add_fd failed\n");
287                         goto done;
288                 }
289                 tevent_req_set_callback(watch_req, watch_handler, &done);
290         }
291
292         (void)winbind_off();
293         ok = init_guest_session_info(frame);
294         (void)winbind_on();
295         if (!ok) {
296                 DBG_ERR("init_guest_session_info failed\n");
297                 goto done;
298         }
299
300         (void)winbind_off();
301         status = init_system_session_info(frame);
302         (void)winbind_on();
303         if (!NT_STATUS_IS_OK(status)) {
304                 DBG_ERR("init_system_session_info failed: %s\n",
305                         nt_errstr(status));
306                 goto done;
307         }
308
309         sigterm_handler = tevent_add_signal(
310                 ev, frame, SIGTERM, 0, bgqd_sig_term_handler, &done);
311         if (sigterm_handler == NULL) {
312                 DBG_ERR("Could not install SIGTERM handler\n");
313                 goto done;
314         }
315
316         bq = register_printing_bq_handlers(frame, msg_ctx);
317         if (bq == NULL) {
318                 DBG_ERR("Could not register bq handlers\n");
319                 goto done;
320         }
321
322         ok = locking_init();
323         if (!ok) {
324                 DBG_ERR("locking_init failed\n");
325                 goto done;
326         }
327
328         if (ready_signal_fd != -1) {
329                 pid_t pid = getpid();
330                 ssize_t written;
331
332                 written = sys_write(ready_signal_fd, &pid, sizeof(pid));
333                 if (written != sizeof(pid)) {
334                         DBG_ERR("Reporting readiness failed\n");
335                         goto done;
336                 }
337                 close(ready_signal_fd);
338                 ready_signal_fd = -1;
339         }
340
341         while (!done) {
342                 TALLOC_CTX *tmp = talloc_stackframe();
343                 ret = tevent_loop_once(ev);
344                 TALLOC_FREE(tmp);
345                 if (ret != 0) {
346                         DBG_ERR("tevent_loop_once failed\n");
347                         break;
348                 }
349         }
350
351         exitcode = 0;
352 done:
353         TALLOC_FREE(watch_req);
354         TALLOC_FREE(bq);
355         TALLOC_FREE(sigterm_handler);
356         global_messaging_context_free();
357         TALLOC_FREE(frame);
358         return exitcode;
359 }