s3:pylibsmb: Make .list() work for SMBv2
[samba.git] / source3 / winbindd / wb_getpwsid.c
index fc696cb9a1884069547ab1e526f4116fa26e6484..8dc09eb513d3915be70d912da740a2a0d9c01ddc 100644 (file)
 
 #include "includes.h"
 #include "winbindd.h"
-#include "librpc/gen_ndr/cli_wbint.h"
+#include "librpc/gen_ndr/ndr_winbind_c.h"
+#include "../libcli/security/security.h"
 
 struct wb_getpwsid_state {
-       struct winbindd_domain *user_domain;
        struct tevent_context *ev;
        struct dom_sid sid;
-       struct winbind_userinfo *userinfo;
+       struct wbint_userinfo *userinfo;
        struct winbindd_pw *pw;
 };
 
 static void wb_getpwsid_queryuser_done(struct tevent_req *subreq);
-static void wb_getpwsid_lookupsid_done(struct tevent_req *subreq);
-static void wb_getpwsid_sid2uid_done(struct tevent_req *subreq);
-static void wb_getpwsid_sid2gid_done(struct tevent_req *subreq);
 
 struct tevent_req *wb_getpwsid_send(TALLOC_CTX *mem_ctx,
                                    struct tevent_context *ev,
@@ -50,9 +47,9 @@ struct tevent_req *wb_getpwsid_send(TALLOC_CTX *mem_ctx,
        state->ev = ev;
        state->pw = pw;
 
-       state->user_domain = find_domain_from_sid_noinit(user_sid);
-       if (state->user_domain == NULL) {
-               tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
+       if (dom_sid_in_domain(&global_sid_Unix_Users, user_sid)) {
+               /* unmapped Unix users must be resolved locally */
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
                return tevent_req_post(req, ev);
        }
 
@@ -70,154 +67,84 @@ static void wb_getpwsid_queryuser_done(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct wb_getpwsid_state *state = tevent_req_data(
                req, struct wb_getpwsid_state);
+       struct winbindd_pw *pw = state->pw;
+       struct wbint_userinfo *info;
+       fstring acct_name;
+       const char *output_username = NULL;
+       char *mapped_name = NULL;
+       char *tmp;
        NTSTATUS status;
 
        status = wb_queryuser_recv(subreq, state, &state->userinfo);
        TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
                return;
        }
+       info = state->userinfo;
 
-       if ((state->userinfo->acct_name != NULL)
-           && (state->userinfo->acct_name[0] != '\0')) {
-               /*
-                * QueryUser got us a name, let's got directly to the
-                * sid2uid step
-                */
-               subreq = wb_sid2uid_send(state, state->ev,
-                                        &state->userinfo->user_sid);
-               if (tevent_req_nomem(subreq, req)) {
-                       return;
-               }
-               tevent_req_set_callback(subreq, wb_getpwsid_sid2uid_done, req);
+       pw->pw_uid = info->uid;
+       pw->pw_gid = info->primary_gid;
+
+       fstrcpy(acct_name, info->acct_name);
+       if (!strlower_m(acct_name)) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
                return;
        }
 
        /*
-        * QueryUser didn't get us a name, do it via LSA.
+        * TODO:
+        * This function should be called in 'idmap winbind child'. It shouldn't
+        * be a blocking call, but for this we need to add a new function for
+        * winbind.idl. This is a fix which can be backported for now.
         */
-       subreq = wb_lookupsid_send(state, state->ev,
-                                  &state->userinfo->user_sid);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
-       }
-       tevent_req_set_callback(subreq, wb_getpwsid_lookupsid_done, req);
-}
-
-static void wb_getpwsid_lookupsid_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct wb_getpwsid_state *state = tevent_req_data(
-               req, struct wb_getpwsid_state);
-       NTSTATUS status;
-       enum lsa_SidType type;
-       const char *domain;
-
-       status = wb_lookupsid_recv(subreq, state->userinfo, &type, &domain,
-                                  &state->userinfo->acct_name);
-       TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-               return;
-       }
-       subreq = wb_sid2uid_send(state, state->ev, &state->userinfo->user_sid);
-       if (tevent_req_nomem(subreq, req)) {
-               return;
-       }
-       tevent_req_set_callback(subreq, wb_getpwsid_sid2uid_done, req);
-}
-
-static void wb_getpwsid_sid2uid_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct wb_getpwsid_state *state = tevent_req_data(
-               req, struct wb_getpwsid_state);
-       NTSTATUS status;
-
-       status = wb_sid2uid_recv(subreq, &state->pw->pw_uid);
-       TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-               return;
-       }
-       subreq = wb_sid2gid_send(state, state->ev,
-                                &state->userinfo->group_sid);
-       if (tevent_req_nomem(subreq, req)) {
+       status = normalize_name_map(state,
+                                   info->domain_name,
+                                   acct_name,
+                                   &mapped_name);
+       if (NT_STATUS_IS_OK(status) ||
+           NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
+               fstrcpy(acct_name, mapped_name);
+       }
+       output_username = fill_domain_username_talloc(state,
+                                                     info->domain_name,
+                                                     acct_name,
+                                                     true);
+       if (output_username == NULL) {
+               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
                return;
        }
-       tevent_req_set_callback(subreq, wb_getpwsid_sid2gid_done, req);
-}
 
-static void wb_getpwsid_sid2gid_done(struct tevent_req *subreq)
-{
-       struct tevent_req *req = tevent_req_callback_data(
-               subreq, struct tevent_req);
-       struct wb_getpwsid_state *state = tevent_req_data(
-               req, struct wb_getpwsid_state);
-       NTSTATUS status;
-       char *username;
-       char *mapped_name;
+       strlcpy(pw->pw_name, output_username, sizeof(pw->pw_name));
 
-       status = wb_sid2gid_recv(subreq, &state->pw->pw_gid);
-       TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
-               return;
-       }
+       strlcpy(pw->pw_gecos, info->full_name ? info->full_name : "",
+               sizeof(pw->pw_gecos));
 
-       username = talloc_strdup_lower(state, state->userinfo->acct_name);
-       if (tevent_req_nomem(username, req)) {
+       tmp = talloc_sub_specified(
+               state, info->homedir, acct_name,
+               info->primary_group_name, info->domain_name,
+               pw->pw_uid, pw->pw_gid);
+       if (tevent_req_nomem(tmp, req)) {
                return;
        }
+       strlcpy(pw->pw_dir, tmp, sizeof(pw->pw_dir));
+       TALLOC_FREE(tmp);
 
-       status = normalize_name_map(state, state->user_domain, username,
-                                   &mapped_name);
-
-       if (NT_STATUS_IS_OK(status)
-           || NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
-               /*
-                * normalize_name_map did something
-                */
-               fstrcpy(state->pw->pw_name, mapped_name);
-               TALLOC_FREE(mapped_name);
-       } else {
-               fill_domain_username(state->pw->pw_name,
-                                    state->user_domain->name,
-                                    username, True);
-       }
-       fstrcpy(state->pw->pw_passwd, "*");
-       fstrcpy(state->pw->pw_gecos, state->userinfo->full_name);
-
-       if (!fillup_pw_field(lp_template_homedir(), username,
-                            state->user_domain->name, state->pw->pw_uid,
-                            state->pw->pw_gid, state->userinfo->homedir,
-                            state->pw->pw_dir)) {
-               DEBUG(5, ("Could not compose homedir\n"));
-               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+       tmp = talloc_sub_specified(
+               state, info->shell, acct_name,
+               info->primary_group_name, info->domain_name,
+               pw->pw_uid, pw->pw_gid);
+       if (tevent_req_nomem(tmp, req)) {
                return;
        }
+       strlcpy(pw->pw_shell, tmp, sizeof(pw->pw_shell));
+       TALLOC_FREE(tmp);
 
-       if (!fillup_pw_field(lp_template_shell(), state->pw->pw_name,
-                            state->user_domain->name, state->pw->pw_uid,
-                            state->pw->pw_gid, state->userinfo->shell,
-                            state->pw->pw_shell)) {
-               DEBUG(5, ("Could not compose shell\n"));
-               tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
-               return;
-       }
+       strlcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd));
 
        tevent_req_done(req);
 }
 
 NTSTATUS wb_getpwsid_recv(struct tevent_req *req)
 {
-       NTSTATUS status;
-
-       if (tevent_req_is_nterror(req, &status)) {
-               return status;
-       }
-       return NT_STATUS_OK;
+       return tevent_req_simple_recv_ntstatus(req);
 }