idmap_autorid: Make idmap_autorid_acquire_range public
[sfrench/samba-autobuild/.git] / source3 / winbindd / wb_fill_pwent.c
index 6fad5f43605f6b1047d244299a01d9b7fd0409f0..2229b056cfed9f067d5af66d42229199be2036cd 100644 (file)
 
 #include "includes.h"
 #include "winbindd.h"
-#include "librpc/gen_ndr/ndr_wbint_c.h"
+#include "librpc/gen_ndr/ndr_winbind_c.h"
 
 struct wb_fill_pwent_state {
        struct tevent_context *ev;
-       struct wbint_userinfo *info;
+       const struct wbint_userinfo *info;
        struct winbindd_pw *pw;
 };
 
 static bool fillup_pw_field(const char *lp_template,
                            const char *username,
+                           const char *grpname,
                            const char *domname,
                            uid_t uid,
                            gid_t gid,
@@ -36,11 +37,11 @@ static bool fillup_pw_field(const char *lp_template,
                            fstring out);
 
 static void wb_fill_pwent_sid2uid_done(struct tevent_req *subreq);
-static void wb_fill_pwent_sid2gid_done(struct tevent_req *subreq);
+static void wb_fill_pwent_getgrsid_done(struct tevent_req *subreq);
 
 struct tevent_req *wb_fill_pwent_send(TALLOC_CTX *mem_ctx,
                                      struct tevent_context *ev,
-                                     struct wbint_userinfo *info,
+                                     const struct wbint_userinfo *info,
                                      struct winbindd_pw *pw)
 {
        struct tevent_req *req, *subreq;
@@ -54,7 +55,7 @@ struct tevent_req *wb_fill_pwent_send(TALLOC_CTX *mem_ctx,
        state->info = info;
        state->pw = pw;
 
-       subreq = wb_sid2uid_send(state, state->ev, &state->info->user_sid);
+       subreq = wb_sids2xids_send(state, state->ev, &state->info->user_sid, 1);
        if (tevent_req_nomem(subreq, req)) {
                return tevent_req_post(req, ev);
        }
@@ -69,42 +70,66 @@ static void wb_fill_pwent_sid2uid_done(struct tevent_req *subreq)
        struct wb_fill_pwent_state *state = tevent_req_data(
                req, struct wb_fill_pwent_state);
        NTSTATUS status;
+       struct unixid xids[1];
 
-       status = wb_sid2uid_recv(subreq, &state->pw->pw_uid);
+       status = wb_sids2xids_recv(subreq, xids, ARRAY_SIZE(xids));
        TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
                return;
        }
 
-       subreq = wb_sid2gid_send(state, state->ev, &state->info->group_sid);
+       /*
+        * We are filtering further down in sids2xids, but that filtering
+        * depends on the actual type of the sid handed in (as determined
+        * by lookupsids). Here we need to filter for the type of object
+        * actually requested, in this case uid.
+        */
+       if (!(xids[0].type == ID_TYPE_UID || xids[0].type == ID_TYPE_BOTH)) {
+               tevent_req_nterror(req, NT_STATUS_NONE_MAPPED);
+               return;
+       }
+
+       state->pw->pw_uid = (uid_t)xids[0].id;
+
+       subreq = wb_getgrsid_send(state, state->ev, &state->info->group_sid, 0);
        if (tevent_req_nomem(subreq, req)) {
                return;
        }
-       tevent_req_set_callback(subreq, wb_fill_pwent_sid2gid_done, req);
+       tevent_req_set_callback(subreq, wb_fill_pwent_getgrsid_done, req);
 }
 
-static void wb_fill_pwent_sid2gid_done(struct tevent_req *subreq)
+static void wb_fill_pwent_getgrsid_done(struct tevent_req *subreq)
 {
        struct tevent_req *req = tevent_req_callback_data(
                subreq, struct tevent_req);
        struct wb_fill_pwent_state *state = tevent_req_data(
                req, struct wb_fill_pwent_state);
        struct winbindd_domain *domain;
-       char *dom_name;
+       const char *dom_name;
+       const char *grp_name;
        fstring user_name, output_username;
        char *mapped_name = NULL;
+       struct talloc_dict *members;
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
        NTSTATUS status;
-
-       status = wb_sid2gid_recv(subreq, &state->pw->pw_gid);
+       bool ok;
+
+       /* xid handling is done in getgrsid() */
+       status = wb_getgrsid_recv(subreq,
+                                 tmp_ctx,
+                                 &dom_name,
+                                 &grp_name,
+                                 &state->pw->pw_gid,
+                                 &members);
        TALLOC_FREE(subreq);
-       if (!NT_STATUS_IS_OK(status)) {
-               tevent_req_nterror(req, status);
+       if (tevent_req_nterror(req, status)) {
+               talloc_free(tmp_ctx);
                return;
        }
 
        domain = find_domain_from_sid_noinit(&state->info->user_sid);
        if (domain == NULL) {
+               talloc_free(tmp_ctx);
                tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
                return;
        }
@@ -113,7 +138,10 @@ static void wb_fill_pwent_sid2gid_done(struct tevent_req *subreq)
        /* Username */
 
        fstrcpy(user_name, state->info->acct_name);
-       strlower_m(user_name);
+       if (!strlower_m(user_name)) {
+               tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+               return;
+       }
        status = normalize_name_map(state, domain, user_name, &mapped_name);
 
        /* Basic removal of whitespace */
@@ -134,20 +162,36 @@ static void wb_fill_pwent_sid2gid_done(struct tevent_req *subreq)
        strlcpy(state->pw->pw_name,
                output_username,
                sizeof(state->pw->pw_name));
-       fstrcpy(state->pw->pw_gecos, state->info->full_name);
+       /* FIXME The full_name can be longer than 255 chars */
+       strlcpy(state->pw->pw_gecos,
+               state->info->full_name != NULL ? state->info->full_name : "",
+               sizeof(state->pw->pw_gecos));
 
        /* Home directory and shell */
-
-       if (!fillup_pw_field(lp_template_homedir(), user_name, dom_name,
-                            state->pw->pw_uid, state->pw->pw_gid,
-                            state->info->homedir, state->pw->pw_dir)) {
+       ok = fillup_pw_field(lp_template_homedir(),
+                            user_name,
+                            grp_name,
+                            dom_name,
+                            state->pw->pw_uid,
+                            state->pw->pw_gid,
+                            state->info->homedir,
+                            state->pw->pw_dir);
+       if (!ok) {
+               talloc_free(tmp_ctx);
                tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
                return;
        }
 
-       if (!fillup_pw_field(lp_template_shell(), user_name, dom_name,
-                            state->pw->pw_uid, state->pw->pw_gid,
-                            state->info->shell, state->pw->pw_shell)) {
+       ok = fillup_pw_field(lp_template_shell(),
+                            user_name,
+                            grp_name,
+                            dom_name,
+                            state->pw->pw_uid,
+                            state->pw->pw_gid,
+                            state->info->shell,
+                            state->pw->pw_shell);
+       talloc_free(tmp_ctx);
+       if (!ok) {
                tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
                return;
        }
@@ -166,38 +210,38 @@ NTSTATUS wb_fill_pwent_recv(struct tevent_req *req)
 
 static bool fillup_pw_field(const char *lp_template,
                            const char *username,
+                           const char *grpname,
                            const char *domname,
                            uid_t uid,
                            gid_t gid,
                            const char *in,
                            fstring out)
 {
-       char *templ;
+       const char *templ;
+       char *result;
 
        if (out == NULL)
                return False;
 
-       /* The substitution of %U and %D in the 'template
-          homedir' is done by talloc_sub_specified() below.
-          If we have an in string (which means the value has already
-          been set in the nss_info backend), then use that.
-          Otherwise use the template value passed in. */
+       templ = lp_template;
 
        if ((in != NULL) && (in[0] != '\0') && (lp_security() == SEC_ADS)) {
-               templ = talloc_sub_specified(talloc_tos(), in,
-                                            username, domname,
-                                            uid, gid);
-       } else {
-               templ = talloc_sub_specified(talloc_tos(), lp_template,
-                                            username, domname,
-                                            uid, gid);
+               /*
+                * The backend has already filled in the required value. Use
+                * that instead of the template.
+                */
+               templ = in;
        }
 
-       if (!templ)
+       result = talloc_sub_specified(talloc_tos(), templ,
+                                     username, grpname, domname,
+                                     uid, gid);
+       if (result == NULL) {
                return False;
+       }
 
-       strlcpy(out, templ, sizeof(fstring));
-       TALLOC_FREE(templ);
+       fstrcpy(out, result);
+       TALLOC_FREE(result);
 
        return True;