LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 417 656 63.6 %
Date: 2024-04-21 15:09:00 Functions: 22 28 78.6 %

          Line data    Source code
       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           0 : static void winbindd_status(void)
      73             : {
      74             :         struct winbindd_cli_state *tmp;
      75             : 
      76           0 :         DEBUG(0, ("winbindd status:\n"));
      77             : 
      78             :         /* Print client state information */
      79             : 
      80           0 :         DEBUG(0, ("\t%d clients currently active\n", winbindd_num_clients()));
      81             : 
      82           0 :         if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
      83           0 :                 DEBUG(2, ("\tclient list:\n"));
      84           0 :                 for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
      85           0 :                         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           0 : }
      91             : 
      92             : /*
      93             :   handle stdin becoming readable when we are in --foreground mode
      94             :  */
      95          45 : 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          45 :         if (read(0, &c, 1) != 1) {
     102          45 :                 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          45 :                 DEBUG(0,("EOF on stdin (is_parent=%d)\n",
     107             :                          (int)*is_parent));
     108          45 :                 winbindd_terminate(*is_parent);
     109             :         }
     110           0 : }
     111             : 
     112          45 : bool winbindd_setup_stdin_handler(bool parent, bool foreground)
     113             : {
     114             :         bool *is_parent;
     115             : 
     116          45 :         if (foreground) {
     117             :                 struct stat st;
     118             : 
     119          45 :                 is_parent = talloc(global_event_context(), bool);
     120          45 :                 if (!is_parent) {
     121           0 :                         return false;
     122             :                 }
     123             : 
     124          45 :                 *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          45 :                 if (fstat(0, &st) != 0) {
     132           0 :                         return false;
     133             :                 }
     134          45 :                 if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
     135          45 :                         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          45 :         return true;
     145             : }
     146             : 
     147          31 : 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          54 :         while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
     157          23 :                 winbind_child_died(pid);
     158             :         }
     159          31 : }
     160             : 
     161          45 : static bool winbindd_setup_sig_chld_handler(void)
     162             : {
     163             :         struct tevent_signal *se;
     164             : 
     165          45 :         se = tevent_add_signal(global_event_context(),
     166             :                                global_event_context(),
     167             :                                SIGCHLD, 0,
     168             :                                winbindd_sig_chld_handler,
     169             :                                NULL);
     170          45 :         if (!se) {
     171           0 :                 return false;
     172             :         }
     173             : 
     174          45 :         return true;
     175             : }
     176             : 
     177           0 : 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           0 :         winbindd_status();
     185           0 : }
     186             : 
     187          45 : static bool winbindd_setup_sig_usr2_handler(void)
     188             : {
     189             :         struct tevent_signal *se;
     190             : 
     191          45 :         se = tevent_add_signal(global_event_context(),
     192             :                                global_event_context(),
     193             :                                SIGUSR2, 0,
     194             :                                winbindd_sig_usr2_handler,
     195             :                                NULL);
     196          45 :         if (!se) {
     197           0 :                 return false;
     198             :         }
     199             : 
     200          45 :         return true;
     201             : }
     202             : 
     203             : /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/
     204           0 : 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           0 :         DEBUG(0,("Got shutdown message\n"));
     212           0 :         winbindd_terminate(true);
     213           0 : }
     214             : 
     215             : 
     216           4 : 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           4 :         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           4 :         child_pid = fork();
     235             : 
     236           4 :         if (child_pid == -1) {
     237           0 :                 DEBUG(1, ("winbind_msg_validate_cache: Could not fork: %s\n",
     238             :                           strerror(errno)));
     239           0 :                 return;
     240             :         }
     241             : 
     242           4 :         if (child_pid != 0) {
     243             :                 /* parent */
     244           4 :                 DEBUG(5, ("winbind_msg_validate_cache: child created with "
     245             :                           "pid %d.\n", (int)child_pid));
     246           4 :                 return;
     247             :         }
     248             : 
     249             :         /* child */
     250             : 
     251           0 :         status = winbindd_reinit_after_fork(NULL, NULL);
     252           0 :         if (!NT_STATUS_IS_OK(status)) {
     253           0 :                 DEBUG(1, ("winbindd_reinit_after_fork failed: %s\n",
     254             :                           nt_errstr(status)));
     255           0 :                 _exit(0);
     256             :         }
     257             : 
     258             :         /* install default SIGCHLD handler: validation code uses fork/waitpid */
     259           0 :         CatchSignal(SIGCHLD, SIG_DFL);
     260             : 
     261           0 :         process_set_title("wb: check cache", "validate cache child");
     262             : 
     263           0 :         ret = (uint8_t)winbindd_validate_cache_nobackup();
     264           0 :         DEBUG(10, ("winbindd_msg_validata_cache: got return value %d\n", ret));
     265           0 :         messaging_send_buf(msg_ctx, server_id, MSG_WINBIND_VALIDATE_CACHE, &ret,
     266             :                            (size_t)1);
     267           0 :         _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      254707 : 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      254707 :         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      254707 :         if (debug_traceid_get() != 0) {
     435      254707 :                 request_index = ++request_index == 0 ? 2 : request_index;
     436      254707 :                 debug_traceid_set(request_index);
     437             :         }
     438      254707 :         req = tevent_req_create(mem_ctx, &state,
     439             :                                 struct process_request_state);
     440      254707 :         if (req == NULL) {
     441           0 :                 return NULL;
     442             :         }
     443      254707 :         state->cli_state = cli_state;
     444      254707 :         state->ev = ev;
     445             : 
     446      254707 :         ok = tevent_req_set_profile(req);
     447      254707 :         if (!ok) {
     448           0 :                 return tevent_req_post(req, ev);
     449             :         }
     450             : 
     451      254707 :         SMB_ASSERT(cli_state->mem_ctx == NULL);
     452      254707 :         cli_state->mem_ctx = talloc_named(cli_state, 0, "winbind request");
     453      254707 :         if (tevent_req_nomem(cli_state->mem_ctx, req)) {
     454           0 :                 return tevent_req_post(req, ev);
     455             :         }
     456             : 
     457      254707 :         cli_state->response = talloc_zero(
     458             :                 cli_state->mem_ctx,
     459             :                 struct winbindd_response);
     460      254707 :         if (tevent_req_nomem(cli_state->response, req)) {
     461           0 :                 return tevent_req_post(req, ev);
     462             :         }
     463      254707 :         cli_state->response->result = WINBINDD_PENDING;
     464      254707 :         cli_state->response->length = sizeof(struct winbindd_response);
     465             : 
     466             :         /* Remember who asked us. */
     467      254707 :         cli_state->pid = cli_state->request->pid;
     468      254707 :         memcpy(cli_state->client_name,
     469      254707 :                cli_state->request->client_name,
     470             :                sizeof(cli_state->client_name));
     471             : 
     472      254707 :         cli_state->cmd_name = "unknown request";
     473      254707 :         cli_state->recv_fn = NULL;
     474             : 
     475             :         /* client is newest */
     476      254707 :         winbindd_promote_client(cli_state);
     477             : 
     478     5689595 :         for (atable = async_nonpriv_table; atable->send_req; atable += 1) {
     479     5557373 :                 if (cmd == atable->cmd) {
     480      122485 :                         break;
     481             :                 }
     482             :         }
     483             : 
     484      254707 :         if ((atable->send_req == NULL) && cli_state->privileged) {
     485       17474 :                 for (atable = async_priv_table; atable->send_req;
     486       12982 :                      atable += 1) {
     487       17074 :                         if (cmd == atable->cmd) {
     488        4092 :                                 break;
     489             :                         }
     490             :                 }
     491             :         }
     492             : 
     493      254707 :         if (atable->send_req != NULL) {
     494      126577 :                 cli_state->cmd_name = atable->cmd_name;
     495      126577 :                 cli_state->recv_fn = atable->recv_req;
     496             : 
     497      126577 :                 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      126577 :                 subreq = atable->send_req(
     503             :                         state,
     504      126577 :                         state->ev,
     505             :                         cli_state,
     506             :                         cli_state->request);
     507      126577 :                 if (tevent_req_nomem(subreq, req)) {
     508           0 :                         return tevent_req_post(req, ev);
     509             :                 }
     510      126577 :                 tevent_req_set_callback(subreq, process_request_done, req);
     511      126577 :                 return req;
     512             :         }
     513             : 
     514      377450 :         for (i=0; i<ARRAY_SIZE(bool_dispatch_table); i++) {
     515      377450 :                 if (cmd == bool_dispatch_table[i].cmd) {
     516      128130 :                         break;
     517             :                 }
     518             :         }
     519             : 
     520      128130 :         ok = false;
     521             : 
     522      128130 :         if (i < ARRAY_SIZE(bool_dispatch_table)) {
     523      128130 :                 cli_state->cmd_name = bool_dispatch_table[i].cmd_name;
     524             : 
     525      128130 :                 DBG_DEBUG("process_request: request fn %s\n",
     526             :                           bool_dispatch_table[i].cmd_name);
     527      128130 :                 ok = bool_dispatch_table[i].fn(cli_state);
     528             :         }
     529             : 
     530      128130 :         cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
     531             : 
     532      128130 :         TALLOC_FREE(cli_state->io_req);
     533      128130 :         TALLOC_FREE(cli_state->request);
     534             : 
     535      128130 :         subreq = wb_resp_write_send(
     536             :                 state,
     537      128130 :                 state->ev,
     538             :                 cli_state->out_queue,
     539             :                 cli_state->sock,
     540             :                 cli_state->response);
     541      128130 :         if (tevent_req_nomem(subreq, req)) {
     542           0 :                 return tevent_req_post(req, ev);
     543             :         }
     544      128130 :         tevent_req_set_callback(subreq, process_request_written, req);
     545             : 
     546      128130 :         cli_state->io_req = subreq;
     547             : 
     548      128130 :         return req;
     549             : }
     550             : 
     551      126577 : static void process_request_done(struct tevent_req *subreq)
     552             : {
     553      126577 :         struct tevent_req *req = tevent_req_callback_data(
     554             :                 subreq, struct tevent_req);
     555      126577 :         struct process_request_state *state = tevent_req_data(
     556             :                 req, struct process_request_state);
     557      126577 :         struct winbindd_cli_state *cli_state = state->cli_state;
     558             :         NTSTATUS status;
     559             :         bool ok;
     560             : 
     561      126577 :         status = cli_state->recv_fn(subreq, cli_state->response);
     562      126577 :         TALLOC_FREE(subreq);
     563             : 
     564      126577 :         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      126577 :         ok = NT_STATUS_IS_OK(status);
     571      126577 :         cli_state->response->result = ok ? WINBINDD_OK : WINBINDD_ERROR;
     572             : 
     573      126577 :         TALLOC_FREE(cli_state->io_req);
     574      126577 :         TALLOC_FREE(cli_state->request);
     575             : 
     576      126577 :         subreq = wb_resp_write_send(
     577             :                 state,
     578             :                 state->ev,
     579             :                 cli_state->out_queue,
     580             :                 cli_state->sock,
     581             :                 cli_state->response);
     582      126577 :         if (tevent_req_nomem(subreq, req)) {
     583           0 :                 return;
     584             :         }
     585      126577 :         tevent_req_set_callback(subreq, process_request_written, req);
     586             : 
     587      126577 :         cli_state->io_req = subreq;
     588             : }
     589             : 
     590      254707 : static void process_request_written(struct tevent_req *subreq)
     591             : {
     592      254707 :         struct tevent_req *req = tevent_req_callback_data(
     593             :                 subreq, struct tevent_req);
     594      254707 :         struct process_request_state *state = tevent_req_data(
     595             :                 req, struct process_request_state);
     596      254707 :         struct winbindd_cli_state *cli_state = state->cli_state;
     597             :         ssize_t ret;
     598             :         int err;
     599             : 
     600      254707 :         cli_state->io_req = NULL;
     601             : 
     602      254707 :         ret = wb_resp_write_recv(subreq, &err);
     603      254707 :         TALLOC_FREE(subreq);
     604      254707 :         if (ret == -1) {
     605           0 :                 tevent_req_nterror(req, map_nt_error_from_unix(err));
     606           0 :                 return;
     607             :         }
     608             : 
     609      254707 :         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      254707 :         TALLOC_FREE(cli_state->mem_ctx);
     615      254707 :         cli_state->response = NULL;
     616      254707 :         cli_state->cmd_name = "no request";
     617      254707 :         cli_state->recv_fn = NULL;
     618             : 
     619      254707 :         tevent_req_done(req);
     620             : }
     621             : 
     622      254707 : 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      254707 :         if (tevent_req_is_nterror(req, &status)) {
     630           0 :                 tevent_req_received(req);
     631           0 :                 return status;
     632             :         }
     633             : 
     634      254707 :         *profile = tevent_req_move_profile(req, mem_ctx);
     635      254707 :         tevent_req_received(req);
     636      254707 :         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        8037 : 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        8037 :         len = sizeof(sunaddr);
     666             : 
     667        8037 :         sock = accept(listen_sock, (struct sockaddr *)(void *)&sunaddr, &len);
     668             : 
     669        8037 :         if (sock == -1) {
     670           0 :                 if (errno != EINTR) {
     671           0 :                         D_ERR("Failed to accept socket: %s\n", strerror(errno));
     672             :                 }
     673           0 :                 return;
     674             :         }
     675        8037 :         smb_set_close_on_exec(sock);
     676             : 
     677        8037 :         D_INFO("Accepted client socket %d\n", sock);
     678             : 
     679             :         /* Create new connection structure */
     680             : 
     681        8037 :         if ((state = talloc_zero(NULL, struct winbindd_cli_state)) == NULL) {
     682           0 :                 close(sock);
     683           0 :                 return;
     684             :         }
     685             : 
     686        8037 :         state->sock = sock;
     687             : 
     688        8037 :         state->out_queue = tevent_queue_create(state, "winbind client reply");
     689        8037 :         if (state->out_queue == NULL) {
     690           0 :                 close(sock);
     691           0 :                 TALLOC_FREE(state);
     692           0 :                 return;
     693             :         }
     694             : 
     695        8037 :         state->privileged = privileged;
     696             : 
     697        8037 :         req = wb_req_read_send(state, global_event_context(), state->sock,
     698             :                                WINBINDD_MAX_EXTRA_DATA);
     699        8037 :         if (req == NULL) {
     700           0 :                 TALLOC_FREE(state);
     701           0 :                 close(sock);
     702           0 :                 return;
     703             :         }
     704        8037 :         tevent_req_set_callback(req, winbind_client_request_read, state);
     705        8037 :         state->io_req = req;
     706             : 
     707             :         /* Add to connection list */
     708             : 
     709        8037 :         winbindd_add_client(state);
     710             : }
     711             : 
     712      262625 : static void winbind_client_request_read(struct tevent_req *req)
     713             : {
     714      262625 :         struct winbindd_cli_state *state = tevent_req_callback_data(
     715             :                 req, struct winbindd_cli_state);
     716             :         ssize_t ret;
     717             :         int err;
     718             : 
     719      262625 :         state->io_req = NULL;
     720             : 
     721      262625 :         ret = wb_req_read_recv(req, state, &state->request, &err);
     722      262625 :         TALLOC_FREE(req);
     723      262625 :         if (ret == -1) {
     724        7918 :                 if (err == EPIPE) {
     725        7918 :                         DEBUG(6, ("closing socket %d, client exited\n",
     726             :                                   state->sock));
     727             :                 } else {
     728           0 :                         DEBUG(2, ("Could not read client request from fd %d: "
     729             :                                   "%s\n", state->sock, strerror(err)));
     730             :                 }
     731        7918 :                 close(state->sock);
     732        7918 :                 state->sock = -1;
     733        7918 :                 remove_client(state);
     734        7918 :                 return;
     735             :         }
     736             : 
     737      254707 :         req = wait_for_read_send(state, global_event_context(), state->sock,
     738             :                                  true);
     739      254707 :         if (req == NULL) {
     740           0 :                 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           0 :                 remove_client(state);
     744           0 :                 return;
     745             :         }
     746      254707 :         tevent_req_set_callback(req, winbind_client_activity, state);
     747      254707 :         state->io_req = req;
     748             : 
     749      254707 :         req = process_request_send(state, global_event_context(), state);
     750      254707 :         if (req == NULL) {
     751           0 :                 DBG_ERR("process_request_send failed\n");
     752           0 :                 remove_client(state);
     753           0 :                 return;
     754             :         }
     755      254707 :         tevent_req_set_callback(req, winbind_client_processed, state);
     756             : }
     757             : 
     758           0 : static void winbind_client_activity(struct tevent_req *req)
     759             : {
     760             :         struct winbindd_cli_state *state =
     761           0 :             tevent_req_callback_data(req, struct winbindd_cli_state);
     762             :         int err;
     763             :         bool has_data;
     764             : 
     765           0 :         has_data = wait_for_read_recv(req, &err);
     766             : 
     767           0 :         if (has_data) {
     768           0 :                 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           0 :                 if (err == EPIPE) {
     773           0 :                         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           0 :                         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           0 :         remove_client(state);
     787           0 : }
     788             : 
     789      254707 : static void winbind_client_processed(struct tevent_req *req)
     790             : {
     791      254707 :         struct winbindd_cli_state *cli_state = tevent_req_callback_data(
     792             :                 req, struct winbindd_cli_state);
     793      254707 :         struct tevent_req_profile *profile = NULL;
     794             :         struct timeval start, stop, diff;
     795             :         int threshold;
     796             :         NTSTATUS status;
     797             : 
     798      254707 :         status = process_request_recv(req, cli_state, &profile);
     799      254707 :         TALLOC_FREE(req);
     800      254707 :         if (!NT_STATUS_IS_OK(status)) {
     801           0 :                 DBG_DEBUG("process_request failed: %s\n", nt_errstr(status));
     802           0 :                 remove_client(cli_state);
     803           0 :                 return;
     804             :         }
     805             : 
     806      254707 :         tevent_req_profile_get_start(profile, NULL, &start);
     807      254707 :         tevent_req_profile_get_stop(profile, NULL, &stop);
     808      254707 :         diff = tevent_timeval_until(&start, &stop);
     809             : 
     810      254707 :         threshold = lp_parm_int(-1, "winbind", "request profile threshold", 60);
     811             : 
     812      254707 :         if (diff.tv_sec >= threshold) {
     813             :                 int depth;
     814             :                 char *str;
     815             : 
     816           0 :                 depth = lp_parm_int(
     817             :                         -1,
     818             :                         "winbind",
     819             :                         "request profile depth",
     820             :                         INT_MAX);
     821             : 
     822           0 :                 DBG_ERR("request took %u.%.6u seconds\n",
     823             :                         (unsigned)diff.tv_sec, (unsigned)diff.tv_usec);
     824             : 
     825           0 :                 str = tevent_req_profile_string(
     826             :                         talloc_tos(), profile, 0, depth);
     827           0 :                 if (str != NULL) {
     828             :                         /* No "\n", already contained in "str" */
     829           0 :                         DEBUGADD(0, ("%s", str));
     830             :                 }
     831           0 :                 TALLOC_FREE(str);
     832             :         }
     833             : 
     834      254707 :         TALLOC_FREE(profile);
     835             : 
     836      254707 :         req = wb_req_read_send(
     837             :                 cli_state,
     838             :                 global_event_context(),
     839             :                 cli_state->sock,
     840             :                 WINBINDD_MAX_EXTRA_DATA);
     841      254707 :         if (req == NULL) {
     842           0 :                 remove_client(cli_state);
     843           0 :                 return;
     844             :         }
     845      254707 :         tevent_req_set_callback(req, winbind_client_request_read, cli_state);
     846      254707 :         cli_state->io_req = req;
     847             : }
     848             : 
     849             : /* Remove a client connection from client connection list */
     850             : 
     851        8004 : static void remove_client(struct winbindd_cli_state *state)
     852             : {
     853             :         /* It's a dead client - hold a funeral */
     854             : 
     855        8004 :         if (state == NULL) {
     856           0 :                 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        8004 :         TALLOC_FREE(state->io_req);
     877             : 
     878        8004 :         if (state->sock != -1) {
     879          86 :                 char c = 0;
     880             :                 int nwritten;
     881             : 
     882             :                 /* tell client, we are closing ... */
     883          86 :                 nwritten = write(state->sock, &c, sizeof(c));
     884          86 :                 if (nwritten == -1) {
     885           0 :                         DEBUG(2, ("final write to client failed: %s\n",
     886             :                                 strerror(errno)));
     887             :                 }
     888             : 
     889             :                 /* Close socket */
     890             : 
     891          86 :                 close(state->sock);
     892          86 :                 state->sock = -1;
     893             :         }
     894             : 
     895        8004 :         TALLOC_FREE(state->mem_ctx);
     896             : 
     897             :         /* Remove from list and free */
     898             : 
     899        8004 :         winbindd_remove_client(state);
     900        8004 :         TALLOC_FREE(state);
     901             : }
     902             : 
     903             : /* Is a client idle? */
     904             : 
     905          86 : static bool client_is_idle(struct winbindd_cli_state *state) {
     906         172 :   return (state->request == NULL &&
     907          86 :           state->response == NULL &&
     908         172 :           !state->pwent_state && !state->grent_state);
     909             : }
     910             : 
     911             : /* Shutdown client connection which has been idle for the longest time */
     912             : 
     913           0 : static bool remove_idle_client(void)
     914             : {
     915           0 :         struct winbindd_cli_state *state, *remove_state = NULL;
     916           0 :         int nidle = 0;
     917             : 
     918           0 :         for (state = winbindd_client_list(); state; state = state->next) {
     919           0 :                 if (client_is_idle(state)) {
     920           0 :                         nidle++;
     921             :                         /* list is sorted by access time */
     922           0 :                         remove_state = state;
     923             :                 }
     924             :         }
     925             : 
     926           0 :         if (remove_state) {
     927           0 :                 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           0 :                 remove_client(remove_state);
     930           0 :                 return True;
     931             :         }
     932             : 
     933           0 :         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       13342 : static void remove_timed_out_clients(void)
     943             : {
     944       13342 :         struct winbindd_cli_state *state, *prev = NULL;
     945       13342 :         time_t curr_time = time(NULL);
     946       13342 :         int timeout_val = lp_winbind_request_timeout();
     947             : 
     948       13428 :         for (state = winbindd_client_list_tail(); state; state = prev) {
     949             :                 time_t expiry_time;
     950             : 
     951        8756 :                 prev = winbindd_client_list_prev(state);
     952        8756 :                 expiry_time = state->last_access + timeout_val;
     953             : 
     954        8756 :                 if (curr_time <= expiry_time) {
     955             :                         /* list is sorted, previous clients in
     956             :                            list are newer */
     957        8670 :                         break;
     958             :                 }
     959             : 
     960          86 :                 if (client_is_idle(state)) {
     961          86 :                         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           0 :                         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          86 :                 remove_client(state);
     973             :         }
     974       13342 : }
     975             : 
     976        5305 : 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        5305 :         remove_timed_out_clients();
     982        5305 :         if (tevent_add_timer(ev, ev,
     983             :                              timeval_current_ofs(SCRUB_CLIENTS_INTERVAL, 0),
     984             :                              winbindd_scrub_clients_handler, NULL) == NULL) {
     985           0 :                 DEBUG(0, ("winbindd: failed to reschedule client scrubber\n"));
     986           0 :                 exit(1);
     987             :         }
     988        5305 : }
     989             : 
     990             : struct winbindd_listen_state {
     991             :         bool privileged;
     992             :         int fd;
     993             : };
     994             : 
     995        8037 : 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        8037 :         struct winbindd_listen_state *s = talloc_get_type_abort(private_data,
    1001             :                                           struct winbindd_listen_state);
    1002             : 
    1003        8037 :         while (winbindd_num_clients() > lp_winbind_max_clients() - 1) {
    1004           0 :                 DEBUG(5,("winbindd: Exceeding %d client "
    1005             :                          "connections, removing idle "
    1006             :                          "connection.\n", lp_winbind_max_clients()));
    1007           0 :                 if (!remove_idle_client()) {
    1008           0 :                         DEBUG(0,("winbindd: Exceeding %d "
    1009             :                                  "client connections, no idle "
    1010             :                                  "connection found\n",
    1011             :                                  lp_winbind_max_clients()));
    1012           0 :                         break;
    1013             :                 }
    1014             :         }
    1015        8037 :         remove_timed_out_clients();
    1016        8037 :         new_connection(s->fd, s->privileged);
    1017        8037 : }
    1018             : 
    1019             : /*
    1020             :  * Winbindd socket accessor functions
    1021             :  */
    1022             : 
    1023          45 : static bool winbindd_setup_listeners(void)
    1024             : {
    1025          45 :         struct winbindd_listen_state *pub_state = NULL;
    1026          45 :         struct winbindd_listen_state *priv_state = NULL;
    1027             :         struct tevent_fd *fde;
    1028             :         int rc;
    1029             :         char *socket_path;
    1030             : 
    1031          45 :         pub_state = talloc(global_event_context(),
    1032             :                            struct winbindd_listen_state);
    1033          45 :         if (!pub_state) {
    1034           0 :                 goto failed;
    1035             :         }
    1036             : 
    1037          45 :         pub_state->privileged = false;
    1038          45 :         pub_state->fd = create_pipe_sock(
    1039             :                 lp_winbindd_socket_directory(), WINBINDD_SOCKET_NAME, 0755);
    1040          45 :         if (pub_state->fd == -1) {
    1041           0 :                 goto failed;
    1042             :         }
    1043          45 :         rc = listen(pub_state->fd, 5);
    1044          45 :         if (rc < 0) {
    1045           0 :                 goto failed;
    1046             :         }
    1047             : 
    1048          45 :         fde = tevent_add_fd(global_event_context(), pub_state, pub_state->fd,
    1049             :                             TEVENT_FD_READ, winbindd_listen_fde_handler,
    1050             :                             pub_state);
    1051          45 :         if (fde == NULL) {
    1052           0 :                 close(pub_state->fd);
    1053           0 :                 goto failed;
    1054             :         }
    1055          45 :         tevent_fd_set_auto_close(fde);
    1056             : 
    1057          45 :         priv_state = talloc(global_event_context(),
    1058             :                             struct winbindd_listen_state);
    1059          45 :         if (!priv_state) {
    1060           0 :                 goto failed;
    1061             :         }
    1062             : 
    1063          45 :         socket_path = get_winbind_priv_pipe_dir();
    1064          45 :         if (socket_path == NULL) {
    1065           0 :                 goto failed;
    1066             :         }
    1067             : 
    1068          45 :         priv_state->privileged = true;
    1069          45 :         priv_state->fd = create_pipe_sock(
    1070             :                 socket_path, WINBINDD_SOCKET_NAME, 0750);
    1071          45 :         TALLOC_FREE(socket_path);
    1072          45 :         if (priv_state->fd == -1) {
    1073           0 :                 goto failed;
    1074             :         }
    1075          45 :         rc = listen(priv_state->fd, 5);
    1076          45 :         if (rc < 0) {
    1077           0 :                 goto failed;
    1078             :         }
    1079             : 
    1080          45 :         fde = tevent_add_fd(global_event_context(), priv_state,
    1081             :                             priv_state->fd, TEVENT_FD_READ,
    1082             :                             winbindd_listen_fde_handler, priv_state);
    1083          45 :         if (fde == NULL) {
    1084           0 :                 close(priv_state->fd);
    1085           0 :                 goto failed;
    1086             :         }
    1087          45 :         tevent_fd_set_auto_close(fde);
    1088             : 
    1089          45 :         winbindd_scrub_clients_handler(global_event_context(), NULL,
    1090             :                                        timeval_current(), NULL);
    1091          45 :         return true;
    1092           0 : failed:
    1093           0 :         TALLOC_FREE(pub_state);
    1094           0 :         TALLOC_FREE(priv_state);
    1095           0 :         return false;
    1096             : }
    1097             : 
    1098          45 : static void winbindd_register_handlers(struct messaging_context *msg_ctx,
    1099             :                                        bool foreground)
    1100             : {
    1101          45 :         bool scan_trusts = true;
    1102             :         NTSTATUS status;
    1103          45 :         struct tevent_timer *te = NULL;
    1104             : 
    1105             :         /* Setup signal handlers */
    1106             : 
    1107          45 :         if (!winbindd_setup_sig_term_handler(true))
    1108           0 :                 exit(1);
    1109          45 :         if (!winbindd_setup_stdin_handler(true, foreground))
    1110           0 :                 exit(1);
    1111          45 :         if (!winbindd_setup_sig_hup_handler(NULL))
    1112           0 :                 exit(1);
    1113          45 :         if (!winbindd_setup_sig_chld_handler())
    1114           0 :                 exit(1);
    1115          45 :         if (!winbindd_setup_sig_usr2_handler())
    1116           0 :                 exit(1);
    1117             : 
    1118          45 :         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          45 :         if (!winbindd_cache_validate_and_initialize()) {
    1125           0 :                 exit(1);
    1126             :         }
    1127             : 
    1128             :         /* React on 'smbcontrol winbindd reload-config' in the same way
    1129             :            as to SIGHUP signal */
    1130          45 :         messaging_register(msg_ctx, NULL,
    1131             :                            MSG_SMB_CONF_UPDATED,
    1132             :                            winbindd_msg_reload_services_parent);
    1133          45 :         messaging_register(msg_ctx, NULL,
    1134             :                            MSG_SHUTDOWN, msg_shutdown);
    1135             : 
    1136             :         /* Handle online/offline messages. */
    1137          45 :         messaging_register(msg_ctx, NULL,
    1138             :                            MSG_WINBIND_OFFLINE, winbind_msg_offline);
    1139          45 :         messaging_register(msg_ctx, NULL,
    1140             :                            MSG_WINBIND_ONLINE, winbind_msg_online);
    1141          45 :         messaging_register(msg_ctx, NULL,
    1142             :                            MSG_WINBIND_ONLINESTATUS, winbind_msg_onlinestatus);
    1143             : 
    1144             :         /* Handle domain online/offline messages for domains */
    1145          45 :         messaging_register(global_messaging_context(), NULL,
    1146             :                            MSG_WINBIND_DOMAIN_OFFLINE, winbind_msg_domain_offline);
    1147          45 :         messaging_register(global_messaging_context(), NULL,
    1148             :                            MSG_WINBIND_DOMAIN_ONLINE, winbind_msg_domain_online);
    1149             : 
    1150          45 :         messaging_register(msg_ctx, NULL,
    1151             :                            MSG_WINBIND_VALIDATE_CACHE,
    1152             :                            winbind_msg_validate_cache);
    1153             : 
    1154          45 :         messaging_register(msg_ctx, NULL,
    1155             :                            MSG_WINBIND_DUMP_DOMAIN_LIST,
    1156             :                            winbind_msg_dump_domain_list);
    1157             : 
    1158          45 :         messaging_register(msg_ctx, NULL,
    1159             :                            MSG_WINBIND_IP_DROPPED,
    1160             :                            winbind_msg_ip_dropped_parent);
    1161             : 
    1162             :         /* Register handler for MSG_DEBUG. */
    1163          45 :         messaging_register(msg_ctx, NULL,
    1164             :                            MSG_DEBUG,
    1165             :                            winbind_msg_debug);
    1166             : 
    1167          45 :         messaging_register(msg_ctx, NULL,
    1168             :                            MSG_WINBIND_DISCONNECT_DC,
    1169             :                            winbind_disconnect_dc_parent);
    1170             : 
    1171          45 :         netsamlogon_cache_init(); /* Non-critical */
    1172             : 
    1173             :         /* clear the cached list of trusted domains */
    1174             : 
    1175          45 :         wcache_tdc_clear();
    1176             : 
    1177          45 :         if (!init_domain_list()) {
    1178           0 :                 DEBUG(0,("unable to initialize domain list\n"));
    1179           0 :                 exit(1);
    1180             :         }
    1181             : 
    1182          45 :         status = init_idmap_child(global_event_context());
    1183          45 :         if (NT_STATUS_IS_ERR(status)) {
    1184           0 :                 DBG_ERR("Unable to start idmap child: %s\n", nt_errstr(status));
    1185           0 :                 exit(1);
    1186             :         }
    1187             : 
    1188          45 :         status = init_locator_child(global_event_context());
    1189          45 :         if (NT_STATUS_IS_ERR(status)) {
    1190           0 :                 DBG_ERR("Unable to start locator child: %s\n", nt_errstr(status));
    1191           0 :                 exit(1);
    1192             :         }
    1193             : 
    1194          45 :         smb_nscd_flush_user_cache();
    1195          45 :         smb_nscd_flush_group_cache();
    1196             : 
    1197          45 :         if (!lp_winbind_scan_trusted_domains()) {
    1198          43 :                 scan_trusts = false;
    1199             :         }
    1200             : 
    1201          45 :         if (!lp_allow_trusted_domains()) {
    1202           0 :                 scan_trusts = false;
    1203             :         }
    1204             : 
    1205          45 :         if (IS_DC) {
    1206          14 :                 scan_trusts = false;
    1207             :         }
    1208             : 
    1209          45 :         if (scan_trusts) {
    1210           2 :                 if (tevent_add_timer(global_event_context(), NULL, timeval_zero(),
    1211             :                               rescan_trusted_domains, NULL) == NULL) {
    1212           0 :                         DEBUG(0, ("Could not trigger rescan_trusted_domains()\n"));
    1213           0 :                         exit(1);
    1214             :                 }
    1215             :         }
    1216             : 
    1217          45 :         te = tevent_add_timer(global_event_context(),
    1218             :                               NULL,
    1219             :                               timeval_zero(),
    1220             :                               winbindd_ping_offline_domains,
    1221             :                               NULL);
    1222          45 :         if (te == NULL) {
    1223           0 :                 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
    1224           0 :                 exit(1);
    1225             :         }
    1226             : 
    1227          45 :         status = wb_irpc_register();
    1228             : 
    1229          45 :         if (!NT_STATUS_IS_OK(status)) {
    1230           0 :                 DEBUG(0, ("Could not register IRPC handlers\n"));
    1231           0 :                 exit(1);
    1232             :         }
    1233          45 : }
    1234             : 
    1235             : struct winbindd_addrchanged_state {
    1236             :         struct addrchange_context *ctx;
    1237             :         struct tevent_context *ev;
    1238             :         struct messaging_context *msg_ctx;
    1239             : };
    1240             : 
    1241             : static void winbindd_addr_changed(struct tevent_req *req);
    1242             : 
    1243          45 : static void winbindd_init_addrchange(TALLOC_CTX *mem_ctx,
    1244             :                                      struct tevent_context *ev,
    1245             :                                      struct messaging_context *msg_ctx)
    1246             : {
    1247             :         struct winbindd_addrchanged_state *state;
    1248             :         struct tevent_req *req;
    1249             :         NTSTATUS status;
    1250             : 
    1251          45 :         state = talloc(mem_ctx, struct winbindd_addrchanged_state);
    1252          45 :         if (state == NULL) {
    1253           0 :                 DEBUG(10, ("talloc failed\n"));
    1254           0 :                 return;
    1255             :         }
    1256          45 :         state->ev = ev;
    1257          45 :         state->msg_ctx = msg_ctx;
    1258             : 
    1259          45 :         status = addrchange_context_create(state, &state->ctx);
    1260          45 :         if (!NT_STATUS_IS_OK(status)) {
    1261           0 :                 DEBUG(10, ("addrchange_context_create failed: %s\n",
    1262             :                            nt_errstr(status)));
    1263           0 :                 TALLOC_FREE(state);
    1264           0 :                 return;
    1265             :         }
    1266          45 :         req = addrchange_send(state, ev, state->ctx);
    1267          45 :         if (req == NULL) {
    1268           0 :                 DEBUG(0, ("addrchange_send failed\n"));
    1269           0 :                 TALLOC_FREE(state);
    1270           0 :                 return;
    1271             :         }
    1272          45 :         tevent_req_set_callback(req, winbindd_addr_changed, state);
    1273             : }
    1274             : 
    1275           0 : static void winbindd_addr_changed(struct tevent_req *req)
    1276             : {
    1277           0 :         struct winbindd_addrchanged_state *state = tevent_req_callback_data(
    1278             :                 req, struct winbindd_addrchanged_state);
    1279             :         enum addrchange_type type;
    1280             :         struct sockaddr_storage addr;
    1281             :         NTSTATUS status;
    1282             : 
    1283           0 :         status = addrchange_recv(req, &type, &addr, NULL);
    1284           0 :         TALLOC_FREE(req);
    1285           0 :         if (!NT_STATUS_IS_OK(status)) {
    1286           0 :                 DEBUG(10, ("addrchange_recv failed: %s, stop listening\n",
    1287             :                            nt_errstr(status)));
    1288           0 :                 TALLOC_FREE(state);
    1289           0 :                 return;
    1290             :         }
    1291           0 :         if (type == ADDRCHANGE_DEL) {
    1292             :                 char addrstr[INET6_ADDRSTRLEN];
    1293             :                 DATA_BLOB blob;
    1294             : 
    1295           0 :                 print_sockaddr(addrstr, sizeof(addrstr), &addr);
    1296             : 
    1297           0 :                 DEBUG(3, ("winbindd: kernel (AF_NETLINK) dropped ip %s\n",
    1298             :                           addrstr));
    1299             : 
    1300           0 :                 blob = data_blob_const(addrstr, strlen(addrstr)+1);
    1301             : 
    1302           0 :                 status = messaging_send(state->msg_ctx,
    1303           0 :                                         messaging_server_id(state->msg_ctx),
    1304             :                                         MSG_WINBIND_IP_DROPPED, &blob);
    1305           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1306           0 :                         DEBUG(10, ("messaging_send failed: %s - ignoring\n",
    1307             :                                    nt_errstr(status)));
    1308             :                 }
    1309             :         }
    1310           0 :         req = addrchange_send(state, state->ev, state->ctx);
    1311           0 :         if (req == NULL) {
    1312           0 :                 DEBUG(0, ("addrchange_send failed\n"));
    1313           0 :                 TALLOC_FREE(state);
    1314           0 :                 return;
    1315             :         }
    1316           0 :         tevent_req_set_callback(req, winbindd_addr_changed, state);
    1317             : }
    1318             : 
    1319             : /* Main function */
    1320             : 
    1321          45 : int main(int argc, const char **argv)
    1322             : {
    1323             :         static bool log_stdout = False;
    1324          45 :         struct samba_cmdline_daemon_cfg *cmdline_daemon_cfg = NULL;
    1325         180 :         struct poptOption long_options[] = {
    1326             :                 POPT_AUTOHELP
    1327             :                 {
    1328             :                         .longName   = "no-caching",
    1329             :                         .shortName  = 'n',
    1330             :                         .argInfo    = POPT_ARG_NONE,
    1331             :                         .arg        = NULL,
    1332             :                         .val        = 'n',
    1333             :                         .descrip    = "Disable caching",
    1334             :                 },
    1335          45 :                 POPT_COMMON_SAMBA
    1336          45 :                 POPT_COMMON_DAEMON
    1337          45 :                 POPT_COMMON_VERSION
    1338             :                 POPT_TABLEEND
    1339             :         };
    1340             :         const struct loadparm_substitution *lp_sub =
    1341          45 :                 loadparm_s3_global_substitution();
    1342             :         poptContext pc;
    1343             :         int opt;
    1344             :         TALLOC_CTX *frame;
    1345             :         NTSTATUS status;
    1346             :         bool ok;
    1347          45 :         const struct dcesrv_endpoint_server *ep_server = NULL;
    1348          45 :         struct dcesrv_context *dce_ctx = NULL;
    1349          45 :         size_t winbindd_socket_dir_len = 0;
    1350          45 :         char *winbindd_priv_socket_dir = NULL;
    1351          45 :         size_t winbindd_priv_socket_dir_len = 0;
    1352             : 
    1353          45 :         setproctitle_init(argc, discard_const(argv), environ);
    1354             : 
    1355             :         /*
    1356             :          * Do this before any other talloc operation
    1357             :          */
    1358          45 :         talloc_enable_null_tracking();
    1359          45 :         frame = talloc_stackframe();
    1360             : 
    1361             :         /*
    1362             :          * We want total control over the permissions on created files,
    1363             :          * so set our umask to 0.
    1364             :          */
    1365          45 :         umask(0);
    1366             : 
    1367          45 :         smb_init_locale();
    1368             : 
    1369             :         /* glibc (?) likes to print "User defined signal 1" and exit if a
    1370             :            SIGUSR[12] is received before a handler is installed */
    1371             : 
    1372          45 :         CatchSignal(SIGUSR1, SIG_IGN);
    1373          45 :         CatchSignal(SIGUSR2, SIG_IGN);
    1374             : 
    1375          45 :         ok = samba_cmdline_init(frame,
    1376             :                                 SAMBA_CMDLINE_CONFIG_SERVER,
    1377             :                                 true /* require_smbconf */);
    1378          45 :         if (!ok) {
    1379           0 :                 DBG_ERR("Failed to setup cmdline parser\n");
    1380           0 :                 TALLOC_FREE(frame);
    1381           0 :                 exit(1);
    1382             :         }
    1383             : 
    1384          45 :         cmdline_daemon_cfg = samba_cmdline_get_daemon_cfg();
    1385             : 
    1386          45 :         pc = samba_popt_get_context(getprogname(), argc, argv, long_options, 0);
    1387          45 :         if (pc == NULL) {
    1388           0 :                 DBG_ERR("Failed to setup popt parser!\n");
    1389           0 :                 TALLOC_FREE(frame);
    1390           0 :                 exit(1);
    1391             :         }
    1392             : 
    1393          45 :         while ((opt = poptGetNextOpt(pc)) != -1) {
    1394           0 :                 switch (opt) {
    1395           0 :                 case 'n':
    1396           0 :                         winbindd_set_use_cache(false);
    1397           0 :                         break;
    1398           0 :                 default:
    1399           0 :                         d_fprintf(stderr, "\nInvalid option %s: %s\n\n",
    1400             :                                   poptBadOption(pc, 0), poptStrerror(opt));
    1401           0 :                         poptPrintUsage(pc, stderr, 0);
    1402           0 :                         exit(1);
    1403             :                 }
    1404             :         }
    1405             : 
    1406             :         /* Set environment variable so we don't recursively call ourselves.
    1407             :            This may also be useful interactively. */
    1408          45 :         if ( !winbind_off() ) {
    1409           0 :                 DEBUG(0,("Failed to disable recursive winbindd calls.  Exiting.\n"));
    1410           0 :                 exit(1);
    1411             :         }
    1412             : 
    1413             :         /* Initialise for running in non-root mode */
    1414          45 :         sec_init();
    1415             : 
    1416          45 :         set_remote_machine_name("winbindd", False);
    1417             : 
    1418          45 :         dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
    1419          45 :         if (cmdline_daemon_cfg->daemon && cmdline_daemon_cfg->interactive) {
    1420           0 :                 d_fprintf(stderr,"\nERROR: "
    1421             :                           "Option -i|--interactive is not allowed together with -D|--daemon\n\n");
    1422           0 :                 poptPrintUsage(pc, stderr, 0);
    1423           0 :                 exit(1);
    1424             :         }
    1425             : 
    1426          45 :         log_stdout = (debug_get_log_type() == DEBUG_STDOUT);
    1427          45 :         if (cmdline_daemon_cfg->interactive) {
    1428             :                 /*
    1429             :                  * libcmdline POPT_DAEMON callback sets "fork" to false if "-i"
    1430             :                  * for interactive is passed on the commandline. Set it back to
    1431             :                  * true. TODO: check if this is correct, smbd and nmbd don't do
    1432             :                  * this.
    1433             :                  */
    1434           0 :                 cmdline_daemon_cfg->fork = true;
    1435           0 :                 log_stdout = true;
    1436             :         }
    1437             : 
    1438          45 :         if (log_stdout && cmdline_daemon_cfg->fork) {
    1439           0 :                 d_fprintf(stderr, "\nERROR: "
    1440             :                           "Can't log to stdout (-S) unless daemon is in "
    1441             :                           "foreground (-F) or interactive (-i)\n\n");
    1442           0 :                 poptPrintUsage(pc, stderr, 0);
    1443           0 :                 exit(1);
    1444             :         }
    1445             : 
    1446          45 :         poptFreeContext(pc);
    1447             : 
    1448          45 :         reopen_logs();
    1449             : 
    1450          45 :         DBG_STARTUP_NOTICE("winbindd version %s started.\n%s\n",
    1451             :                            samba_version_string(),
    1452             :                            samba_copyright_string());
    1453             : 
    1454             :         /* After parsing the configuration file we setup the core path one more time
    1455             :          * as the log file might have been set in the configuration and cores's
    1456             :          * path is by default basename(lp_logfile()).
    1457             :          */
    1458          45 :         dump_core_setup("winbindd", lp_logfile(talloc_tos(), lp_sub));
    1459             : 
    1460          45 :         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
    1461           0 :                 if (!lp_parm_bool(-1, "server role check", "inhibit", false)) {
    1462           0 :                         DBG_ERR("server role = 'active directory domain controller' not compatible with running the winbindd binary. \n");
    1463           0 :                         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"));
    1464           0 :                         exit(1);
    1465             :                 }
    1466             :                 /* Main 'samba' daemon will notify */
    1467           0 :                 daemon_sd_notifications(false);
    1468             :         }
    1469             : 
    1470          45 :         if (lp_security() == SEC_ADS) {
    1471          28 :                 const char *realm = lp_realm();
    1472          28 :                 const char *workgroup = lp_workgroup();
    1473             : 
    1474          28 :                 if (workgroup == NULL || strlen(workgroup) == 0) {
    1475           0 :                         DBG_ERR("For 'secuirity = ADS' mode, the 'workgroup' "
    1476             :                                 "parameter is required to be set!\n");
    1477           0 :                         exit(1);
    1478             :                 }
    1479             : 
    1480          28 :                 if (realm == NULL || strlen(realm) == 0) {
    1481           0 :                         DBG_ERR("For 'secuirity = ADS' mode, the 'realm' "
    1482             :                                 "parameter is required to be set!\n");
    1483           0 :                         exit(1);
    1484             :                 }
    1485             :         }
    1486             : 
    1487          45 :         winbindd_socket_dir_len = strlen(lp_winbindd_socket_directory());
    1488          45 :         if (winbindd_socket_dir_len > 0) {
    1489          45 :                 size_t winbindd_socket_len =
    1490             :                         winbindd_socket_dir_len + 1 +
    1491             :                         strlen(WINBINDD_SOCKET_NAME);
    1492          45 :                 struct sockaddr_un un = {
    1493             :                         .sun_family = AF_UNIX,
    1494             :                 };
    1495          45 :                 size_t sun_path_len = sizeof(un.sun_path);
    1496             : 
    1497          45 :                 if (winbindd_socket_len >= sun_path_len) {
    1498           0 :                         DBG_ERR("The winbind socket path [%s/%s] is too long "
    1499             :                                 "(%zu >= %zu)\n",
    1500             :                                 lp_winbindd_socket_directory(),
    1501             :                                 WINBINDD_SOCKET_NAME,
    1502             :                                 winbindd_socket_len,
    1503             :                                 sun_path_len);
    1504           0 :                         exit(1);
    1505             :                 }
    1506             :         } else {
    1507           0 :                 DBG_ERR("'winbindd_socket_directory' parameter is empty\n");
    1508           0 :                 exit(1);
    1509             :         }
    1510             : 
    1511          45 :         winbindd_priv_socket_dir = get_winbind_priv_pipe_dir();
    1512          45 :         winbindd_priv_socket_dir_len = strlen(winbindd_priv_socket_dir);
    1513          45 :         if (winbindd_priv_socket_dir_len > 0) {
    1514          45 :                 size_t winbindd_priv_socket_len =
    1515             :                         winbindd_priv_socket_dir_len + 1 +
    1516             :                         strlen(WINBINDD_SOCKET_NAME);
    1517          45 :                 struct sockaddr_un un = {
    1518             :                         .sun_family = AF_UNIX,
    1519             :                 };
    1520          45 :                 size_t sun_path_len = sizeof(un.sun_path);
    1521             : 
    1522          45 :                 if (winbindd_priv_socket_len >= sun_path_len) {
    1523           0 :                         DBG_ERR("The winbind privileged socket path [%s/%s] is too long "
    1524             :                                 "(%zu >= %zu)\n",
    1525             :                                 winbindd_priv_socket_dir,
    1526             :                                 WINBINDD_SOCKET_NAME,
    1527             :                                 winbindd_priv_socket_len,
    1528             :                                 sun_path_len);
    1529           0 :                         exit(1);
    1530             :                 }
    1531             :         } else {
    1532           0 :                 DBG_ERR("'winbindd_priv_socket_directory' parameter is empty\n");
    1533           0 :                 exit(1);
    1534             :         }
    1535          45 :         TALLOC_FREE(winbindd_priv_socket_dir);
    1536             : 
    1537          45 :         if (!cluster_probe_ok()) {
    1538           0 :                 exit(1);
    1539             :         }
    1540             : 
    1541             :         /* Initialise messaging system */
    1542             : 
    1543          45 :         if (global_messaging_context() == NULL) {
    1544           0 :                 exit(1);
    1545             :         }
    1546             : 
    1547          45 :         if (!winbindd_reload_services_file(NULL)) {
    1548           0 :                 DEBUG(0, ("error opening config file\n"));
    1549           0 :                 exit(1);
    1550             :         }
    1551             : 
    1552             :         {
    1553             :                 size_t i;
    1554             :                 const char *idmap_backend;
    1555          45 :                 const char *invalid_backends[] = {
    1556             :                         "ad", "rfc2307", "rid",
    1557             :                 };
    1558             : 
    1559          45 :                 idmap_backend = lp_idmap_default_backend();
    1560         180 :                 for (i = 0; i < ARRAY_SIZE(invalid_backends); i++) {
    1561         135 :                         ok = strequal(idmap_backend, invalid_backends[i]);
    1562         135 :                         if (ok) {
    1563           0 :                                 DBG_ERR("FATAL: Invalid idmap backend %s "
    1564             :                                         "configured as the default backend!\n",
    1565             :                                         idmap_backend);
    1566           0 :                                 exit(1);
    1567             :                         }
    1568             :                 }
    1569             :         }
    1570             : 
    1571          45 :         ok = directory_create_or_exist(lp_lock_directory(), 0755);
    1572          45 :         if (!ok) {
    1573           0 :                 DEBUG(0, ("Failed to create directory %s for lock files - %s\n",
    1574             :                           lp_lock_directory(), strerror(errno)));
    1575           0 :                 exit(1);
    1576             :         }
    1577             : 
    1578          45 :         ok = directory_create_or_exist(lp_pid_directory(), 0755);
    1579          45 :         if (!ok) {
    1580           0 :                 DEBUG(0, ("Failed to create directory %s for pid files - %s\n",
    1581             :                           lp_pid_directory(), strerror(errno)));
    1582           0 :                 exit(1);
    1583             :         }
    1584             : 
    1585          45 :         load_interfaces();
    1586             : 
    1587          45 :         if (!secrets_init()) {
    1588             : 
    1589           0 :                 DEBUG(0,("Could not initialize domain trust account secrets. Giving up\n"));
    1590           0 :                 return False;
    1591             :         }
    1592             : 
    1593          45 :         status = rpccli_pre_open_netlogon_creds();
    1594          45 :         if (!NT_STATUS_IS_OK(status)) {
    1595           0 :                 DEBUG(0, ("rpccli_pre_open_netlogon_creds() - %s\n",
    1596             :                           nt_errstr(status)));
    1597           0 :                 exit(1);
    1598             :         }
    1599             : 
    1600             :         /* Unblock all signals we are interested in as they may have been
    1601             :            blocked by the parent process. */
    1602             : 
    1603          45 :         BlockSignals(False, SIGINT);
    1604          45 :         BlockSignals(False, SIGQUIT);
    1605          45 :         BlockSignals(False, SIGTERM);
    1606          45 :         BlockSignals(False, SIGUSR1);
    1607          45 :         BlockSignals(False, SIGUSR2);
    1608          45 :         BlockSignals(False, SIGHUP);
    1609          45 :         BlockSignals(False, SIGCHLD);
    1610             : 
    1611          45 :         if (!interactive) {
    1612          45 :                 become_daemon(cmdline_daemon_cfg->fork,
    1613          45 :                               cmdline_daemon_cfg->no_process_group,
    1614             :                               log_stdout);
    1615             :         } else {
    1616           0 :                 daemon_status("winbindd", "Starting process ...");
    1617             :         }
    1618             : 
    1619          45 :         pidfile_create(lp_pid_directory(), "winbindd");
    1620             : 
    1621             : #ifdef HAVE_SETPGID
    1622             :         /*
    1623             :          * If we're interactive we want to set our own process group for
    1624             :          * signal management.
    1625             :          */
    1626          45 :         if (cmdline_daemon_cfg->interactive &&
    1627           0 :             !cmdline_daemon_cfg->no_process_group)
    1628             :         {
    1629           0 :                 setpgid( (pid_t)0, (pid_t)0);
    1630             :         }
    1631             : #endif
    1632             : 
    1633          45 :         TimeInit();
    1634             : 
    1635             :         /* Don't use winbindd_reinit_after_fork here as
    1636             :          * we're just starting up and haven't created any
    1637             :          * winbindd-specific resources we must free yet. JRA.
    1638             :          */
    1639             : 
    1640          45 :         status = reinit_after_fork(global_messaging_context(),
    1641             :                                    global_event_context(),
    1642             :                                    false);
    1643          45 :         if (!NT_STATUS_IS_OK(status)) {
    1644           0 :                 exit_daemon("Winbindd reinit_after_fork() failed", map_errno_from_nt_status(status));
    1645             :         }
    1646             : 
    1647          45 :         if (lp_winbind_debug_traceid()) {
    1648          45 :                 winbind_debug_traceid_setup(global_event_context());
    1649          45 :                 winbind_debug_call_depth_setup(debug_call_depth_addr());
    1650          45 :                 tevent_thread_call_depth_set_callback(
    1651          45 :                         debuglevel_get() > 1 ? winbind_call_flow : NULL,
    1652             :                         NULL);
    1653             :         }
    1654          45 :         ok = initialize_password_db(true, global_event_context());
    1655          45 :         if (!ok) {
    1656           0 :                 exit_daemon("Failed to initialize passdb backend! "
    1657             :                             "Check the 'passdb backend' variable in your "
    1658             :                             "smb.conf file.", EINVAL);
    1659             :         }
    1660             : 
    1661             :         /*
    1662             :          * Do not initialize the parent-child-pipe before becoming
    1663             :          * a daemon: this is used to detect a died parent in the child
    1664             :          * process.
    1665             :          */
    1666          45 :         status = init_before_fork();
    1667          45 :         if (!NT_STATUS_IS_OK(status)) {
    1668           0 :                 exit_daemon(nt_errstr(status), map_errno_from_nt_status(status));
    1669             :         }
    1670             : 
    1671          45 :         winbindd_register_handlers(global_messaging_context(),
    1672          45 :                                    !cmdline_daemon_cfg->fork);
    1673             : 
    1674          45 :         if (!messaging_parent_dgm_cleanup_init(global_messaging_context())) {
    1675           0 :                 exit(1);
    1676             :         }
    1677             : 
    1678          45 :         status = init_system_session_info(NULL);
    1679          45 :         if (!NT_STATUS_IS_OK(status)) {
    1680           0 :                 exit_daemon("Winbindd failed to setup system user info", map_errno_from_nt_status(status));
    1681             :         }
    1682             : 
    1683          45 :         DBG_INFO("Registering DCE/RPC endpoint servers\n");
    1684             : 
    1685          45 :         ep_server = winbind_get_ep_server();
    1686          45 :         if (ep_server == NULL) {
    1687           0 :                 DBG_ERR("Failed to get 'winbind' endpoint server\n");
    1688           0 :                 exit(1);
    1689             :         }
    1690          45 :         status = dcerpc_register_ep_server(ep_server);
    1691          45 :         if (!NT_STATUS_IS_OK(status)) {
    1692           0 :                 DBG_ERR("Failed to register 'winbind' endpoint "
    1693             :                         "server: %s\n", nt_errstr(status));
    1694           0 :                 exit(1);
    1695             :         }
    1696             : 
    1697          45 :         dce_ctx = global_dcesrv_context();
    1698             : 
    1699          45 :         DBG_INFO("Initializing DCE/RPC registered endpoint servers\n");
    1700             : 
    1701             :         /* Init all registered ep servers */
    1702          45 :         status = dcesrv_init_registered_ep_servers(dce_ctx);
    1703          45 :         if (!NT_STATUS_IS_OK(status)) {
    1704           0 :                 DBG_ERR("Failed to init DCE/RPC endpoint servers: %s\n",
    1705             :                         nt_errstr(status));
    1706           0 :                 exit(1);
    1707             :         }
    1708             : 
    1709          45 :         winbindd_init_addrchange(NULL, global_event_context(),
    1710             :                                  global_messaging_context());
    1711             : 
    1712             :         /* setup listen sockets */
    1713             : 
    1714          45 :         if (!winbindd_setup_listeners()) {
    1715           0 :                 exit_daemon("Winbindd failed to setup listeners", EPIPE);
    1716             :         }
    1717             : 
    1718          45 :         irpc_add_name(winbind_imessaging_context(), "winbind_server");
    1719             : 
    1720          45 :         TALLOC_FREE(frame);
    1721             : 
    1722          45 :         if (!interactive) {
    1723          45 :                 daemon_ready("winbindd");
    1724             :         }
    1725             : 
    1726          45 :         gpupdate_init();
    1727             : 
    1728             :         /* Loop waiting for requests */
    1729             :         while (1) {
    1730     1821335 :                 frame = talloc_stackframe();
    1731             : 
    1732     1821335 :                 if (tevent_loop_once(global_event_context()) == -1) {
    1733           0 :                         DEBUG(1, ("tevent_loop_once() failed: %s\n",
    1734             :                                   strerror(errno)));
    1735           0 :                         return 1;
    1736             :                 }
    1737             : 
    1738     1821290 :                 TALLOC_FREE(frame);
    1739             :         }
    1740             : 
    1741             :         return 0;
    1742             : }

Generated by: LCOV version 1.14