idmap_gid_to_sid: Fix a cut-a-npaste error.
[kai/samba.git] / source3 / winbindd / winbindd_dual.c
index 1f2972f9b2be5b3a6c9dd7c47f7e109b98f3ca34..1e8325f98338efe3be1f244103687994bfe74f3c 100644 (file)
@@ -40,15 +40,16 @@ extern struct winbindd_methods cache_methods;
 
 static void child_read_request(struct winbindd_cli_state *state)
 {
-       ssize_t len;
+       NTSTATUS status;
 
        /* Read data */
 
-       len = read_data(state->sock, (char *)&state->request,
-                       sizeof(state->request), NULL);
+       status = read_data(state->sock, (char *)&state->request,
+                          sizeof(state->request));
 
-       if (len != sizeof(state->request)) {
-               DEBUG(len > 0 ? 0 : 3, ("Got invalid request length: %d\n", (int)len));
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3, ("child_read_request: read_data failed: %s\n",
+                         nt_errstr(status)));
                state->finished = True;
                return;
        }
@@ -72,11 +73,12 @@ static void child_read_request(struct winbindd_cli_state *state)
        /* Ensure null termination */
        state->request.extra_data.data[state->request.extra_len] = '\0';
 
-       len = read_data(state->sock, state->request.extra_data.data,
-                       state->request.extra_len, NULL);
+       status= read_data(state->sock, state->request.extra_data.data,
+                         state->request.extra_len);
 
-       if (len != state->request.extra_len) {
-               DEBUG(0, ("Could not read extra data\n"));
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Could not read extra data: %s\n",
+                         nt_errstr(status)));
                state->finished = True;
                return;
        }
@@ -102,6 +104,7 @@ struct winbindd_async_request {
        void *private_data;
 };
 
+static void async_request_fail(struct winbindd_async_request *state);
 static void async_main_request_sent(void *private_data, bool success);
 static void async_request_sent(void *private_data, bool success);
 static void async_reply_recv(void *private_data, bool success);
@@ -127,6 +130,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
 
        state->mem_ctx = mem_ctx;
        state->child = child;
+       state->reply_timeout_event = NULL;
        state->request = request;
        state->response = response;
        state->continuation = continuation;
@@ -146,10 +150,7 @@ static void async_main_request_sent(void *private_data, bool success)
 
        if (!success) {
                DEBUG(5, ("Could not send async request\n"));
-
-               state->response->length = sizeof(struct winbindd_response);
-               state->response->result = WINBINDD_ERROR;
-               state->continuation(state->private_data, False);
+               async_request_fail(state);
                return;
        }
 
@@ -476,6 +477,10 @@ void winbind_child_died(pid_t pid)
                return;
        }
 
+       /* This will be re-added in fork_domain_child() */
+
+       DLIST_REMOVE(children, child);
+       
        remove_fd_event(&child->event);
        close(child->event.fd);
        child->event.fd = 0;
@@ -495,6 +500,36 @@ void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
        }
 }
 
+/* 
+ * Parent winbindd process sets its own debug level first and then
+ * sends a message to all the winbindd children to adjust their debug
+ * level to that of parents.
+ */
+
+void winbind_msg_debug(struct messaging_context *msg_ctx,
+                        void *private_data,
+                        uint32_t msg_type,
+                        struct server_id server_id,
+                        DATA_BLOB *data)
+{
+       struct winbindd_child *child;
+
+       DEBUG(10,("winbind_msg_debug: got debug message.\n"));
+       
+       debug_message(msg_ctx, private_data, MSG_DEBUG, server_id, data);
+
+       for (child = children; child != NULL; child = child->next) {
+
+               DEBUG(10,("winbind_msg_debug: sending message to pid %u.\n",
+                       (unsigned int)child->pid));
+
+               messaging_send_buf(msg_ctx, pid_to_procid(child->pid),
+                          MSG_DEBUG,
+                          data->data,
+                          strlen((char *) data->data) + 1);
+       }
+}
+
 /* Set our domains as offline and forward the offline message to our children. */
 
 void winbind_msg_offline(struct messaging_context *msg_ctx,
@@ -768,7 +803,7 @@ static void account_lockout_policy_handler(struct event_context *ctx,
                (struct winbindd_child *)private_data;
        TALLOC_CTX *mem_ctx = NULL;
        struct winbindd_methods *methods;
-       SAM_UNK_INFO_12 lockout_policy;
+       struct samr_DomInfo12 lockout_policy;
        NTSTATUS result;
 
        DEBUG(10,("account_lockout_policy_handler called\n"));
@@ -959,6 +994,7 @@ static bool fork_domain_child(struct winbindd_child *child)
        int fdpair[2];
        struct winbindd_cli_state state;
        struct winbindd_domain *domain;
+       struct winbindd_domain *primary_domain = NULL;
 
        if (child->domain) {
                DEBUG(10, ("fork_domain_child called for domain '%s'\n",
@@ -976,9 +1012,6 @@ static bool fork_domain_child(struct winbindd_child *child)
        ZERO_STRUCT(state);
        state.pid = sys_getpid();
 
-       /* Stop zombies */
-       CatchChild();
-
        child->pid = sys_fork();
 
        if (child->pid == -1) {
@@ -1000,12 +1033,16 @@ static bool fork_domain_child(struct winbindd_child *child)
 
        /* Child */
 
+       DEBUG(10, ("Child process %d\n", (int)sys_getpid()));
+
+       /* Stop zombies in children */
+       CatchChild();
+
        state.sock = fdpair[0];
        close(fdpair[1]);
 
-       /* tdb needs special fork handling */
-       if (tdb_reopen_all(1) == -1) {
-               DEBUG(0,("tdb_reopen_all failed.\n"));
+       if (!reinit_after_fork(winbind_messaging_context(), true)) {
+               DEBUG(0,("reinit_after_fork() failed\n"));
                _exit(0);
        }
 
@@ -1038,6 +1075,8 @@ static bool fork_domain_child(struct winbindd_child *child)
                             MSG_DUMP_EVENT_LIST, NULL);
        messaging_deregister(winbind_messaging_context(),
                             MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);
+       messaging_deregister(winbind_messaging_context(),
+                            MSG_DEBUG, NULL);
 
        /* Handle online/offline messages. */
        messaging_register(winbind_messaging_context(), NULL,
@@ -1048,6 +1087,8 @@ static bool fork_domain_child(struct winbindd_child *child)
                           MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus);
        messaging_register(winbind_messaging_context(), NULL,
                           MSG_DUMP_EVENT_LIST, child_msg_dump_event_list);
+       messaging_register(winbind_messaging_context(), NULL,
+                          MSG_DEBUG, debug_message);
 
        if ( child->domain ) {
                child->domain->startup = True;
@@ -1055,10 +1096,13 @@ static bool fork_domain_child(struct winbindd_child *child)
        }
 
        /* Ensure we have no pending check_online events other
-          than one for this domain. */
+          than one for this domain or the primary domain. */
 
        for (domain = domain_list(); domain; domain = domain->next) {
-               if (domain != child->domain) {
+               if (domain->primary) {
+                       primary_domain = domain;
+               }
+               if ((domain != child->domain) && !domain->primary) {
                        TALLOC_FREE(domain->check_online_event);
                }
        }
@@ -1075,6 +1119,18 @@ static bool fork_domain_child(struct winbindd_child *child)
 
                set_domain_online_request(child->domain);
 
+               if (primary_domain != child->domain) {
+                       /* We need to talk to the primary
+                        * domain as well as the trusted
+                        * domain inside a trusted domain
+                        * child.
+                        * See the code in :
+                        * set_dc_type_and_flags_trustinfo()
+                        * for details.
+                        */
+                       set_domain_online_request(primary_domain);
+               }
+
                child->lockout_policy_event = event_add_timed(
                        winbind_event_context(), NULL, timeval_zero(),
                        "account_lockout_policy_handler",
@@ -1082,16 +1138,6 @@ static bool fork_domain_child(struct winbindd_child *child)
                        child);
        }
 
-       /* Special case for Winbindd on a Samba DC,
-        * We want to make sure the child can connect to smbd
-        * but not the main daemon */
-
-       if (child->domain && child->domain->internal && IS_DC) {
-               child->domain->internal = False;
-               child->domain->methods = &cache_methods;
-               child->domain->online = False;
-       }
-
        while (1) {
 
                int ret;
@@ -1101,6 +1147,11 @@ static bool fork_domain_child(struct winbindd_child *child)
                struct timeval now;
                TALLOC_CTX *frame = talloc_stackframe();
 
+               /* check for signals */
+               winbind_check_sigterm(false);
+               winbind_check_sighup(override_logfile ? NULL :
+                               child->logfilename);
+
                run_events(winbind_event_context(), 0, NULL, NULL);
 
                GetTimeOfDay(&now);