LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 418 657 63.6 %
Date: 2024-05-31 13:13:24 Functions: 22 28 78.6 %

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

Generated by: LCOV version 1.14