s3: make better use of ccache by not including version.h in every C-file.
[metze/samba/wip.git] / source3 / winbindd / winbindd_misc.c
index 8933cf27945d058dcd58af1807bb72cbaeecb6da..737fd08d2a2221af0b58576f16ad99f96279c8a3 100644 (file)
@@ -86,10 +86,7 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do
                   "good" : "bad"));
 
  done:
-       state->response.data.auth.nt_status = NT_STATUS_V(result);
-       fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
-       fstrcpy(state->response.data.auth.error_string, nt_errstr(result));
-       state->response.data.auth.pam_error = nt_status_to_pam(result);
+       set_auth_errors(&state->response, result);
 
        DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Checking the trust account password returned %s\n", 
                                                state->response.data.auth.nt_status_string));
@@ -97,6 +94,129 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do
        return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
 }
 
+/* Helpers for listing user and group names */
+
+const char *ent_type_strings[] = {"users", 
+                                 "groups"};
+
+static const char *get_ent_type_string(enum ent_type type)
+{
+       return ent_type_strings[type];
+}
+
+struct listent_state {
+       TALLOC_CTX *mem_ctx;
+       struct winbindd_cli_state *cli_state;
+       enum ent_type type;
+       int domain_count;
+       char *extra_data;
+       uint32_t extra_data_len;
+};
+
+static void listent_recv(void *private_data, bool success, fstring dom_name,
+                        char *extra_data);
+
+/* List domain users/groups without mapping to unix ids */
+void winbindd_list_ent(struct winbindd_cli_state *state, enum ent_type type)
+{
+       struct winbindd_domain *domain;
+       const char *which_domain;
+       struct listent_state *ent_state;
+
+       DEBUG(3, ("[%5lu]: list %s\n", (unsigned long)state->pid, 
+             get_ent_type_string(type)));
+
+       /* Ensure null termination */
+       state->request.domain_name[sizeof(state->request.domain_name)-1]='\0';  
+       which_domain = state->request.domain_name;
+       
+       /* Initialize listent_state */
+       ent_state = TALLOC_P(state->mem_ctx, struct listent_state);
+       if (ent_state == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               request_error(state);
+               return;
+       }
+
+       ent_state->mem_ctx = state->mem_ctx;
+       ent_state->cli_state = state;
+       ent_state->type = type;
+       ent_state->domain_count = 0;
+       ent_state->extra_data = NULL;
+       ent_state->extra_data_len = 0;
+
+       /* Must count the full list of expected domains before we request data
+        * from any of them.  Otherwise it's possible for a connection to the
+        * first domain to fail, call listent_recv(), and return to the
+        * client without checking any other domains. */
+       for (domain = domain_list(); domain; domain = domain->next) {
+               /* if we have a domain name restricting the request and this
+                  one in the list doesn't match, then just bypass the remainder
+                  of the loop */
+               if ( *which_domain && !strequal(which_domain, domain->name) )
+                       continue;
+
+               ent_state->domain_count++;
+       }
+
+       /* Make sure we're enumerating at least one domain */
+       if (!ent_state->domain_count) {
+               request_ok(state);
+               return;
+       }
+
+       /* Enumerate list of trusted domains and request user/group list from
+        * each */
+       for (domain = domain_list(); domain; domain = domain->next) {
+               if ( *which_domain && !strequal(which_domain, domain->name) )
+                       continue;
+
+               winbindd_listent_async(state->mem_ctx, domain, 
+                                         listent_recv, ent_state, type);
+       }
+}
+
+static void listent_recv(void *private_data, bool success, fstring dom_name,
+                        char *extra_data)
+{
+       /* extra_data comes to us as a '\0' terminated string of comma
+          separated users or groups */
+       struct listent_state *state = talloc_get_type_abort(
+               private_data, struct listent_state);
+
+       /* Append users/groups from one domain onto the whole list */
+       if (extra_data) {
+               DEBUG(5, ("listent_recv: %s returned %s.\n", 
+                     dom_name, get_ent_type_string(state->type)));
+                if (!state->extra_data)
+                        state->extra_data = talloc_asprintf(state->mem_ctx,
+                                                            "%s", extra_data);
+                else
+                        state->extra_data = talloc_asprintf_append(
+                                                            state->extra_data,
+                                                            ",%s", extra_data);
+                /* Add one for the '\0' and each additional ',' */
+                state->extra_data_len += strlen(extra_data) + 1;
+       }
+       else {
+               DEBUG(5, ("listent_recv: %s returned no %s.\n", 
+                     dom_name, get_ent_type_string(state->type)));
+       }
+
+       if (--state->domain_count)
+               /* Still waiting for some child domains to return */
+               return;
+
+       /* Return list of all users/groups to the client */
+       if (state->extra_data) {
+               state->cli_state->response.extra_data.data = 
+                       SMB_STRDUP(state->extra_data);
+               state->cli_state->response.length += state->extra_data_len;
+       }
+
+       request_ok(state->cli_state);
+}      
+
 /* Constants and helper functions for determining domain trust types */
 
 enum trust_type {
@@ -372,7 +492,7 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain,
 
        if (!W_ERROR_IS_OK(werr)) {
                DEBUG(5, ("Error requesting DCname for domain %s: %s\n",
-                       state->request.domain_name, dos_errstr(werr)));
+                       state->request.domain_name, win_errstr(werr)));
                return WINBINDD_ERROR;
        }
 
@@ -622,7 +742,7 @@ void winbindd_info(struct winbindd_cli_state *state)
        DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
 
        state->response.data.info.winbind_separator = *lp_winbind_separator();
-       fstrcpy(state->response.data.info.samba_version, SAMBA_VERSION_STRING);
+       fstrcpy(state->response.data.info.samba_version, samba_version_string());
        request_ok(state);
 }