Back-ported fix from 3.2 (mainly from Bo Yang <boyang@novell.com>)
[tprouty/samba.git] / source / nsswitch / winbindd_async.c
index a8a92c3caead17b9dcbf370b22b7735d40f35bf0..ad136bdc0d783eaf437a523fd5e40b424ae78c3b 100644 (file)
@@ -163,6 +163,7 @@ enum winbindd_result winbindd_dual_set_mapping(struct winbindd_domain *domain,
        map.sid = &sid;
        map.xid.id = state->request.data.dual_idmapset.id;
        map.xid.type = state->request.data.dual_idmapset.type;
+       map.status = ID_MAPPED;
 
        result = idmap_set_mapping(&map);
        return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
@@ -273,6 +274,11 @@ enum winbindd_result winbindd_dual_sids2xids(struct winbindd_domain *domain,
 
        DEBUG(3, ("[%5lu]: sids to unix ids\n", (unsigned long)state->pid));
 
+       if (state->request.extra_len == 0) {
+               DEBUG(0, ("Invalid buffer size!\n"));
+               return WINBINDD_ERROR;
+       }
+
        sids = (DOM_SID *)state->request.extra_data.data;
        num = state->request.extra_len / sizeof(DOM_SID);
 
@@ -776,6 +782,12 @@ enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
  This is the second callback after contacting the forest root
 ********************************************************************/
 
+struct lookupname_state {
+       char *dom_name;
+       char *name;
+       void *caller_private_data;
+};
+
 static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success,
                            struct winbindd_response *response,
                            void *c, void *private_data)
@@ -784,27 +796,28 @@ static void lookupname_recv2(TALLOC_CTX *mem_ctx, BOOL success,
                     enum lsa_SidType type) =
                (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c;
        DOM_SID sid;
+       struct lookupname_state *s = talloc_get_type_abort(private_data, struct lookupname_state);
 
        if (!success) {
                DEBUG(5, ("Could not trigger lookup_name\n"));
-               cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+               cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
                return;
        }
 
        if (response->result != WINBINDD_OK) {
                DEBUG(5, ("lookup_name returned an error\n"));
-               cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+               cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
                return;
        }
 
        if (!string_to_sid(&sid, response->data.sid.sid)) {
                DEBUG(0, ("Could not convert string %s to sid\n",
                          response->data.sid.sid));
-               cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+               cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
                return;
        }
 
-       cont(private_data, True, &sid,
+       cont(s->caller_private_data, True, &sid,
             (enum lsa_SidType)response->data.sid.type);
 }
 
@@ -820,36 +833,32 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
                     enum lsa_SidType type) =
                (void (*)(void *, BOOL, const DOM_SID *, enum lsa_SidType))c;
        DOM_SID sid;
+       struct lookupname_state *s = talloc_get_type_abort(private_data, struct lookupname_state);
 
        if (!success) {
                DEBUG(5, ("lookupname_recv: lookup_name() failed!\n"));
-               cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+               cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
                return;
        }
 
        if (response->result != WINBINDD_OK) {
                /* Try again using the forest root */
                struct winbindd_domain *root_domain = find_root_domain();
-               struct winbindd_cli_state *state = (struct winbindd_cli_state*)private_data;            
-               struct winbindd_request request;                
-               char *name_domain, *name_account;
-               
+               struct winbindd_request request;
+
                if ( !root_domain ) {
                        DEBUG(5,("lookupname_recv: unable to determine forest root\n"));
-                       cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+                       cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
                        return;
                }
 
-               name_domain  = state->request.data.name.dom_name;
-               name_account = state->request.data.name.name;   
-
                ZERO_STRUCT(request);
                request.cmd = WINBINDD_LOOKUPNAME;
-               fstrcpy(request.data.name.dom_name, name_domain);
-               fstrcpy(request.data.name.name, name_account);
+               fstrcpy(request.data.name.dom_name, s->dom_name);
+               fstrcpy(request.data.name.name, s->name);
 
                do_async_domain(mem_ctx, root_domain, &request, lookupname_recv2,
-                               (void *)cont, private_data);
+                               (void *)cont, s);
 
                return;
        }
@@ -857,11 +866,11 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, BOOL success,
        if (!string_to_sid(&sid, response->data.sid.sid)) {
                DEBUG(0, ("Could not convert string %s to sid\n",
                          response->data.sid.sid));
-               cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+               cont(s->caller_private_data, False, NULL, SID_NAME_UNKNOWN);
                return;
        }
 
-       cont(private_data, True, &sid,
+       cont(s->caller_private_data, True, &sid,
             (enum lsa_SidType)response->data.sid.type);
 }
 
@@ -880,6 +889,7 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx,
 {
        struct winbindd_request request;
        struct winbindd_domain *domain;
+       struct lookupname_state *s;
 
        if ( (domain = find_lookup_domain_from_name(dom_name)) == NULL ) {
                DEBUG(5, ("Could not find domain for name %s\n", dom_name));
@@ -892,8 +902,23 @@ void winbindd_lookupname_async(TALLOC_CTX *mem_ctx,
        fstrcpy(request.data.name.dom_name, dom_name);
        fstrcpy(request.data.name.name, name);
 
+       if ( (s = TALLOC_ZERO_P(mem_ctx, struct lookupname_state)) == NULL ) {
+               DEBUG(0, ("winbindd_lookupname_async: talloc failed\n"));
+               cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+               return;
+       }
+
+       s->dom_name = talloc_strdup( s, dom_name );
+       s->name     = talloc_strdup( s, name );
+       if (!s->dom_name || !s->name) {
+               cont(private_data, False, NULL, SID_NAME_UNKNOWN);
+               return;
+       }
+
+       s->caller_private_data = private_data;
+
        do_async_domain(mem_ctx, domain, &request, lookupname_recv,
-                       (void *)cont, private_data);
+                       (void *)cont, s);
 }
 
 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
@@ -1407,6 +1432,12 @@ static void query_user_recv(TALLOC_CTX *mem_ctx, BOOL success,
                return;
        }
 
+       if (response->result != WINBINDD_OK) {
+               DEBUG(5, ("query_user returned an error\n"));
+               cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
+               return;
+       }
+
        cont(private_data, True, response->data.user_info.acct_name,
             response->data.user_info.full_name,
             response->data.user_info.homedir,