r18937: Protect against segc in the idmap winbindd child process
[jra/samba/.git] / source / nsswitch / winbindd_dual.c
index 55f897603c11473f804345556c41a6d57df8f308..317a103f33294be789267fba4e1aa890e4431cdd 100644 (file)
@@ -46,7 +46,7 @@ static void child_read_request(struct winbindd_cli_state *state)
                        sizeof(state->request));
 
        if (len != sizeof(state->request)) {
-               DEBUG(0, ("Got invalid request length: %d\n", (int)len));
+               DEBUG(len > 0 ? 0 : 3, ("Got invalid request length: %d\n", (int)len));
                state->finished = True;
                return;
        }
@@ -108,7 +108,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
                   void (*continuation)(void *private_data, BOOL success),
                   void *private_data)
 {
-       struct winbindd_async_request *state, *tmp;
+       struct winbindd_async_request *state;
 
        SMB_ASSERT(continuation != NULL);
 
@@ -127,7 +127,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
        state->continuation = continuation;
        state->private_data = private_data;
 
-       DLIST_ADD_END(child->requests, state, tmp);
+       DLIST_ADD_END(child->requests, state, struct winbindd_async_request *);
 
        schedule_async_request(child);
 
@@ -576,7 +576,17 @@ static void child_msg_offline(int msg_type, struct process_id src, void *buf, si
 
        for (domain = domain_list(); domain; domain = domain->next) {
                DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
-               domain->online = False;
+               set_domain_offline(domain);
+       }
+}
+
+/* Ensure any negative cache entries with the netbios or realm names are removed. */
+
+void winbindd_flush_negative_conn_cache(struct winbindd_domain *domain)
+{
+       flush_negative_conn_cache_for_domain(domain->name);
+       if (*domain->alt_name) {
+               flush_negative_conn_cache_for_domain(domain->alt_name);
        }
 }
 
@@ -596,15 +606,16 @@ static void child_msg_online(int msg_type, struct process_id src, void *buf, siz
        /* Set our global state as online. */
        set_global_winbindd_state_online();
 
-       winbindd_flush_nscd_cache();
+       smb_nscd_flush_user_cache();
+       smb_nscd_flush_group_cache();
 
-       /* Mark everything online - delete any negative cache entries
-          to force an immediate reconnect. */
+       /* Try and mark everything online - delete any negative cache entries
+          to force a reconnect now. */
 
        for (domain = domain_list(); domain; domain = domain->next) {
                DEBUG(5,("child_msg_online: marking %s online.\n", domain->name));
-               domain->online = True;
-               check_negative_conn_cache_timeout(domain->name, domain->dcname, 0);
+               winbindd_flush_negative_conn_cache(domain);
+               set_domain_online_request(domain);
        }
 }
 
@@ -614,7 +625,7 @@ static const char *collect_onlinestatus(TALLOC_CTX *mem_ctx)
        char *buf = NULL;
 
        if ((buf = talloc_asprintf(mem_ctx, "global:%s ", 
-                                  get_global_winbindd_state_online() ? 
+                                  get_global_winbindd_state_offline() ? 
                                   "Offline":"Online")) == NULL) {
                return NULL;
        }
@@ -671,6 +682,7 @@ static BOOL fork_domain_child(struct winbindd_child *child)
        int fdpair[2];
        struct winbindd_cli_state state;
        extern BOOL override_logfile;
+       time_t startup_time;
 
        if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
                DEBUG(0, ("Could not open child pipe: %s\n",
@@ -754,6 +766,11 @@ static BOOL fork_domain_child(struct winbindd_child *child)
        message_register(MSG_WINBIND_ONLINE,child_msg_online);
        message_register(MSG_WINBIND_ONLINESTATUS,child_msg_onlinestatus);
 
+       if ( child->domain ) {
+               child->domain->startup = True;
+       }
+       startup_time = time(NULL);
+
        while (1) {
 
                int ret;
@@ -770,6 +787,13 @@ static BOOL fork_domain_child(struct winbindd_child *child)
 
                GetTimeOfDay(&now);
 
+               if (child->domain && child->domain->startup && (now.tv_sec > startup_time + 30)) {
+                       /* No longer in "startup" mode. */
+                       DEBUG(10,("fork_domain_child: domain %s no longer in 'startup' mode.\n",
+                               child->domain->name ));
+                       child->domain->startup = False;
+               }
+
                tp = get_timed_events_timeout(&t);
                if (tp) {
                        DEBUG(11,("select will use timeout of %u.%u seconds\n",