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

Generated by: LCOV version 1.13