cdd6d4319cbde3d40c5989eba2d321ef53313511
[metze/samba-autobuild/.git] / source3 / winbindd / winbindd.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind daemon for ntdom nss module
5
6    Copyright (C) by Tim Potter 2000-2002
7    Copyright (C) Andrew Tridgell 2002
8    Copyright (C) Jelmer Vernooij 2003
9    Copyright (C) Volker Lendecke 2004
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/cmdline/cmdline.h"
27 #include "winbindd.h"
28 #include "nsswitch/winbind_client.h"
29 #include "nsswitch/wb_reqtrans.h"
30 #include "ntdomain.h"
31 #include "librpc/rpc/dcesrv_core.h"
32 #include "librpc/gen_ndr/ndr_lsa_scompat.h"
33 #include "librpc/gen_ndr/ndr_samr_scompat.h"
34 #include "librpc/gen_ndr/ndr_winbind_scompat.h"
35 #include "secrets.h"
36 #include "rpc_client/cli_netlogon.h"
37 #include "idmap.h"
38 #include "lib/addrchange.h"
39 #include "auth.h"
40 #include "messages.h"
41 #include "../lib/util/pidfile.h"
42 #include "util_cluster.h"
43 #include "source4/lib/messaging/irpc.h"
44 #include "source4/lib/messaging/messaging.h"
45 #include "lib/param/param.h"
46 #include "lib/async_req/async_sock.h"
47 #include "libsmb/samlogon_cache.h"
48 #include "libcli/auth/netlogon_creds_cli.h"
49 #include "passdb.h"
50 #include "lib/util/tevent_req_profile.h"
51 #include "lib/gencache.h"
52 #include "rpc_server/rpc_config.h"
53 #include "lib/global_contexts.h"
54 #include "source3/lib/substitute.h"
55 #include "winbindd_traceid.h"
56 #include "lib/util/util_process.h"
57
58 #undef DBGC_CLASS
59 #define DBGC_CLASS DBGC_WINBIND
60
61 #define SCRUB_CLIENTS_INTERVAL 5
62
63 static bool client_is_idle(struct winbindd_cli_state *state);
64 static void remove_client(struct winbindd_cli_state *state);
65
66 static bool interactive = False;
67
68 /* Reload configuration */
69
70
71
72 static void winbindd_status(void)
73 {
74         struct winbindd_cli_state *tmp;
75
76         DEBUG(0, ("winbindd status:\n"));
77
78         /* Print client state information */
79
80         DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
81
82         if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
83                 DEBUG(2, ("\tclient list:\n"));
84                 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
85                         DEBUGADD(2, ("\t\tpid %lu, sock %d (%s)\n",
86                                      (unsigned long)tmp->pid, tmp->sock,
87                                      client_is_idle(tmp) ? "idle" : "active"));
88                 }
89         }
90 }
91
92 /*
93   handle stdin becoming readable when we are in --foreground mode
94  */
95 static void winbindd_stdin_handler(struct tevent_context *ev,
96                                struct tevent_fd *fde,
97                                uint16_t flags,
98                                void *private_data)
99 {
100         char c;
101         if (read(0, &c, 1) != 1) {
102                 bool *is_parent = talloc_get_type_abort(private_data, bool);
103
104                 /* we have reached EOF on stdin, which means the
105                    parent has exited. Shutdown the server */
106                 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
107                          (int)*is_parent));
108                 winbindd_terminate(*is_parent);
109         }
110 }
111
112 bool winbindd_setup_stdin_handler(bool parent, bool foreground)
113 {
114         bool *is_parent;
115
116         if (foreground) {
117                 struct stat st;
118
119                 is_parent = talloc(global_event_context(), bool);
120                 if (!is_parent) {
121                         return false;
122                 }
123
124                 *is_parent = parent;
125
126                 /* if we are running in the foreground then look for
127                    EOF on stdin, and exit if it happens. This allows
128                    us to die if the parent process dies
129                    Only do this on a pipe or socket, no other device.
130                 */
131                 if (fstat(0, &st) != 0) {
132                         return false;
133                 }
134                 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
135                         tevent_add_fd(global_event_context(),
136                                         is_parent,
137                                         0,
138                                         TEVENT_FD_READ,
139                                         winbindd_stdin_handler,
140                                         is_parent);
141                 }
142         }
143
144         return true;
145 }
146
147 static void winbindd_sig_chld_handler(struct tevent_context *ev,
148                                       struct tevent_signal *se,
149                                       int signum,
150                                       int count,
151                                       void *siginfo,
152                                       void *private_data)
153 {
154         pid_t pid;
155
156         while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
157                 winbind_child_died(pid);
158         }
159 }
160
161 static bool winbindd_setup_sig_chld_handler(void)
162 {
163         struct tevent_signal *se;
164
165         se = tevent_add_signal(global_event_context(),
166                                global_event_context(),
167                                SIGCHLD, 0,
168                                winbindd_sig_chld_handler,
169                                NULL);
170         if (!se) {
171                 return false;
172         }
173
174         return true;
175 }
176
177 static void winbindd_sig_usr2_handler(struct tevent_context *ev,
178                                       struct tevent_signal *se,
179                                       int signum,
180                                       int count,
181                                       void *siginfo,
182                                       void *private_data)
183 {
184         winbindd_status();
185 }
186
187 static bool winbindd_setup_sig_usr2_handler(void)
188 {
189         struct tevent_signal *se;
190
191         se = tevent_add_signal(global_event_context(),
192                                global_event_context(),
193                                SIGUSR2, 0,
194                                winbindd_sig_usr2_handler,
195                                NULL);
196         if (!se) {
197                 return false;
198         }
199
200         return true;
201 }
202
203 /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
204 static void msg_shutdown(struct messaging_context *msg,
205                          void *private_data,
206                          uint32_t msg_type,
207                          struct server_id server_id,
208                          DATA_BLOB *data)
209 {
210         /* only the parent waits for this message */
211         DEBUG(0,("Got shutdown message\n"));
212         winbindd_terminate(true);
213 }
214
215
216 static void winbind_msg_validate_cache(struct messaging_context *msg_ctx,
217                                        void *private_data,
218                                        uint32_t msg_type,
219                                        struct server_id server_id,
220                                        DATA_BLOB *data)
221 {
222         uint8_t ret;
223         pid_t child_pid;
224         NTSTATUS status;
225
226         DEBUG(10, ("winbindd_msg_validate_cache: got validate-cache "
227                    "message.\n"));
228
229         /*
230          * call the validation code from a child:
231          * so we don't block the main winbindd and the validation
232          * code can safely use fork/waitpid...
233          */
234         child_pid = fork();
235
236         if (child_pid == -1) {
237                 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
238                           strerror(errno)));
239                 return;
240         }
241
242         if (child_pid != 0) {
243                 /* parent */
244                 DEBUG(5, ("winbind_msg_validate_cache: child created with "
245                           "pid %d.\n", (int)child_pid));
246                 return;
247         }
248
249         /* child */
250
251         status = winbindd_reinit_after_fork(NULL, NULL);
252         if (!NT_STATUS_IS_OK(status)) {
253                 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
254                           nt_errstr(status)));
255                 _exit(0);
256         }
257
258         /* install default SIGCHLD handler: validation code uses fork/waitpid */
259         CatchSignal(SIGCHLD, SIG_DFL);
260
261         process_set_title("wb: check cache", "validate cache child");
262
263         ret = (uint8_t)winbindd_validate_cache_nobackup();
264         DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
265         messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
266                            (size_t)1);
267         _exit(0);
268 }
269
270 static struct winbindd_bool_dispatch_table {
271         enum winbindd_cmd cmd;
272         bool (*fn)(struct winbindd_cli_state *state);
273         const char *cmd_name;
274 } bool_dispatch_table[] = {
275         { WINBINDD_INTERFACE_VERSION,
276           winbindd_interface_version,
277           "INTERFACE_VERSION" },
278         { WINBINDD_INFO,
279           winbindd_info,
280           "INFO" },
281         { WINBINDD_PING,
282           winbindd_ping,
283           "PING" },
284         { WINBINDD_DOMAIN_NAME,
285           winbindd_domain_name,
286           "DOMAIN_NAME" },
287         { WINBINDD_NETBIOS_NAME,
288           winbindd_netbios_name,
289           "NETBIOS_NAME" },
290         { WINBINDD_DC_INFO,
291           winbindd_dc_info,
292           "DC_INFO" },
293         { WINBINDD_CCACHE_NTLMAUTH,
294           winbindd_ccache_ntlm_auth,
295           "NTLMAUTH" },
296         { WINBINDD_CCACHE_SAVE,
297           winbindd_ccache_save,
298           "CCACHE_SAVE" },
299         { WINBINDD_PRIV_PIPE_DIR,
300           winbindd_priv_pipe_dir,
301           "WINBINDD_PRIV_PIPE_DIR" },
302         { WINBINDD_LIST_TRUSTDOM,
303           winbindd_list_trusted_domains,
304           "LIST_TRUSTDOM" },
305 };
306
307 struct winbindd_async_dispatch_table {
308         enum winbindd_cmd cmd;
309         const char *cmd_name;
310         struct tevent_req *(*send_req)(TALLOC_CTX *mem_ctx,
311                                        struct tevent_context *ev,
312                                        struct winbindd_cli_state *cli,
313                                        struct winbindd_request *request);
314         NTSTATUS (*recv_req)(struct tevent_req *req,
315                              struct winbindd_response *presp);
316 };
317
318 static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
319         { WINBINDD_LOOKUPSID, "LOOKUPSID",
320           winbindd_lookupsid_send, winbindd_lookupsid_recv },
321         { WINBINDD_LOOKUPSIDS, "LOOKUPSIDS",
322           winbindd_lookupsids_send, winbindd_lookupsids_recv },
323         { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
324           winbindd_lookupname_send, winbindd_lookupname_recv },
325         { WINBINDD_SIDS_TO_XIDS, "SIDS_TO_XIDS",
326           winbindd_sids_to_xids_send, winbindd_sids_to_xids_recv },
327         { WINBINDD_XIDS_TO_SIDS, "XIDS_TO_SIDS",
328           winbindd_xids_to_sids_send, winbindd_xids_to_sids_recv },
329         { WINBINDD_GETPWSID, "GETPWSID",
330           winbindd_getpwsid_send, winbindd_getpwsid_recv },
331         { WINBINDD_GETPWNAM, "GETPWNAM",
332           winbindd_getpwnam_send, winbindd_getpwnam_recv },
333         { WINBINDD_GETPWUID, "GETPWUID",
334           winbindd_getpwuid_send, winbindd_getpwuid_recv },
335         { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
336           winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
337         { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
338           winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
339         { WINBINDD_GETGROUPS, "GETGROUPS",
340           winbindd_getgroups_send, winbindd_getgroups_recv },
341         { WINBINDD_SHOW_SEQUENCE, "SHOW_SEQUENCE",
342           winbindd_show_sequence_send, winbindd_show_sequence_recv },
343         { WINBINDD_GETGRGID, "GETGRGID",
344           winbindd_getgrgid_send, winbindd_getgrgid_recv },
345         { WINBINDD_GETGRNAM, "GETGRNAM",
346           winbindd_getgrnam_send, winbindd_getgrnam_recv },
347         { WINBINDD_GETUSERSIDS, "GETUSERSIDS",
348           winbindd_getusersids_send, winbindd_getusersids_recv },
349         { WINBINDD_LOOKUPRIDS, "LOOKUPRIDS",
350           winbindd_lookuprids_send, winbindd_lookuprids_recv },
351         { WINBINDD_SETPWENT, "SETPWENT",
352           winbindd_setpwent_send, winbindd_setpwent_recv },
353         { WINBINDD_GETPWENT, "GETPWENT",
354           winbindd_getpwent_send, winbindd_getpwent_recv },
355         { WINBINDD_ENDPWENT, "ENDPWENT",
356           winbindd_endpwent_send, winbindd_endpwent_recv },
357         { WINBINDD_DSGETDCNAME, "DSGETDCNAME",
358           winbindd_dsgetdcname_send, winbindd_dsgetdcname_recv },
359         { WINBINDD_GETDCNAME, "GETDCNAME",
360           winbindd_getdcname_send, winbindd_getdcname_recv },
361         { WINBINDD_SETGRENT, "SETGRENT",
362           winbindd_setgrent_send, winbindd_setgrent_recv },
363         { WINBINDD_GETGRENT, "GETGRENT",
364           winbindd_getgrent_send, winbindd_getgrent_recv },
365         { WINBINDD_ENDGRENT, "ENDGRENT",
366           winbindd_endgrent_send, winbindd_endgrent_recv },
367         { WINBINDD_LIST_USERS, "LIST_USERS",
368           winbindd_list_users_send, winbindd_list_users_recv },
369         { WINBINDD_LIST_GROUPS, "LIST_GROUPS",
370           winbindd_list_groups_send, winbindd_list_groups_recv },
371         { WINBINDD_CHECK_MACHACC, "CHECK_MACHACC",
372           winbindd_check_machine_acct_send, winbindd_check_machine_acct_recv },
373         { WINBINDD_PING_DC, "PING_DC",
374           winbindd_ping_dc_send, winbindd_ping_dc_recv },
375         { WINBINDD_PAM_AUTH, "PAM_AUTH",
376           winbindd_pam_auth_send, winbindd_pam_auth_recv },
377         { WINBINDD_PAM_LOGOFF, "PAM_LOGOFF",
378           winbindd_pam_logoff_send, winbindd_pam_logoff_recv },
379         { WINBINDD_PAM_CHAUTHTOK, "PAM_CHAUTHTOK",
380           winbindd_pam_chauthtok_send, winbindd_pam_chauthtok_recv },
381         { WINBINDD_PAM_CHNG_PSWD_AUTH_CRAP, "PAM_CHNG_PSWD_AUTH_CRAP",
382           winbindd_pam_chng_pswd_auth_crap_send,
383           winbindd_pam_chng_pswd_auth_crap_recv },
384         { WINBINDD_WINS_BYIP, "WINS_BYIP",
385           winbindd_wins_byip_send, winbindd_wins_byip_recv },
386         { WINBINDD_WINS_BYNAME, "WINS_BYNAME",
387           winbindd_wins_byname_send, winbindd_wins_byname_recv },
388         { WINBINDD_DOMAIN_INFO, "DOMAIN_INFO",
389           winbindd_domain_info_send, winbindd_domain_info_recv },
390
391         { 0, NULL, NULL, NULL }
392 };
393
394 static struct winbindd_async_dispatch_table async_priv_table[] = {
395         { WINBINDD_ALLOCATE_UID, "ALLOCATE_UID",
396           winbindd_allocate_uid_send, winbindd_allocate_uid_recv },
397         { WINBINDD_ALLOCATE_GID, "ALLOCATE_GID",
398           winbindd_allocate_gid_send, winbindd_allocate_gid_recv },
399         { WINBINDD_CHANGE_MACHACC, "CHANGE_MACHACC",
400           winbindd_change_machine_acct_send, winbindd_change_machine_acct_recv },
401         { WINBINDD_PAM_AUTH_CRAP, "PAM_AUTH_CRAP",
402           winbindd_pam_auth_crap_send, winbindd_pam_auth_crap_recv },
403
404         { 0, NULL, NULL, NULL }
405 };
406
407 struct process_request_state {
408         struct winbindd_cli_state *cli_state;
409         struct tevent_context *ev;
410 };
411
412 static void process_request_done(struct tevent_req *subreq);
413 static void process_request_written(struct tevent_req *subreq);
414
415 static struct tevent_req *process_request_send(
416         TALLOC_CTX *mem_ctx,
417         struct tevent_context *ev,
418         struct winbindd_cli_state *cli_state)
419 {
420         struct tevent_req *req, *subreq;
421         struct process_request_state *state;
422         struct winbindd_async_dispatch_table *atable;
423         enum winbindd_cmd cmd = cli_state->request->cmd;
424         size_t i;
425         bool ok;
426         static uint64_t request_index = 1;
427
428         /*
429          * debug traceid values:
430          * 0   .. inactive
431          * 1   .. not processing a winbind request, but in other code (timers)
432          * >=2 .. winbind request processing
433          */
434         if (debug_traceid_get() != 0) {
435                 request_index = ++request_index == 0 ? 2 : request_index;
436                 debug_traceid_set(request_index);
437         }
438         req = tevent_req_create(mem_ctx, &state,
439                                 struct process_request_state);
440         if (req == NULL) {
441                 return NULL;
442         }
443         state->cli_state = cli_state;
444         state->ev = ev;
445
446         ok = tevent_req_set_profile(req);
447         if (!ok) {
448                 return tevent_req_post(req, ev);
449         }
450
451         SMB_ASSERT(cli_state->mem_ctx == NULL);
452         cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
453         if (tevent_req_nomem(cli_state->mem_ctx, req)) {
454                 return tevent_req_post(req, ev);
455         }
456
457         cli_state->response = talloc_zero(
458                 cli_state->mem_ctx,
459                 struct winbindd_response);
460         if (tevent_req_nomem(cli_state->response, req)) {
461                 return tevent_req_post(req, ev);
462         }
463         cli_state->response->result = WINBINDD_PENDING;
464         cli_state->response->length = sizeof(struct winbindd_response);
465
466         /* Remember who asked us. */
467         cli_state->pid = cli_state->request->pid;
468         memcpy(cli_state->client_name,
469                cli_state->request->client_name,
470                sizeof(cli_state->client_name));
471
472         cli_state->cmd_name = "unknown request";
473         cli_state->recv_fn = NULL;
474
475         /* client is newest */
476         winbindd_promote_client(cli_state);
477
478         for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
479                 if (cmd == atable->cmd) {
480                         break;
481                 }
482         }
483
484         if ((atable->send_req == NULL) && cli_state->privileged) {
485                 for (atable = async_priv_table; atable->send_req;
486                      atable += 1) {
487                         if (cmd == atable->cmd) {
488                                 break;
489                         }
490                 }
491         }
492
493         if (atable->send_req != NULL) {
494                 cli_state->cmd_name = atable->cmd_name;
495                 cli_state->recv_fn = atable->recv_req;
496
497                 DBG_NOTICE("[%s (%d)] Handling async request: %s\n",
498                            cli_state->client_name,
499                            (int)cli_state->pid,
500                            cli_state->cmd_name);
501
502                 subreq = atable->send_req(
503                         state,
504                         state->ev,
505                         cli_state,
506                         cli_state->request);
507                 if (tevent_req_nomem(subreq, req)) {
508                         return tevent_req_post(req, ev);
509                 }
510                 tevent_req_set_callback(subreq, process_request_done, req);
511                 return req;
512         }
513
514         for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
515                 if (cmd == bool_dispatch_table[i].cmd) {
516                         break;
517                 }
518         }
519
520         ok = false;
521
522         if (i < ARRAY_SIZE(bool_dispatch_table)) {
523                 cli_state->cmd_name = bool_dispatch_table[i].cmd_name;
524
525                 DBG_DEBUG("process_request: request fn %s\n",
526                           bool_dispatch_table[i].cmd_name);
527                 ok = bool_dispatch_table[i].fn(cli_state);
528         }
529
530         cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
531
532         TALLOC_FREE(cli_state->io_req);
533         TALLOC_FREE(cli_state->request);
534
535         subreq = wb_resp_write_send(
536                 state,
537                 state->ev,
538                 cli_state->out_queue,
539                 cli_state->sock,
540                 cli_state->response);
541         if (tevent_req_nomem(subreq, req)) {
542                 return tevent_req_post(req, ev);
543         }
544         tevent_req_set_callback(subreq, process_request_written, req);
545
546         cli_state->io_req = subreq;
547
548         return req;
549 }
550
551 static void process_request_done(struct tevent_req *subreq)
552 {
553         struct tevent_req *req = tevent_req_callback_data(
554                 subreq, struct tevent_req);
555         struct process_request_state *state = tevent_req_data(
556                 req, struct process_request_state);
557         struct winbindd_cli_state *cli_state = state->cli_state;
558         NTSTATUS status;
559         bool ok;
560
561         status = cli_state->recv_fn(subreq, cli_state->response);
562         TALLOC_FREE(subreq);
563
564         DBG_NOTICE("[%s(%d):%s]: %s\n",
565                    cli_state->client_name,
566                    (int)cli_state->pid,
567                    cli_state->cmd_name,
568                    nt_errstr(status));
569
570         ok = NT_STATUS_IS_OK(status);
571         cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
572
573         TALLOC_FREE(cli_state->io_req);
574         TALLOC_FREE(cli_state->request);
575
576         subreq = wb_resp_write_send(
577                 state,
578                 state->ev,
579                 cli_state->out_queue,
580                 cli_state->sock,
581                 cli_state->response);
582         if (tevent_req_nomem(subreq, req)) {
583                 return;
584         }
585         tevent_req_set_callback(subreq, process_request_written, req);
586
587         cli_state->io_req = subreq;
588 }
589
590 static void process_request_written(struct tevent_req *subreq)
591 {
592         struct tevent_req *req = tevent_req_callback_data(
593                 subreq, struct tevent_req);
594         struct process_request_state *state = tevent_req_data(
595                 req, struct process_request_state);
596         struct winbindd_cli_state *cli_state = state->cli_state;
597         ssize_t ret;
598         int err;
599
600         cli_state->io_req = NULL;
601
602         ret = wb_resp_write_recv(subreq, &err);
603         TALLOC_FREE(subreq);
604         if (ret == -1) {
605                 tevent_req_nterror(req, map_nt_error_from_unix(err));
606                 return;
607         }
608
609         DBG_DEBUG("[%s(%d):%s]: delivered response to client\n",
610                   cli_state->client_name,
611                   (int)cli_state->pid,
612                   cli_state->cmd_name);
613
614         TALLOC_FREE(cli_state->mem_ctx);
615         cli_state->response = NULL;
616         cli_state->cmd_name = "no request";
617         cli_state->recv_fn = NULL;
618
619         tevent_req_done(req);
620 }
621
622 static NTSTATUS process_request_recv(
623         struct tevent_req *req,
624         TALLOC_CTX *mem_ctx,
625         struct tevent_req_profile **profile)
626 {
627         NTSTATUS status;
628
629         if (tevent_req_is_nterror(req, &status)) {
630                 tevent_req_received(req);
631                 return status;
632         }
633
634         *profile = tevent_req_move_profile(req, mem_ctx);
635         tevent_req_received(req);
636         return NT_STATUS_OK;
637 }
638
639 /*
640  * This is the main event loop of winbind requests. It goes through a
641  * state-machine of 3 read/write requests, 4 if you have extra data to send.
642  *
643  * An idle winbind client has a read request of 4 bytes outstanding,
644  * finalizing function is request_len_recv, checking the length. request_recv
645  * then processes the packet. The processing function then at some point has
646  * to call request_finished which schedules sending the response.
647  */
648
649 static void winbind_client_request_read(struct tevent_req *req);
650 static void winbind_client_activity(struct tevent_req *req);
651 static void winbind_client_processed(struct tevent_req *req);
652
653 /* Process a new connection by adding it to the client connection list */
654
655 static void new_connection(int listen_sock, bool privileged)
656 {
657         struct sockaddr_un sunaddr;
658         struct winbindd_cli_state *state;
659         struct tevent_req *req;
660         socklen_t len;
661         int sock;
662
663         /* Accept connection */
664
665         len = sizeof(sunaddr);
666
667         sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
668
669         if (sock == -1) {
670                 if (errno != EINTR) {
671                         D_ERR("Failed to accept socket: %s\n", strerror(errno));
672                 }
673                 return;
674         }
675         smb_set_close_on_exec(sock);
676
677         D_INFO("Accepted client socket %d\n", sock);
678
679         /* Create new connection structure */
680
681         if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
682                 close(sock);
683                 return;
684         }
685
686         state->sock = sock;
687
688         state->out_queue = tevent_queue_create(state, "winbind client reply");
689         if (state->out_queue == NULL) {
690                 close(sock);
691                 TALLOC_FREE(state);
692                 return;
693         }
694
695         state->privileged = privileged;
696
697         req = wb_req_read_send(state, global_event_context(), state->sock,
698                                WINBINDD_MAX_EXTRA_DATA);
699         if (req == NULL) {
700                 TALLOC_FREE(state);
701                 close(sock);
702                 return;
703         }
704         tevent_req_set_callback(req, winbind_client_request_read, state);
705         state->io_req = req;
706
707         /* Add to connection list */
708
709         winbindd_add_client(state);
710 }
711
712 static void winbind_client_request_read(struct tevent_req *req)
713 {
714         struct winbindd_cli_state *state = tevent_req_callback_data(
715                 req, struct winbindd_cli_state);
716         ssize_t ret;
717         int err;
718
719         state->io_req = NULL;
720
721         ret = wb_req_read_recv(req, state, &state->request, &err);
722         TALLOC_FREE(req);
723         if (ret == -1) {
724                 if (err == EPIPE) {
725                         DEBUG(6, ("closing socket %d, client exited\n",
726                                   state->sock));
727                 } else {
728                         DEBUG(2, ("Could not read client request from fd %d: "
729                                   "%s\n", state->sock, strerror(err)));
730                 }
731                 close(state->sock);
732                 state->sock = -1;
733                 remove_client(state);
734                 return;
735         }
736
737         req = wait_for_read_send(state, global_event_context(), state->sock,
738                                  true);
739         if (req == NULL) {
740                 DEBUG(0, ("winbind_client_request_read[%d:%s]:"
741                           " wait_for_read_send failed - removing client\n",
742                           (int)state->pid, state->cmd_name));
743                 remove_client(state);
744                 return;
745         }
746         tevent_req_set_callback(req, winbind_client_activity, state);
747         state->io_req = req;
748
749         req = process_request_send(state, global_event_context(), state);
750         if (req == NULL) {
751                 DBG_ERR("process_request_send failed\n");
752                 remove_client(state);
753                 return;
754         }
755         tevent_req_set_callback(req, winbind_client_processed, state);
756 }
757
758 static void winbind_client_activity(struct tevent_req *req)
759 {
760         struct winbindd_cli_state *state =
761             tevent_req_callback_data(req, struct winbindd_cli_state);
762         int err;
763         bool has_data;
764
765         has_data = wait_for_read_recv(req, &err);
766
767         if (has_data) {
768                 DEBUG(0, ("winbind_client_activity[%d:%s]:"
769                           "unexpected data from client - removing client\n",
770                           (int)state->pid, state->cmd_name));
771         } else {
772                 if (err == EPIPE) {
773                         DEBUG(6, ("winbind_client_activity[%d:%s]: "
774                                   "client has closed connection - removing "
775                                   "client\n",
776                                   (int)state->pid, state->cmd_name));
777                 } else {
778                         DEBUG(2, ("winbind_client_activity[%d:%s]: "
779                                   "client socket error (%s) - removing "
780                                   "client\n",
781                                   (int)state->pid, state->cmd_name,
782                                   strerror(err)));
783                 }
784         }
785
786         remove_client(state);
787 }
788
789 static void winbind_client_processed(struct tevent_req *req)
790 {
791         struct winbindd_cli_state *cli_state = tevent_req_callback_data(
792                 req, struct winbindd_cli_state);
793         struct tevent_req_profile *profile = NULL;
794         struct timeval start, stop, diff;
795         int threshold;
796         NTSTATUS status;
797
798         status = process_request_recv(req, cli_state, &profile);
799         TALLOC_FREE(req);
800         if (!NT_STATUS_IS_OK(status)) {
801                 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
802                 remove_client(cli_state);
803                 return;
804         }
805
806         tevent_req_profile_get_start(profile, NULL, &start);
807         tevent_req_profile_get_stop(profile, NULL, &stop);
808         diff = tevent_timeval_until(&start, &stop);
809
810         threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
811
812         if (diff.tv_sec >= threshold) {
813                 int depth;
814                 char *str;
815
816                 depth = lp_parm_int(
817                         -1,
818                         "winbind",
819                         "request profile depth",
820                         INT_MAX);
821
822                 DBG_ERR("request took %u.%.6u seconds\n",
823                         (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
824
825                 str = tevent_req_profile_string(
826                         talloc_tos(), profile, 0, depth);
827                 if (str != NULL) {
828                         /* No "\n", already contained in "str" */
829                         DEBUGADD(0, ("%s", str));
830                 }
831                 TALLOC_FREE(str);
832         }
833
834         TALLOC_FREE(profile);
835
836         req = wb_req_read_send(
837                 cli_state,
838                 global_event_context(),
839                 cli_state->sock,
840                 WINBINDD_MAX_EXTRA_DATA);
841         if (req == NULL) {
842                 remove_client(cli_state);
843                 return;
844         }
845         tevent_req_set_callback(req, winbind_client_request_read, cli_state);
846         cli_state->io_req = req;
847 }
848
849 /* Remove a client connection from client connection list */
850
851 static void remove_client(struct winbindd_cli_state *state)
852 {
853         /* It's a dead client - hold a funeral */
854
855         if (state == NULL) {
856                 return;
857         }
858
859         /*
860          * We need to remove a pending wb_req_read_*
861          * or wb_resp_write_* request before closing the
862          * socket.
863          *
864          * This is important as they might have used tevent_add_fd() and we
865          * use the epoll * backend on linux. So we must remove the tevent_fd
866          * before closing the fd.
867          *
868          * Otherwise we might hit a race with close_conns_after_fork() (via
869          * winbindd_reinit_after_fork()) where a file descriptor
870          * is still open in a child, which means it's still active in
871          * the parents epoll queue, but the related tevent_fd is already
872          * already gone in the parent.
873          *
874          * See bug #11141.
875          */
876         TALLOC_FREE(state->io_req);
877
878         if (state->sock != -1) {
879                 char c = 0;
880                 int nwritten;
881
882                 /* tell client, we are closing ... */
883                 nwritten = write(state->sock, &c, sizeof(c));
884                 if (nwritten == -1) {
885                         DEBUG(2, ("final write to client failed: %s\n",
886                                 strerror(errno)));
887                 }
888
889                 /* Close socket */
890
891                 close(state->sock);
892                 state->sock = -1;
893         }
894
895         TALLOC_FREE(state->mem_ctx);
896
897         /* Remove from list and free */
898
899         winbindd_remove_client(state);
900         TALLOC_FREE(state);
901 }
902
903 /* Is a client idle? */
904
905 static bool client_is_idle(struct winbindd_cli_state *state) {
906   return (state->request == NULL &&
907           state->response == NULL &&
908           !state->pwent_state && !state->grent_state);
909 }
910
911 /* Shutdown client connection which has been idle for the longest time */
912
913 static bool remove_idle_client(void)
914 {
915         struct winbindd_cli_state *state, *remove_state = NULL;
916         int nidle = 0;
917
918         for (state = winbindd_client_list(); state; state = state->next) {
919                 if (client_is_idle(state)) {
920                         nidle++;
921                         /* list is sorted by access time */
922                         remove_state = state;
923                 }
924         }
925
926         if (remove_state) {
927                 DEBUG(5,("Found %d idle client connections, shutting down sock %d, pid %u\n",
928                         nidle, remove_state->sock, (unsigned int)remove_state->pid));
929                 remove_client(remove_state);
930                 return True;
931         }
932
933         return False;
934 }
935
936 /*
937  * Terminate all clients whose requests have taken longer than
938  * "winbind request timeout" seconds to process, or have been
939  * idle for more than "winbind request timeout" seconds.
940  */
941
942 static void remove_timed_out_clients(void)
943 {
944         struct winbindd_cli_state *state, *prev = NULL;
945         time_t curr_time = time(NULL);
946         int timeout_val = lp_winbind_request_timeout();
947
948         for (state = winbindd_client_list_tail(); state; state = prev) {
949                 time_t expiry_time;
950
951                 prev = winbindd_client_list_prev(state);
952                 expiry_time = state->last_access + timeout_val;
953
954                 if (curr_time <= expiry_time) {
955                         /* list is sorted, previous clients in
956                            list are newer */
957                         break;
958                 }
959
960                 if (client_is_idle(state)) {
961                         DEBUG(5,("Idle client timed out, "
962                                  "shutting down sock %d, pid %u\n",
963                                  state->sock,
964                                  (unsigned int)state->pid));
965                 } else {
966                         DEBUG(5,("Client request timed out, "
967                                  "shutting down sock %d, pid %u\n",
968                                  state->sock,
969                                  (unsigned int)state->pid));
970                 }
971
972                 remove_client(state);
973         }
974 }
975
976 static void winbindd_scrub_clients_handler(struct tevent_context *ev,
977                                            struct tevent_timer *te,
978                                            struct timeval current_time,
979                                            void *private_data)
980 {
981         remove_timed_out_clients();
982         if (tevent_add_timer(ev, ev,
983                              timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
984                              winbindd_scrub_clients_handler, NULL) == NULL) {
985                 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
986                 exit(1);
987         }
988 }
989
990 struct winbindd_listen_state {
991         bool privileged;
992         int fd;
993 };
994
995 static void winbindd_listen_fde_handler(struct tevent_context *ev,
996                                         struct tevent_fd *fde,
997                                         uint16_t flags,
998                                         void *private_data)
999 {
1000         struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
1001                                           struct winbindd_listen_state);
1002
1003         while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
1004                 DEBUG(5,("winbindd: Exceeding %d client "
1005                          "connections, removing idle "
1006                          "connection.\n", lp_winbind_max_clients()));
1007                 if (!remove_idle_client()) {
1008                         DEBUG(0,("winbindd: Exceeding %d "
1009                                  "client connections, no idle "
1010                                  "connection found\n",
1011                                  lp_winbind_max_clients()));
1012                         break;
1013                 }
1014         }
1015         remove_timed_out_clients();
1016         new_connection(s->fd, s->privileged);
1017 }
1018
1019 /*
1020  * Winbindd socket accessor functions
1021  */
1022
1023 static bool winbindd_setup_listeners(void)
1024 {
1025         struct winbindd_listen_state *pub_state = NULL;
1026         struct winbindd_listen_state *priv_state = NULL;
1027         struct tevent_fd *fde;
1028         int rc;
1029         char *socket_path;
1030
1031         pub_state = talloc(global_event_context(),
1032                            struct winbindd_listen_state);
1033         if (!pub_state) {
1034                 goto failed;
1035         }
1036
1037         pub_state->privileged = false;
1038         pub_state->fd = create_pipe_sock(
1039                 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
1040         if (pub_state->fd == -1) {
1041                 goto failed;
1042         }
1043         rc = listen(pub_state->fd, 5);
1044         if (rc < 0) {
1045                 goto failed;
1046         }
1047
1048         fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
1049                             TEVENT_FD_READ, winbindd_listen_fde_handler,
1050                             pub_state);
1051         if (fde == NULL) {
1052                 close(pub_state->fd);
1053                 goto failed;
1054         }
1055         tevent_fd_set_auto_close(fde);
1056
1057         priv_state = talloc(global_event_context(),
1058                             struct winbindd_listen_state);
1059         if (!priv_state) {
1060                 goto failed;
1061         }
1062
1063         socket_path = get_winbind_priv_pipe_dir();
1064         if (socket_path == NULL) {
1065                 goto failed;
1066         }
1067
1068         priv_state->privileged = true;
1069         priv_state->fd = create_pipe_sock(
1070                 socket_path, WINBINDD_SOCKET_NAME, 0750);
1071         TALLOC_FREE(socket_path);
1072         if (priv_state->fd == -1) {
1073                 goto failed;
1074         }
1075         rc = listen(priv_state->fd, 5);
1076         if (rc < 0) {
1077                 goto failed;
1078         }
1079
1080         fde = tevent_add_fd(global_event_context(), priv_state,
1081                             priv_state->fd, TEVENT_FD_READ,
1082                             winbindd_listen_fde_handler, priv_state);
1083         if (fde == NULL) {
1084                 close(priv_state->fd);
1085                 goto failed;
1086         }
1087         tevent_fd_set_auto_close(fde);
1088
1089         winbindd_scrub_clients_handler(global_event_context(), NULL,
1090                                        timeval_current(), NULL);
1091         return true;
1092 failed:
1093         TALLOC_FREE(pub_state);
1094         TALLOC_FREE(priv_state);
1095         return false;
1096 }
1097
1098 static void winbindd_register_handlers(struct messaging_context *msg_ctx,
1099                                        bool foreground)
1100 {
1101         bool scan_trusts = true;
1102         NTSTATUS status;
1103         struct tevent_timer *te = NULL;
1104
1105         /* Setup signal handlers */
1106
1107         if (!winbindd_setup_sig_term_handler(true))
1108                 exit(1);
1109         if (!winbindd_setup_stdin_handler(true, foreground))
1110                 exit(1);
1111         if (!winbindd_setup_sig_hup_handler(NULL))
1112                 exit(1);
1113         if (!winbindd_setup_sig_chld_handler())
1114                 exit(1);
1115         if (!winbindd_setup_sig_usr2_handler())
1116                 exit(1);
1117
1118         CatchSignal(SIGPIPE, SIG_IGN);                 /* Ignore sigpipe */
1119
1120         /*
1121          * Ensure all cache and idmap caches are consistent
1122          * and initialized before we startup.
1123          */
1124         if (!winbindd_cache_validate_and_initialize()) {
1125                 exit(1);
1126         }
1127
1128         /* React on 'smbcontrol winbindd reload-config' in the same way
1129            as to SIGHUP signal */
1130         messaging_register(msg_ctx, NULL,
1131                            MSG_SMB_CONF_UPDATED,
1132                            winbindd_msg_reload_services_parent);
1133         messaging_register(msg_ctx, NULL,
1134                            MSG_SHUTDOWN, msg_shutdown);
1135
1136         /* Handle online/offline messages. */
1137         messaging_register(msg_ctx, NULL,
1138                            MSG_WINBIND_OFFLINE, winbind_msg_offline);
1139         messaging_register(msg_ctx, NULL,
1140                            MSG_WINBIND_ONLINE, winbind_msg_online);
1141         messaging_register(msg_ctx, NULL,
1142                            MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
1143
1144         /* Handle domain online/offline messages for domains */
1145         messaging_register(global_messaging_context(), NULL,
1146                            MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
1147         messaging_register(global_messaging_context(), NULL,
1148                            MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
1149
1150         messaging_register(msg_ctx, NULL,
1151                            MSG_WINBIND_VALIDATE_CACHE,
1152                            winbind_msg_validate_cache);
1153
1154         messaging_register(msg_ctx, NULL,
1155                            MSG_WINBIND_DUMP_DOMAIN_LIST,
1156                            winbind_msg_dump_domain_list);
1157
1158         messaging_register(msg_ctx, NULL,
1159                            MSG_WINBIND_IP_DROPPED,
1160                            winbind_msg_ip_dropped_parent);
1161
1162         /* Register handler for MSG_DEBUG. */
1163         messaging_register(msg_ctx, NULL,
1164                            MSG_DEBUG,
1165                            winbind_msg_debug);
1166
1167         messaging_register(msg_ctx, NULL,
1168                            MSG_WINBIND_DISCONNECT_DC,
1169                            winbind_disconnect_dc_parent);
1170
1171         netsamlogon_cache_init(); /* Non-critical */
1172
1173         /* clear the cached list of trusted domains */
1174
1175         wcache_tdc_clear();
1176
1177         if (!init_domain_list()) {
1178                 DEBUG(0,("unable to initialize domain list\n"));
1179                 exit(1);
1180         }
1181
1182         init_idmap_child();
1183         init_locator_child();
1184
1185         smb_nscd_flush_user_cache();
1186         smb_nscd_flush_group_cache();
1187
1188         if (!lp_winbind_scan_trusted_domains()) {
1189                 scan_trusts = false;
1190         }
1191
1192         if (!lp_allow_trusted_domains()) {
1193                 scan_trusts = false;
1194         }
1195
1196         if (IS_DC) {
1197                 scan_trusts = false;
1198         }
1199
1200         if (scan_trusts) {
1201                 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
1202                               rescan_trusted_domains, NULL) == NULL) {
1203                         DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
1204                         exit(1);
1205                 }
1206         }
1207
1208         te = tevent_add_timer(global_event_context(),
1209                               NULL,
1210                               timeval_zero(),
1211                               winbindd_ping_offline_domains,
1212                               NULL);
1213         if (te == NULL) {
1214                 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
1215                 exit(1);
1216         }
1217
1218         status = wb_irpc_register();
1219
1220         if (!NT_STATUS_IS_OK(status)) {
1221                 DEBUG(0, ("Could not register IRPC handlers\n"));
1222                 exit(1);
1223         }
1224 }
1225
1226 struct winbindd_addrchanged_state {
1227         struct addrchange_context *ctx;
1228         struct tevent_context *ev;
1229         struct messaging_context *msg_ctx;
1230 };
1231
1232 static void winbindd_addr_changed(struct tevent_req *req);
1233
1234 static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
1235                                      struct tevent_context *ev,
1236                                      struct messaging_context *msg_ctx)
1237 {
1238         struct winbindd_addrchanged_state *state;
1239         struct tevent_req *req;
1240         NTSTATUS status;
1241
1242         state = talloc(mem_ctx, struct winbindd_addrchanged_state);
1243         if (state == NULL) {
1244                 DEBUG(10, ("talloc failed\n"));
1245                 return;
1246         }
1247         state->ev = ev;
1248         state->msg_ctx = msg_ctx;
1249
1250         status = addrchange_context_create(state, &state->ctx);
1251         if (!NT_STATUS_IS_OK(status)) {
1252                 DEBUG(10, ("addrchange_context_create failed: %s\n",
1253                            nt_errstr(status)));
1254                 TALLOC_FREE(state);
1255                 return;
1256         }
1257         req = addrchange_send(state, ev, state->ctx);
1258         if (req == NULL) {
1259                 DEBUG(0, ("addrchange_send failed\n"));
1260                 TALLOC_FREE(state);
1261                 return;
1262         }
1263         tevent_req_set_callback(req, winbindd_addr_changed, state);
1264 }
1265
1266 static void winbindd_addr_changed(struct tevent_req *req)
1267 {
1268         struct winbindd_addrchanged_state *state = tevent_req_callback_data(
1269                 req, struct winbindd_addrchanged_state);
1270         enum addrchange_type type;
1271         struct sockaddr_storage addr;
1272         NTSTATUS status;
1273
1274         status = addrchange_recv(req, &type, &addr);
1275         TALLOC_FREE(req);
1276         if (!NT_STATUS_IS_OK(status)) {
1277                 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
1278                            nt_errstr(status)));
1279                 TALLOC_FREE(state);
1280                 return;
1281         }
1282         if (type == ADDRCHANGE_DEL) {
1283                 char addrstr[INET6_ADDRSTRLEN];
1284                 DATA_BLOB blob;
1285
1286                 print_sockaddr(addrstr, sizeof(addrstr), &addr);
1287
1288                 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
1289                           addrstr));
1290
1291                 blob = data_blob_const(addrstr, strlen(addrstr)+1);
1292
1293                 status = messaging_send(state->msg_ctx,
1294                                         messaging_server_id(state->msg_ctx),
1295                                         MSG_WINBIND_IP_DROPPED, &blob);
1296                 if (!NT_STATUS_IS_OK(status)) {
1297                         DEBUG(10, ("messaging_send failed: %s - ignoring\n",
1298                                    nt_errstr(status)));
1299                 }
1300         }
1301         req = addrchange_send(state, state->ev, state->ctx);
1302         if (req == NULL) {
1303                 DEBUG(0, ("addrchange_send failed\n"));
1304                 TALLOC_FREE(state);
1305                 return;
1306         }
1307         tevent_req_set_callback(req, winbindd_addr_changed, state);
1308 }
1309
1310 /* Main function */
1311
1312 int main(int argc, const char **argv)
1313 {
1314         static bool log_stdout = False;
1315         struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
1316         struct poptOption long_options[] = {
1317                 POPT_AUTOHELP
1318                 {
1319                         .longName   = "no-caching",
1320                         .shortName  = 'n',
1321                         .argInfo    = POPT_ARG_NONE,
1322                         .arg        = NULL,
1323                         .val        = 'n',
1324                         .descrip    = "Disable caching",
1325                 },
1326                 POPT_COMMON_SAMBA
1327                 POPT_COMMON_DAEMON
1328                 POPT_COMMON_VERSION
1329                 POPT_TABLEEND
1330         };
1331         const struct loadparm_substitution *lp_sub =
1332                 loadparm_s3_global_substitution();
1333         poptContext pc;
1334         int opt;
1335         TALLOC_CTX *frame;
1336         NTSTATUS status;
1337         bool ok;
1338         const struct dcesrv_endpoint_server *ep_server = NULL;
1339         struct dcesrv_context *dce_ctx = NULL;
1340         size_t winbindd_socket_dir_len = 0;
1341         char *winbindd_priv_socket_dir = NULL;
1342         size_t winbindd_priv_socket_dir_len = 0;
1343
1344         setproctitle_init(argc, discard_const(argv), environ);
1345
1346         /*
1347          * Do this before any other talloc operation
1348          */
1349         talloc_enable_null_tracking();
1350         frame = talloc_stackframe();
1351
1352         /*
1353          * We want total control over the permissions on created files,
1354          * so set our umask to 0.
1355          */
1356         umask(0);
1357
1358         smb_init_locale();
1359
1360         /* glibc (?) likes to print "User defined signal 1" and exit if a
1361            SIGUSR[12] is received before a handler is installed */
1362
1363         CatchSignal(SIGUSR1, SIG_IGN);
1364         CatchSignal(SIGUSR2, SIG_IGN);
1365
1366         ok = samba_cmdline_init(frame,
1367                                 SAMBA_CMDLINE_CONFIG_SERVER,
1368                                 true /* require_smbconf */);
1369         if (!ok) {
1370                 DBG_ERR("Failed to setup cmdline parser\n");
1371                 TALLOC_FREE(frame);
1372                 exit(1);
1373         }
1374
1375         cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
1376
1377         pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
1378         if (pc == NULL) {
1379                 DBG_ERR("Failed to setup popt parser!\n");
1380                 TALLOC_FREE(frame);
1381                 exit(1);
1382         }
1383
1384         while ((opt = poptGetNextOpt(pc)) != -1) {
1385                 switch (opt) {
1386                 case 'n':
1387                         winbindd_set_use_cache(false);
1388                         break;
1389                 default:
1390                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
1391                                   poptBadOption(pc, 0), poptStrerror(opt));
1392                         poptPrintUsage(pc, stderr, 0);
1393                         exit(1);
1394                 }
1395         }
1396
1397         /* Set environment variable so we don't recursively call ourselves.
1398            This may also be useful interactively. */
1399         if ( !winbind_off() ) {
1400                 DEBUG(0,("Failed to disable recursive winbindd calls.  Exiting.\n"));
1401                 exit(1);
1402         }
1403
1404         /* Initialise for running in non-root mode */
1405         sec_init();
1406
1407         set_remote_machine_name("winbindd", False);
1408
1409         dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1410         if (cmdline_daemon_cfg->daemon && cmdline_daemon_cfg->interactive) {
1411                 d_fprintf(stderr,"\nERROR: "
1412                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
1413                 poptPrintUsage(pc, stderr, 0);
1414                 exit(1);
1415         }
1416
1417         log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
1418         if (cmdline_daemon_cfg->interactive) {
1419                 /*
1420                  * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
1421                  * for interactive is passed on the commandline. Set it back to
1422                  * true. TODO: check if this is correct, smbd and nmbd don't do
1423                  * this.
1424                  */
1425                 cmdline_daemon_cfg->fork = true;
1426                 log_stdout = true;
1427         }
1428
1429         if (log_stdout && cmdline_daemon_cfg->fork) {
1430                 d_fprintf(stderr, "\nERROR: "
1431                           "Can't log to stdout (-S) unless daemon is in "
1432                           "foreground (-F) or interactive (-i)\n\n");
1433                 poptPrintUsage(pc, stderr, 0);
1434                 exit(1);
1435         }
1436
1437         poptFreeContext(pc);
1438
1439         reopen_logs();
1440
1441         DBG_STARTUP_NOTICE("winbindd version %s started.\n"
1442                         COPYRIGHT_STARTUP_MESSAGE "\n",
1443                 samba_version_string());
1444
1445         /* After parsing the configuration file we setup the core path one more time
1446          * as the log file might have been set in the configuration and cores's
1447          * path is by default basename(lp_logfile()).
1448          */
1449         dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
1450
1451         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1452                 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
1453                         DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
1454                         DEBUGADD(0, ("You should start 'samba' instead, and it will control starting the internal AD DC winbindd implementation, which is not the same as this one\n"));
1455                         exit(1);
1456                 }
1457                 /* Main 'samba' daemon will notify */
1458                 daemon_sd_notifications(false);
1459         }
1460
1461         if (lp_security() == SEC_ADS) {
1462                 const char *realm = lp_realm();
1463                 const char *workgroup = lp_workgroup();
1464
1465                 if (workgroup == NULL || strlen(workgroup) == 0) {
1466                         DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
1467                                 "parameter is required to be set!\n");
1468                         exit(1);
1469                 }
1470
1471                 if (realm == NULL || strlen(realm) == 0) {
1472                         DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
1473                                 "parameter is required to be set!\n");
1474                         exit(1);
1475                 }
1476         }
1477
1478         winbindd_socket_dir_len = strlen(lp_winbindd_socket_directory());
1479         if (winbindd_socket_dir_len > 0) {
1480                 size_t winbindd_socket_len =
1481                         winbindd_socket_dir_len + 1 +
1482                         strlen(WINBINDD_SOCKET_NAME);
1483                 struct sockaddr_un un = {
1484                         .sun_family = AF_UNIX,
1485                 };
1486                 size_t sun_path_len = sizeof(un.sun_path);
1487
1488                 if (winbindd_socket_len >= sun_path_len) {
1489                         DBG_ERR("The winbind socket path [%s/%s] is too long "
1490                                 "(%zu >= %zu)\n",
1491                                 lp_winbindd_socket_directory(),
1492                                 WINBINDD_SOCKET_NAME,
1493                                 winbindd_socket_len,
1494                                 sun_path_len);
1495                         exit(1);
1496                 }
1497         } else {
1498                 DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
1499                 exit(1);
1500         }
1501
1502         winbindd_priv_socket_dir = get_winbind_priv_pipe_dir();
1503         winbindd_priv_socket_dir_len = strlen(winbindd_priv_socket_dir);
1504         if (winbindd_priv_socket_dir_len > 0) {
1505                 size_t winbindd_priv_socket_len =
1506                         winbindd_priv_socket_dir_len + 1 +
1507                         strlen(WINBINDD_SOCKET_NAME);
1508                 struct sockaddr_un un = {
1509                         .sun_family = AF_UNIX,
1510                 };
1511                 size_t sun_path_len = sizeof(un.sun_path);
1512
1513                 if (winbindd_priv_socket_len >= sun_path_len) {
1514                         DBG_ERR("The winbind privileged socket path [%s/%s] is too long "
1515                                 "(%zu >= %zu)\n",
1516                                 winbindd_priv_socket_dir,
1517                                 WINBINDD_SOCKET_NAME,
1518                                 winbindd_priv_socket_len,
1519                                 sun_path_len);
1520                         exit(1);
1521                 }
1522         } else {
1523                 DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
1524                 exit(1);
1525         }
1526         TALLOC_FREE(winbindd_priv_socket_dir);
1527
1528         if (!cluster_probe_ok()) {
1529                 exit(1);
1530         }
1531
1532         /* Initialise messaging system */
1533
1534         if (global_messaging_context() == NULL) {
1535                 exit(1);
1536         }
1537
1538         if (!winbindd_reload_services_file(NULL)) {
1539                 DEBUG(0, ("error opening config file\n"));
1540                 exit(1);
1541         }
1542
1543         {
1544                 size_t i;
1545                 const char *idmap_backend;
1546                 const char *invalid_backends[] = {
1547                         "ad", "rfc2307", "rid",
1548                 };
1549
1550                 idmap_backend = lp_idmap_default_backend();
1551                 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
1552                         ok = strequal(idmap_backend, invalid_backends[i]);
1553                         if (ok) {
1554                                 DBG_ERR("FATAL: Invalid idmap backend %s "
1555                                         "configured as the default backend!\n",
1556                                         idmap_backend);
1557                                 exit(1);
1558                         }
1559                 }
1560         }
1561
1562         ok = directory_create_or_exist(lp_lock_directory(), 0755);
1563         if (!ok) {
1564                 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
1565                           lp_lock_directory(), strerror(errno)));
1566                 exit(1);
1567         }
1568
1569         ok = directory_create_or_exist(lp_pid_directory(), 0755);
1570         if (!ok) {
1571                 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
1572                           lp_pid_directory(), strerror(errno)));
1573                 exit(1);
1574         }
1575
1576         load_interfaces();
1577
1578         if (!secrets_init()) {
1579
1580                 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
1581                 return False;
1582         }
1583
1584         status = rpccli_pre_open_netlogon_creds();
1585         if (!NT_STATUS_IS_OK(status)) {
1586                 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
1587                           nt_errstr(status)));
1588                 exit(1);
1589         }
1590
1591         /* Unblock all signals we are interested in as they may have been
1592            blocked by the parent process. */
1593
1594         BlockSignals(False, SIGINT);
1595         BlockSignals(False, SIGQUIT);
1596         BlockSignals(False, SIGTERM);
1597         BlockSignals(False, SIGUSR1);
1598         BlockSignals(False, SIGUSR2);
1599         BlockSignals(False, SIGHUP);
1600         BlockSignals(False, SIGCHLD);
1601
1602         if (!interactive) {
1603                 become_daemon(cmdline_daemon_cfg->fork,
1604                               cmdline_daemon_cfg->no_process_group,
1605                               log_stdout);
1606         } else {
1607                 daemon_status("winbindd", "Starting process ...");
1608         }
1609
1610         pidfile_create(lp_pid_directory(), "winbindd");
1611
1612 #ifdef HAVE_SETPGID
1613         /*
1614          * If we're interactive we want to set our own process group for
1615          * signal management.
1616          */
1617         if (cmdline_daemon_cfg->interactive &&
1618             !cmdline_daemon_cfg->no_process_group)
1619         {
1620                 setpgid( (pid_t)0, (pid_t)0);
1621         }
1622 #endif
1623
1624         TimeInit();
1625
1626         /* Don't use winbindd_reinit_after_fork here as
1627          * we're just starting up and haven't created any
1628          * winbindd-specific resources we must free yet. JRA.
1629          */
1630
1631         status = reinit_after_fork(global_messaging_context(),
1632                                    global_event_context(),
1633                                    false);
1634         if (!NT_STATUS_IS_OK(status)) {
1635                 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
1636         }
1637
1638         if (lp_winbind_debug_traceid()) {
1639                 winbind_debug_traceid_setup(global_event_context());
1640                 winbind_debug_call_depth_setup(debug_call_depth_addr());
1641                 tevent_thread_call_depth_set_callback(
1642                         debuglevel_get() > 1 ? winbind_call_flow : NULL,
1643                         NULL);
1644         }
1645         ok = initialize_password_db(true, global_event_context());
1646         if (!ok) {
1647                 exit_daemon("Failed to initialize passdb backend! "
1648                             "Check the 'passdb backend' variable in your "
1649                             "smb.conf file.", EINVAL);
1650         }
1651
1652         /*
1653          * Do not initialize the parent-child-pipe before becoming
1654          * a daemon: this is used to detect a died parent in the child
1655          * process.
1656          */
1657         status = init_before_fork();
1658         if (!NT_STATUS_IS_OK(status)) {
1659                 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
1660         }
1661
1662         winbindd_register_handlers(global_messaging_context(),
1663                                    !cmdline_daemon_cfg->fork);
1664
1665         if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
1666                 exit(1);
1667         }
1668
1669         status = init_system_session_info(NULL);
1670         if (!NT_STATUS_IS_OK(status)) {
1671                 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
1672         }
1673
1674         DBG_INFO("Registering DCE/RPC endpoint servers\n");
1675
1676         ep_server = winbind_get_ep_server();
1677         if (ep_server == NULL) {
1678                 DBG_ERR("Failed to get 'winbind' endpoint server\n");
1679                 exit(1);
1680         }
1681         status = dcerpc_register_ep_server(ep_server);
1682         if (!NT_STATUS_IS_OK(status)) {
1683                 DBG_ERR("Failed to register 'winbind' endpoint "
1684                         "server: %s\n", nt_errstr(status));
1685                 exit(1);
1686         }
1687
1688         dce_ctx = global_dcesrv_context();
1689
1690         DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
1691
1692         /* Init all registered ep servers */
1693         status = dcesrv_init_registered_ep_servers(dce_ctx);
1694         if (!NT_STATUS_IS_OK(status)) {
1695                 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
1696                         nt_errstr(status));
1697                 exit(1);
1698         }
1699
1700         winbindd_init_addrchange(NULL, global_event_context(),
1701                                  global_messaging_context());
1702
1703         /* setup listen sockets */
1704
1705         if (!winbindd_setup_listeners()) {
1706                 exit_daemon("Winbindd failed to setup listeners", EPIPE);
1707         }
1708
1709         irpc_add_name(winbind_imessaging_context(), "winbind_server");
1710
1711         TALLOC_FREE(frame);
1712
1713         if (!interactive) {
1714                 daemon_ready("winbindd");
1715         }
1716
1717         gpupdate_init();
1718
1719         /* Loop waiting for requests */
1720         while (1) {
1721                 frame = talloc_stackframe();
1722
1723                 if (tevent_loop_once(global_event_context()) == -1) {
1724                         DEBUG(1, ("tevent_loop_once() failed: %s\n",
1725                                   strerror(errno)));
1726                         return 1;
1727                 }
1728
1729                 TALLOC_FREE(frame);
1730         }
1731
1732         return 0;
1733 }