summaryrefslogtreecommitdiff
path: root/source3/winbindd
diff options
context:
space:
mode:
authorAlexander Bokovoy <ab@samba.org>2009-08-08 08:07:24 +0300
committerAlexander Bokovoy <ab@samba.org>2009-08-08 08:07:24 +0300
commit8eac1896299d820fec0fd92b2b8b6a058ae39642 (patch)
treef97b0a2c21eb4f91aa51cb2af4381287c3525727 /source3/winbindd
parent217e3086c74eb0b46fab512b5887d9a5a5b7ee9a (diff)
parentd296c774c5981baa863c697782dba1b6280d632e (diff)
downloadsamba-8eac1896299d820fec0fd92b2b8b6a058ae39642.tar.gz
samba-8eac1896299d820fec0fd92b2b8b6a058ae39642.tar.bz2
samba-8eac1896299d820fec0fd92b2b8b6a058ae39642.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba
Diffstat (limited to 'source3/winbindd')
-rw-r--r--source3/winbindd/wb_getpwsid.c223
-rw-r--r--source3/winbindd/wb_gettoken.c218
-rw-r--r--source3/winbindd/wb_gid2sid.c119
-rw-r--r--source3/winbindd/wb_lookupname.c104
-rw-r--r--source3/winbindd/wb_lookupsid.c132
-rw-r--r--source3/winbindd/wb_lookupuseraliases.c101
-rw-r--r--source3/winbindd/wb_lookupusergroups.c99
-rw-r--r--source3/winbindd/wb_queryuser.c121
-rw-r--r--source3/winbindd/wb_sid2gid.c170
-rw-r--r--source3/winbindd/wb_sid2uid.c168
-rw-r--r--source3/winbindd/wb_uid2sid.c119
-rw-r--r--source3/winbindd/winbindd.c40
-rw-r--r--source3/winbindd/winbindd.h1
-rw-r--r--source3/winbindd/winbindd_async.c15
-rw-r--r--source3/winbindd/winbindd_cache.c412
-rw-r--r--source3/winbindd/winbindd_domain.c4
-rw-r--r--source3/winbindd/winbindd_dual.c13
-rw-r--r--source3/winbindd/winbindd_dual_ndr.c273
-rw-r--r--source3/winbindd/winbindd_dual_srv.c174
-rw-r--r--source3/winbindd/winbindd_getgroups.c222
-rw-r--r--source3/winbindd/winbindd_getpwnam.c142
-rw-r--r--source3/winbindd/winbindd_getpwsid.c92
-rw-r--r--source3/winbindd/winbindd_getpwuid.c108
-rw-r--r--source3/winbindd/winbindd_getsidaliases.c137
-rw-r--r--source3/winbindd/winbindd_getuserdomgroups.c121
-rw-r--r--source3/winbindd/winbindd_gid_to_sid.c87
-rw-r--r--source3/winbindd/winbindd_group.c224
-rw-r--r--source3/winbindd/winbindd_idmap.c4
-rw-r--r--source3/winbindd/winbindd_locator.c4
-rw-r--r--source3/winbindd/winbindd_lookupname.c110
-rw-r--r--source3/winbindd/winbindd_lookupsid.c101
-rw-r--r--source3/winbindd/winbindd_misc.c6
-rw-r--r--source3/winbindd/winbindd_proto.h177
-rw-r--r--source3/winbindd/winbindd_sid.c440
-rw-r--r--source3/winbindd/winbindd_sid_to_gid.c94
-rw-r--r--source3/winbindd/winbindd_sid_to_uid.c94
-rw-r--r--source3/winbindd/winbindd_uid_to_sid.c87
-rw-r--r--source3/winbindd/winbindd_user.c382
38 files changed, 3898 insertions, 1240 deletions
diff --git a/source3/winbindd/wb_getpwsid.c b/source3/winbindd/wb_getpwsid.c
new file mode 100644
index 0000000000..fc696cb9a1
--- /dev/null
+++ b/source3/winbindd/wb_getpwsid.c
@@ -0,0 +1,223 @@
+/*
+ Unix SMB/CIFS implementation.
+ async getpwsid
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_getpwsid_state {
+ struct winbindd_domain *user_domain;
+ struct tevent_context *ev;
+ struct dom_sid sid;
+ struct winbind_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,
+ const struct dom_sid *user_sid,
+ struct winbindd_pw *pw)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_getpwsid_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_getpwsid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ sid_copy(&state->sid, user_sid);
+ 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);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_queryuser_send(state, ev, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_getpwsid_queryuser_done, req);
+ return req;
+}
+
+static void wb_getpwsid_queryuser_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_queryuser_recv(subreq, state, &state->userinfo);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ 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);
+ return;
+ }
+
+ /*
+ * QueryUser didn't get us a name, do it via LSA.
+ */
+ 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)) {
+ 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;
+
+ status = wb_sid2gid_recv(subreq, &state->pw->pw_gid);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ username = talloc_strdup_lower(state, state->userinfo->acct_name);
+ if (tevent_req_nomem(username, req)) {
+ return;
+ }
+
+ 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);
+ return;
+ }
+
+ 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;
+ }
+
+ 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;
+}
diff --git a/source3/winbindd/wb_gettoken.c b/source3/winbindd/wb_gettoken.c
new file mode 100644
index 0000000000..26189e5a97
--- /dev/null
+++ b/source3/winbindd/wb_gettoken.c
@@ -0,0 +1,218 @@
+/*
+ Unix SMB/CIFS implementation.
+ async gettoken
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_gettoken_state {
+ struct tevent_context *ev;
+ struct dom_sid usersid;
+ int num_sids;
+ struct dom_sid *sids;
+};
+
+static bool wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
+ int *pnum_sids, struct dom_sid **psids,
+ const struct dom_sid *domain_sid,
+ int num_rids, uint32_t *rids);
+
+static void wb_gettoken_gotgroups(struct tevent_req *subreq);
+static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq);
+static void wb_gettoken_gotbuiltins(struct tevent_req *subreq);
+
+struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *sid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_gettoken_state *state;
+ struct winbindd_domain *domain;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_gettoken_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ sid_copy(&state->usersid, sid);
+ state->ev = ev;
+
+ domain = find_domain_from_sid_noinit(sid);
+ if (domain == NULL) {
+ DEBUG(5, ("Could not find domain from SID %s\n",
+ sid_string_dbg(sid)));
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_lookupusergroups_send(state, ev, domain, &state->usersid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_gettoken_gotgroups, req);
+ return req;
+}
+
+static void wb_gettoken_gotgroups(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_gettoken_state *state = tevent_req_data(
+ req, struct wb_gettoken_state);
+ struct dom_sid *sids;
+ struct winbindd_domain *domain;
+ NTSTATUS status;
+
+ status = wb_lookupusergroups_recv(subreq, state, &state->num_sids,
+ &state->sids);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ sids = talloc_realloc(state, state->sids, struct dom_sid,
+ state->num_sids + 1);
+ if (tevent_req_nomem(sids, req)) {
+ return;
+ }
+ memmove(&sids[1], &sids[0], state->num_sids * sizeof(sids[0]));
+ sid_copy(&sids[0], &state->usersid);
+ state->num_sids += 1;
+ state->sids = sids;
+
+ /*
+ * Expand our domain's aliases
+ */
+ domain = find_our_domain();
+ if (domain == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+
+ subreq = wb_lookupuseraliases_send(state, state->ev, domain,
+ state->num_sids, state->sids);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_gettoken_gotlocalgroups, req);
+}
+
+static void wb_gettoken_gotlocalgroups(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_gettoken_state *state = tevent_req_data(
+ req, struct wb_gettoken_state);
+ uint32_t num_rids;
+ uint32_t *rids;
+ struct winbindd_domain *domain;
+ NTSTATUS status;
+
+ status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ domain = find_our_domain();
+ if (!wb_add_rids_to_sids(state, &state->num_sids, &state->sids,
+ &domain->sid, num_rids, rids)) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ TALLOC_FREE(rids);
+
+ /*
+ * Now expand the builtin groups
+ */
+
+ domain = find_builtin_domain();
+ if (domain == NULL) {
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+
+ subreq = wb_lookupuseraliases_send(state, state->ev, domain,
+ state->num_sids, state->sids);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_gettoken_gotbuiltins, req);
+}
+
+static void wb_gettoken_gotbuiltins(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_gettoken_state *state = tevent_req_data(
+ req, struct wb_gettoken_state);
+ uint32_t num_rids;
+ uint32_t *rids;
+ NTSTATUS status;
+
+ status = wb_lookupuseraliases_recv(subreq, state, &num_rids, &rids);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!wb_add_rids_to_sids(state, &state->num_sids, &state->sids,
+ &global_sid_Builtin, num_rids, rids)) {
+ tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_gettoken_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ int *num_sids, struct dom_sid **sids)
+{
+ struct wb_gettoken_state *state = tevent_req_data(
+ req, struct wb_gettoken_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *num_sids = state->num_sids;
+ *sids = talloc_move(mem_ctx, &state->sids);
+ return NT_STATUS_OK;
+}
+
+static bool wb_add_rids_to_sids(TALLOC_CTX *mem_ctx,
+ int *pnum_sids, struct dom_sid **psids,
+ const struct dom_sid *domain_sid,
+ int num_rids, uint32_t *rids)
+{
+ struct dom_sid *sids;
+ int i;
+
+ sids = talloc_realloc(mem_ctx, *psids, struct dom_sid,
+ *pnum_sids + num_rids);
+ if (sids == NULL) {
+ return false;
+ }
+ for (i=0; i<num_rids; i++) {
+ sid_compose(&sids[i+*pnum_sids], domain_sid, rids[i]);
+ }
+
+ *pnum_sids += num_rids;
+ *psids = sids;
+ return true;
+}
diff --git a/source3/winbindd/wb_gid2sid.c b/source3/winbindd/wb_gid2sid.c
new file mode 100644
index 0000000000..a0ae850ef8
--- /dev/null
+++ b/source3/winbindd/wb_gid2sid.c
@@ -0,0 +1,119 @@
+/*
+ Unix SMB/CIFS implementation.
+ async gid2sid
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_gid2sid_state {
+ struct tevent_context *ev;
+ char *dom_name;
+ struct dom_sid sid;
+};
+
+static void wb_gid2sid_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_gid2sid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ gid_t gid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_gid2sid_state *state;
+ struct winbindd_domain *domain;
+ struct winbindd_child *child;
+ bool expired;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_gid2sid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ if (winbindd_use_idmap_cache()
+ && idmap_cache_find_gid2sid(gid, &state->sid, &expired)) {
+
+ DEBUG(10, ("idmap_cache_find_gid2sid found %d%s\n",
+ (int)gid, expired ? " (expired)": ""));
+
+ if (!expired || idmap_is_offline()) {
+ if (is_null_sid(&state->sid)) {
+ tevent_req_nterror(req,
+ NT_STATUS_NONE_MAPPED);
+ } else {
+ tevent_req_done(req);
+ }
+ return tevent_req_post(req, ev);
+ }
+ }
+
+ state->dom_name = NULL;
+
+ for (domain = domain_list(); domain != NULL; domain = domain->next) {
+ if (domain->have_idmap_config
+ && (gid >= domain->id_range_low)
+ && (gid <= domain->id_range_high)) {
+ state->dom_name = domain->name;
+ break;
+ }
+ }
+
+ child = idmap_child();
+
+ subreq = rpccli_wbint_Gid2Sid_send(
+ state, ev, child->rpccli, state->dom_name,
+ gid, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_gid2sid_done, req);
+ return req;
+}
+
+static void wb_gid2sid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_gid2sid_state *state = tevent_req_data(
+ req, struct wb_gid2sid_state);
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_Gid2Sid_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_gid2sid_recv(struct tevent_req *req, struct dom_sid *sid)
+{
+ struct wb_gid2sid_state *state = tevent_req_data(
+ req, struct wb_gid2sid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ sid_copy(sid, &state->sid);
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/wb_lookupname.c b/source3/winbindd/wb_lookupname.c
new file mode 100644
index 0000000000..d4e9b9ae6c
--- /dev/null
+++ b/source3/winbindd/wb_lookupname.c
@@ -0,0 +1,104 @@
+/*
+ Unix SMB/CIFS implementation.
+ async lookupname
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_lookupname_state {
+ struct dom_sid sid;
+ enum lsa_SidType type;
+};
+
+static void wb_lookupname_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_lookupname_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *dom_name, const char *name,
+ uint32_t flags)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_lookupname_state *state;
+ struct winbindd_domain *domain;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_lookupname_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ domain = find_lookup_domain_from_name(dom_name);
+ if (domain == NULL) {
+ DEBUG(5, ("Could not find domain for %s\n", dom_name));
+ tevent_req_nterror(req, NT_STATUS_NONE_MAPPED);
+ return tevent_req_post(req, ev);
+ }
+
+ status = wcache_name_to_sid(domain, dom_name, name,
+ &state->sid, &state->type);
+ if (NT_STATUS_IS_OK(status)) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = rpccli_wbint_LookupName_send(
+ state, ev, domain->child.rpccli, dom_name, name, flags,
+ &state->type, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_lookupname_done, req);
+ return req;
+}
+
+static void wb_lookupname_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_lookupname_state *state = tevent_req_data(
+ req, struct wb_lookupname_state);
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_LookupName_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_lookupname_recv(struct tevent_req *req, struct dom_sid *sid,
+ enum lsa_SidType *type)
+{
+ struct wb_lookupname_state *state = tevent_req_data(
+ req, struct wb_lookupname_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ sid_copy(sid, &state->sid);
+ *type = state->type;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/wb_lookupsid.c b/source3/winbindd/wb_lookupsid.c
new file mode 100644
index 0000000000..f258828048
--- /dev/null
+++ b/source3/winbindd/wb_lookupsid.c
@@ -0,0 +1,132 @@
+/*
+ Unix SMB/CIFS implementation.
+ async lookupsid
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_lookupsid_state {
+ struct tevent_context *ev;
+ struct winbindd_domain *lookup_domain;
+ struct dom_sid sid;
+ enum lsa_SidType type;
+ const char *domname;
+ const char *name;
+};
+
+static void wb_lookupsid_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_lookupsid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *sid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_lookupsid_state *state;
+ char *dom_name, *name;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_lookupsid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ sid_copy(&state->sid, sid);
+ state->ev = ev;
+
+ state->lookup_domain = find_lookup_domain_from_sid(sid);
+ if (state->lookup_domain == NULL) {
+ DEBUG(5, ("Could not find domain for sid %s\n",
+ sid_string_dbg(sid)));
+ tevent_req_nterror(req, NT_STATUS_NONE_MAPPED);
+ return tevent_req_post(req, ev);
+ }
+
+ status = wcache_sid_to_name(state->lookup_domain, sid, state,
+ &dom_name, &name, &state->type);
+ if (NT_STATUS_IS_OK(status)) {
+ state->domname = dom_name;
+ state->name = name;
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = rpccli_wbint_LookupSid_send(
+ state, ev, state->lookup_domain->child.rpccli,
+ &state->sid, &state->type, &state->domname, &state->name);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_lookupsid_done, req);
+ return req;
+}
+
+static void wb_lookupsid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_lookupsid_state *state = tevent_req_data(
+ req, struct wb_lookupsid_state);
+ struct winbindd_domain *forest_root;
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_LookupSid_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (NT_STATUS_IS_OK(result)) {
+ tevent_req_done(req);
+ return;
+ }
+
+ /*
+ * Let's try the forest root
+ */
+ forest_root = find_root_domain();
+ if ((forest_root == NULL) || (forest_root == state->lookup_domain)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+ state->lookup_domain = forest_root;
+
+ subreq = rpccli_wbint_LookupSid_send(
+ state, state->ev, state->lookup_domain->child.rpccli,
+ &state->sid, &state->type, &state->domname, &state->name);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_lookupsid_done, req);
+}
+
+NTSTATUS wb_lookupsid_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ enum lsa_SidType *type, const char **domain,
+ const char **name)
+{
+ struct wb_lookupsid_state *state = tevent_req_data(
+ req, struct wb_lookupsid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *type = state->type;
+ *domain = talloc_move(mem_ctx, &state->domname);
+ *name = talloc_move(mem_ctx, &state->name);
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/wb_lookupuseraliases.c b/source3/winbindd/wb_lookupuseraliases.c
new file mode 100644
index 0000000000..e2e5e2da08
--- /dev/null
+++ b/source3/winbindd/wb_lookupuseraliases.c
@@ -0,0 +1,101 @@
+/*
+ Unix SMB/CIFS implementation.
+ async lookupuseraliases
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_lookupuseraliases_state {
+ struct tevent_context *ev;
+ struct wbint_SidArray sids;
+ struct wbint_RidArray rids;
+};
+
+static void wb_lookupuseraliases_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_lookupuseraliases_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_domain *domain,
+ int num_sids,
+ const struct dom_sid *sids)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_lookupuseraliases_state *state;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct wb_lookupuseraliases_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->sids.num_sids = num_sids;
+ state->sids.sids = CONST_DISCARD(struct dom_sid *, sids);
+
+ status = wcache_lookup_useraliases(domain, state, num_sids, sids,
+ &state->rids.num_rids,
+ &state->rids.rids);
+ if (NT_STATUS_IS_OK(status)) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = rpccli_wbint_LookupUserAliases_send(
+ state, ev, domain->child.rpccli, &state->sids, &state->rids);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_lookupuseraliases_done, req);
+ return req;
+}
+
+static void wb_lookupuseraliases_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_lookupuseraliases_state *state = tevent_req_data(
+ req, struct wb_lookupuseraliases_state);
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_LookupUserAliases_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_lookupuseraliases_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint32_t *num_aliases, uint32_t **aliases)
+{
+ struct wb_lookupuseraliases_state *state = tevent_req_data(
+ req, struct wb_lookupuseraliases_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *num_aliases = state->rids.num_rids;
+ *aliases = talloc_move(mem_ctx, &state->rids.rids);
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/wb_lookupusergroups.c b/source3/winbindd/wb_lookupusergroups.c
new file mode 100644
index 0000000000..4e96b45c57
--- /dev/null
+++ b/source3/winbindd/wb_lookupusergroups.c
@@ -0,0 +1,99 @@
+/*
+ Unix SMB/CIFS implementation.
+ async lookupusergroups
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_lookupusergroups_state {
+ struct tevent_context *ev;
+ struct dom_sid sid;
+ struct wbint_SidArray sids;
+};
+
+static void wb_lookupusergroups_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_domain *domain,
+ const struct dom_sid *sid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_lookupusergroups_state *state;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct wb_lookupusergroups_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ sid_copy(&state->sid, sid);
+
+ status = wcache_lookup_usergroups(domain, state, sid,
+ &state->sids.num_sids,
+ &state->sids.sids);
+ if (NT_STATUS_IS_OK(status)) {
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = rpccli_wbint_LookupUserGroups_send(
+ state, ev, domain->child.rpccli, &state->sid, &state->sids);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_lookupusergroups_done, req);
+ return req;
+}
+
+static void wb_lookupusergroups_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_lookupusergroups_state *state = tevent_req_data(
+ req, struct wb_lookupusergroups_state);
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_LookupUserGroups_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_lookupusergroups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ int *num_sids, struct dom_sid **sids)
+{
+ struct wb_lookupusergroups_state *state = tevent_req_data(
+ req, struct wb_lookupusergroups_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *num_sids = state->sids.num_sids;
+ *sids = talloc_move(mem_ctx, &state->sids.sids);
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/wb_queryuser.c b/source3/winbindd/wb_queryuser.c
new file mode 100644
index 0000000000..27b8d29951
--- /dev/null
+++ b/source3/winbindd/wb_queryuser.c
@@ -0,0 +1,121 @@
+/*
+ Unix SMB/CIFS implementation.
+ async queryuser
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_queryuser_state {
+ struct dom_sid sid;
+ struct wbint_userinfo info;
+};
+
+static void wb_queryuser_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *user_sid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_queryuser_state *state;
+ struct winbindd_domain *domain;
+ struct winbind_userinfo info;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_queryuser_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ sid_copy(&state->sid, user_sid);
+
+ domain = find_domain_from_sid_noinit(user_sid);
+ if (domain == NULL) {
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
+ return tevent_req_post(req, ev);
+ }
+
+ status = wcache_query_user(domain, state, &state->sid, &info);
+ if (NT_STATUS_IS_OK(status)) {
+ state->info.acct_name = info.acct_name;
+ state->info.full_name = info.full_name;
+ state->info.homedir = info.homedir;
+ state->info.shell = info.shell;
+ state->info.primary_gid = info.primary_gid;
+ sid_copy(&state->info.user_sid, &info.user_sid);
+ sid_copy(&state->info.group_sid, &info.group_sid);
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = rpccli_wbint_QueryUser_send(state, ev, domain->child.rpccli,
+ &state->sid, &state->info);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_queryuser_done, req);
+ return req;
+}
+
+static void wb_queryuser_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_queryuser_state *state = tevent_req_data(
+ req, struct wb_queryuser_state);
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_QueryUser_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_queryuser_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbind_userinfo **pinfo)
+{
+ struct wb_queryuser_state *state = tevent_req_data(
+ req, struct wb_queryuser_state);
+ struct winbind_userinfo *info;
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ info = talloc(mem_ctx, struct winbind_userinfo);
+ if (info == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ info->acct_name = talloc_move(info, &state->info.acct_name);
+ info->full_name = talloc_move(info, &state->info.full_name);
+ info->homedir = talloc_move(info, &state->info.homedir);
+ info->shell = talloc_move(info, &state->info.shell);
+ info->primary_gid = state->info.primary_gid;
+ sid_copy(&info->user_sid, &state->info.user_sid);
+ sid_copy(&info->group_sid, &state->info.group_sid);
+ *pinfo = info;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/wb_sid2gid.c b/source3/winbindd/wb_sid2gid.c
new file mode 100644
index 0000000000..a578746ea2
--- /dev/null
+++ b/source3/winbindd/wb_sid2gid.c
@@ -0,0 +1,170 @@
+/*
+ Unix SMB/CIFS implementation.
+ async sid2gid
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_sid2gid_state {
+ struct tevent_context *ev;
+ struct dom_sid sid;
+ char *dom_name;
+ uint64 gid64;
+ gid_t gid;
+};
+
+static void wb_sid2gid_lookup_done(struct tevent_req *subreq);
+static void wb_sid2gid_done(struct tevent_req *subreq);
+
+
+struct tevent_req *wb_sid2gid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *sid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_sid2gid_state *state;
+ bool expired;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_sid2gid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ sid_copy(&state->sid, sid);
+ state->ev = ev;
+
+ if (winbindd_use_idmap_cache()
+ && idmap_cache_find_sid2gid(sid, &state->gid, &expired)) {
+
+ DEBUG(10, ("idmap_cache_find_sid2gid found %d%s\n",
+ (int)state->gid, expired ? " (expired)": ""));
+
+ if (!expired || IS_DOMAIN_OFFLINE(find_our_domain())) {
+ if (state->gid == -1) {
+ tevent_req_nterror(req, NT_STATUS_NONE_MAPPED);
+ } else {
+ tevent_req_done(req);
+ }
+ return tevent_req_post(req, ev);
+ }
+ }
+
+ /*
+ * We need to make sure the sid is of the right type to not flood
+ * idmap with wrong entries
+ */
+
+ subreq = wb_lookupsid_send(state, ev, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_sid2gid_lookup_done, req);
+ return req;
+}
+
+static void wb_sid2gid_lookup_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_sid2gid_state *state = tevent_req_data(
+ req, struct wb_sid2gid_state);
+ struct winbindd_domain *domain;
+ const char *domname;
+ const char *name;
+ enum lsa_SidType type;
+ NTSTATUS status;
+ struct winbindd_child *child;
+
+ status = wb_lookupsid_recv(subreq, talloc_tos(), &type, &domname,
+ &name);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS)
+ && (type != SID_NAME_WKN_GRP)) {
+ DEBUG(5, ("Sid %s is not a group.\n",
+ sid_string_dbg(&state->sid)));
+ /*
+ * We have to set the cache ourselves here, the child
+ * which is normally responsible was not queried yet.
+ */
+ idmap_cache_set_sid2gid(&state->sid, -1);
+ tevent_req_nterror(req, NT_STATUS_INVALID_SID);
+ return;
+ }
+
+ domain = find_domain_from_sid_noinit(&state->sid);
+
+ /*
+ * TODO: Issue a gettrustinfo here in case we don't have "domain" yet?
+ */
+
+ if ((domain != NULL) && domain->have_idmap_config) {
+ state->dom_name = domain->name;
+ } else {
+ state->dom_name = NULL;
+ }
+
+ child = idmap_child();
+
+ subreq = rpccli_wbint_Sid2Gid_send(state, state->ev, child->rpccli,
+ state->dom_name, &state->sid,
+ &state->gid64);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_sid2gid_done, req);
+}
+
+static void wb_sid2gid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_sid2gid_state *state = tevent_req_data(
+ req, struct wb_sid2gid_state);
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_Sid2Gid_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+
+ state->gid = state->gid64;
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_sid2gid_recv(struct tevent_req *req, gid_t *gid)
+{
+ struct wb_sid2gid_state *state = tevent_req_data(
+ req, struct wb_sid2gid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *gid = state->gid;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/wb_sid2uid.c b/source3/winbindd/wb_sid2uid.c
new file mode 100644
index 0000000000..abfe257bfa
--- /dev/null
+++ b/source3/winbindd/wb_sid2uid.c
@@ -0,0 +1,168 @@
+/*
+ Unix SMB/CIFS implementation.
+ async sid2uid
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_sid2uid_state {
+ struct tevent_context *ev;
+ struct dom_sid sid;
+ char *dom_name;
+ uint64 uid64;
+ uid_t uid;
+};
+
+static void wb_sid2uid_lookup_done(struct tevent_req *subreq);
+static void wb_sid2uid_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_sid2uid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *sid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_sid2uid_state *state;
+ bool expired;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_sid2uid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ sid_copy(&state->sid, sid);
+ state->ev = ev;
+
+ if (winbindd_use_idmap_cache()
+ && idmap_cache_find_sid2uid(sid, &state->uid, &expired)) {
+
+ DEBUG(10, ("idmap_cache_find_sid2uid found %d%s\n",
+ (int)state->uid, expired ? " (expired)": ""));
+
+ if (!expired || IS_DOMAIN_OFFLINE(find_our_domain())) {
+ if (state->uid == -1) {
+ tevent_req_nterror(req, NT_STATUS_NONE_MAPPED);
+ } else {
+ tevent_req_done(req);
+ }
+ return tevent_req_post(req, ev);
+ }
+ }
+
+ /*
+ * We need to make sure the sid is of the right type to not flood
+ * idmap with wrong entries
+ */
+
+ subreq = wb_lookupsid_send(state, ev, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_sid2uid_lookup_done, req);
+ return req;
+}
+
+static void wb_sid2uid_lookup_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_sid2uid_state *state = tevent_req_data(
+ req, struct wb_sid2uid_state);
+ struct winbindd_domain *domain;
+ const char *domname;
+ const char *name;
+ enum lsa_SidType type;
+ NTSTATUS status;
+ struct winbindd_child *child;
+
+ status = wb_lookupsid_recv(subreq, talloc_tos(), &type, &domname,
+ &name);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
+ DEBUG(5, ("Sid %s is not a user or a computer.\n",
+ sid_string_dbg(&state->sid)));
+ /*
+ * We have to set the cache ourselves here, the child
+ * which is normally responsible was not queried yet.
+ */
+ idmap_cache_set_sid2uid(&state->sid, -1);
+ tevent_req_nterror(req, NT_STATUS_INVALID_SID);
+ return;
+ }
+
+ domain = find_domain_from_sid_noinit(&state->sid);
+
+ /*
+ * TODO: Issue a gettrustinfo here in case we don't have "domain" yet?
+ */
+
+ if ((domain != NULL) && domain->have_idmap_config) {
+ state->dom_name = domain->name;
+ } else {
+ state->dom_name = NULL;
+ }
+
+ child = idmap_child();
+
+ subreq = rpccli_wbint_Sid2Uid_send(state, state->ev, child->rpccli,
+ state->dom_name, &state->sid,
+ &state->uid64);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, wb_sid2uid_done, req);
+}
+
+static void wb_sid2uid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_sid2uid_state *state = tevent_req_data(
+ req, struct wb_sid2uid_state);
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_Sid2Uid_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+
+ state->uid = state->uid64;
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_sid2uid_recv(struct tevent_req *req, uid_t *uid)
+{
+ struct wb_sid2uid_state *state = tevent_req_data(
+ req, struct wb_sid2uid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ *uid = state->uid;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/wb_uid2sid.c b/source3/winbindd/wb_uid2sid.c
new file mode 100644
index 0000000000..18ef3b214a
--- /dev/null
+++ b/source3/winbindd/wb_uid2sid.c
@@ -0,0 +1,119 @@
+/*
+ Unix SMB/CIFS implementation.
+ async uid2sid
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+#include "librpc/gen_ndr/cli_wbint.h"
+
+struct wb_uid2sid_state {
+ struct tevent_context *ev;
+ char *dom_name;
+ struct dom_sid sid;
+};
+
+static void wb_uid2sid_done(struct tevent_req *subreq);
+
+struct tevent_req *wb_uid2sid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ uid_t uid)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_uid2sid_state *state;
+ struct winbindd_domain *domain;
+ struct winbindd_child *child;
+ bool expired;
+
+ req = tevent_req_create(mem_ctx, &state, struct wb_uid2sid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ if (winbindd_use_idmap_cache()
+ && idmap_cache_find_uid2sid(uid, &state->sid, &expired)) {
+
+ DEBUG(10, ("idmap_cache_find_uid2sid found %d%s\n",
+ (int)uid, expired ? " (expired)": ""));
+
+ if (!expired || idmap_is_offline()) {
+ if (is_null_sid(&state->sid)) {
+ tevent_req_nterror(req,
+ NT_STATUS_NONE_MAPPED);
+ } else {
+ tevent_req_done(req);
+ }
+ return tevent_req_post(req, ev);
+ }
+ }
+
+ state->dom_name = NULL;
+
+ for (domain = domain_list(); domain != NULL; domain = domain->next) {
+ if (domain->have_idmap_config
+ && (uid >= domain->id_range_low)
+ && (uid <= domain->id_range_high)) {
+ state->dom_name = domain->name;
+ break;
+ }
+ }
+
+ child = idmap_child();
+
+ subreq = rpccli_wbint_Uid2Sid_send(
+ state, ev, child->rpccli, state->dom_name,
+ uid, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_uid2sid_done, req);
+ return req;
+}
+
+static void wb_uid2sid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_uid2sid_state *state = tevent_req_data(
+ req, struct wb_uid2sid_state);
+ NTSTATUS status, result;
+
+ status = rpccli_wbint_Uid2Sid_recv(subreq, state, &result);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ if (!NT_STATUS_IS_OK(result)) {
+ tevent_req_nterror(req, result);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS wb_uid2sid_recv(struct tevent_req *req, struct dom_sid *sid)
+{
+ struct wb_uid2sid_state *state = tevent_req_data(
+ req, struct wb_uid2sid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+ sid_copy(sid, &state->sid);
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c
index 4b6ebd2c42..348816b39c 100644
--- a/source3/winbindd/winbindd.c
+++ b/source3/winbindd/winbindd.c
@@ -427,20 +427,11 @@ static struct winbindd_dispatch_table {
/* User functions */
- { WINBINDD_GETPWNAM, winbindd_getpwnam, "GETPWNAM" },
- { WINBINDD_GETPWUID, winbindd_getpwuid, "GETPWUID" },
- { WINBINDD_GETPWSID, winbindd_getpwsid, "GETPWSID" },
-
{ WINBINDD_SETPWENT, winbindd_setpwent, "SETPWENT" },
{ WINBINDD_ENDPWENT, winbindd_endpwent, "ENDPWENT" },
{ WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" },
- { WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" },
{ WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" },
- { WINBINDD_GETUSERDOMGROUPS, winbindd_getuserdomgroups,
- "GETUSERDOMGROUPS" },
- { WINBINDD_GETSIDALIASES, winbindd_getsidaliases,
- "LOOKUPUSERALIASES" },
/* Group functions */
@@ -469,16 +460,10 @@ static struct winbindd_dispatch_table {
/* SID related functions */
- { WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" },
- { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" },
{ WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" },
/* Lookup related functions */
- { WINBINDD_SID_TO_UID, winbindd_sid_to_uid, "SID_TO_UID" },
- { WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" },
- { WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" },
- { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },
{ WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" },
{ WINBINDD_ALLOCATE_GID, winbindd_allocate_gid, "ALLOCATE_GID" },
{ WINBINDD_SET_MAPPING, winbindd_set_mapping, "SET_MAPPING" },
@@ -488,7 +473,6 @@ static struct winbindd_dispatch_table {
/* Miscellaneous */
{ WINBINDD_CHECK_MACHACC, winbindd_check_machine_acct, "CHECK_MACHACC" },
- { WINBINDD_PING, winbindd_ping, "PING" },
{ WINBINDD_INFO, winbindd_info, "INFO" },
{ WINBINDD_INTERFACE_VERSION, winbindd_interface_version,
"INTERFACE_VERSION" },
@@ -526,6 +510,30 @@ struct winbindd_async_dispatch_table {
static struct winbindd_async_dispatch_table async_nonpriv_table[] = {
{ WINBINDD_PING, "PING",
wb_ping_send, wb_ping_recv },
+ { WINBINDD_LOOKUPSID, "LOOKUPSID",
+ winbindd_lookupsid_send, winbindd_lookupsid_recv },
+ { WINBINDD_LOOKUPNAME, "LOOKUPNAME",
+ winbindd_lookupname_send, winbindd_lookupname_recv },
+ { WINBINDD_SID_TO_UID, "SID_TO_UID",
+ winbindd_sid_to_uid_send, winbindd_sid_to_uid_recv },
+ { WINBINDD_SID_TO_GID, "SID_TO_GID",
+ winbindd_sid_to_gid_send, winbindd_sid_to_gid_recv },
+ { WINBINDD_UID_TO_SID, "UID_TO_SID",
+ winbindd_uid_to_sid_send, winbindd_uid_to_sid_recv },
+ { WINBINDD_GID_TO_SID, "GID_TO_SID",
+ winbindd_gid_to_sid_send, winbindd_gid_to_sid_recv },
+ { WINBINDD_GETPWSID, "GETPWSID",
+ winbindd_getpwsid_send, winbindd_getpwsid_recv },
+ { WINBINDD_GETPWNAM, "GETPWNAM",
+ winbindd_getpwnam_send, winbindd_getpwnam_recv },
+ { WINBINDD_GETPWUID, "GETPWUID",
+ winbindd_getpwuid_send, winbindd_getpwuid_recv },
+ { WINBINDD_GETSIDALIASES, "GETSIDALIASES",
+ winbindd_getsidaliases_send, winbindd_getsidaliases_recv },
+ { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS",
+ winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv },
+ { WINBINDD_GETGROUPS, "GETGROUPS",
+ winbindd_getgroups_send, winbindd_getgroups_recv },
{ 0, NULL, NULL, NULL }
};
diff --git a/source3/winbindd/winbindd.h b/source3/winbindd/winbindd.h
index 8f0db44617..baab7fd11a 100644
--- a/source3/winbindd/winbindd.h
+++ b/source3/winbindd/winbindd.h
@@ -138,6 +138,7 @@ struct winbindd_child {
int sock;
struct tevent_queue *queue;
+ struct rpc_pipe_client *rpccli;
struct timed_event *lockout_policy_event;
struct timed_event *machine_password_change_event;
diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c
index f53875f617..094602160d 100644
--- a/source3/winbindd/winbindd_async.c
+++ b/source3/winbindd/winbindd_async.c
@@ -632,25 +632,32 @@ bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
return True;
}
-bool parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
+bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
DOM_SID **sids, size_t *num_sids)
{
- char *p, *q;
+ const char *p, *q;
p = sidstr;
if (p == NULL)
return False;
while (p[0] != '\0') {
+ fstring tmp;
+ size_t sidlen;
DOM_SID sid;
q = strchr(p, '\n');
if (q == NULL) {
DEBUG(0, ("Got invalid sidstr: %s\n", p));
return False;
}
- *q = '\0';
+ sidlen = PTR_DIFF(q, p);
+ if (sidlen >= sizeof(tmp)-1) {
+ return false;
+ }
+ memcpy(tmp, p, sidlen);
+ tmp[sidlen] = '\0';
q += 1;
- if (!string_to_sid(&sid, p)) {
+ if (!string_to_sid(&sid, tmp)) {
DEBUG(0, ("Could not parse sid %s\n", p));
return False;
}
diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c
index bec2a714c8..5dfdc5ae29 100644
--- a/source3/winbindd/winbindd_cache.c
+++ b/source3/winbindd/winbindd_cache.c
@@ -1605,28 +1605,31 @@ skip_save:
return status;
}
-/* convert a single name to a sid in a domain */
-static NTSTATUS name_to_sid(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
+NTSTATUS wcache_name_to_sid(struct winbindd_domain *domain,
const char *domain_name,
const char *name,
- uint32_t flags,
- DOM_SID *sid,
+ struct dom_sid *sid,
enum lsa_SidType *type)
{
struct winbind_cache *cache = get_cache(domain);
- struct cache_entry *centry = NULL;
+ struct cache_entry *centry;
NTSTATUS status;
- fstring uname;
+ char *uname;
- if (!cache->tdb)
- goto do_query;
+ if (cache->tdb == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ uname = talloc_strdup_upper(talloc_tos(), name);
+ if (uname == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- fstrcpy(uname, name);
- strupper_m(uname);
centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
- if (!centry)
- goto do_query;
+ TALLOC_FREE(uname);
+ if (centry == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
status = centry->status;
if (NT_STATUS_IS_OK(status)) {
@@ -1634,13 +1637,29 @@ static NTSTATUS name_to_sid(struct winbindd_domain *domain,
centry_sid(centry, sid);
}
- DEBUG(10,("name_to_sid: [Cached] - cached name for domain %s status: %s\n",
- domain->name, nt_errstr(status) ));
+ DEBUG(10,("name_to_sid: [Cached] - cached name for domain %s status: "
+ "%s\n", domain->name, nt_errstr(status) ));
centry_free(centry);
return status;
+}
+
+/* convert a single name to a sid in a domain */
+static NTSTATUS name_to_sid(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const char *domain_name,
+ const char *name,
+ uint32_t flags,
+ DOM_SID *sid,
+ enum lsa_SidType *type)
+{
+ NTSTATUS status;
+
+ status = wcache_name_to_sid(domain, domain_name, name, sid, type);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ return status;
+ }
-do_query:
ZERO_STRUCTP(sid);
/* If the seq number check indicated that there is a problem
@@ -1678,42 +1697,65 @@ do_query:
return status;
}
-/* convert a sid to a user or group name. The sid is guaranteed to be in the domain
- given */
-static NTSTATUS sid_to_name(struct winbindd_domain *domain,
+NTSTATUS wcache_sid_to_name(struct winbindd_domain *domain,
+ const struct dom_sid *sid,
TALLOC_CTX *mem_ctx,
- const DOM_SID *sid,
char **domain_name,
char **name,
enum lsa_SidType *type)
{
struct winbind_cache *cache = get_cache(domain);
- struct cache_entry *centry = NULL;
+ struct cache_entry *centry;
+ char *sid_string;
NTSTATUS status;
- fstring sid_string;
- if (!cache->tdb)
- goto do_query;
+ if (cache->tdb == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
- centry = wcache_fetch(cache, domain, "SN/%s",
- sid_to_fstring(sid_string, sid));
- if (!centry)
- goto do_query;
+ sid_string = sid_string_tos(sid);
+ if (sid_string == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- status = centry->status;
- if (NT_STATUS_IS_OK(status)) {
+ centry = wcache_fetch(cache, domain, "SN/%s", sid_string);
+ TALLOC_FREE(sid_string);
+ if (centry == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
+
+ if (NT_STATUS_IS_OK(centry->status)) {
*type = (enum lsa_SidType)centry_uint32(centry);
*domain_name = centry_string(centry, mem_ctx);
*name = centry_string(centry, mem_ctx);
}
- DEBUG(10,("sid_to_name: [Cached] - cached name for domain %s status: %s\n",
- domain->name, nt_errstr(status) ));
-
+ status = centry->status;
centry_free(centry);
+
+ DEBUG(10,("sid_to_name: [Cached] - cached name for domain %s status: "
+ "%s\n", domain->name, nt_errstr(status) ));
+
return status;
+}
+
+/* convert a sid to a user or group name. The sid is guaranteed to be in the domain
+ given */
+static NTSTATUS sid_to_name(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *sid,
+ char **domain_name,
+ char **name,
+ enum lsa_SidType *type)
+{
+ NTSTATUS status;
+
+ status = wcache_sid_to_name(domain, sid, mem_ctx, domain_name, name,
+ type);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ return status;
+ }
-do_query:
*name = NULL;
*domain_name = NULL;
@@ -1897,38 +1939,46 @@ static NTSTATUS rids_to_names(struct winbindd_domain *domain,
return result;
}
-/* Lookup user information from a rid */
-static NTSTATUS query_user(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- const DOM_SID *user_sid,
- WINBIND_USERINFO *info)
+NTSTATUS wcache_query_user(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ struct winbind_userinfo *info)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
- fstring tmp;
+ char *sid_string;
- if (!cache->tdb)
- goto do_query;
+ if (cache->tdb == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
- centry = wcache_fetch(cache, domain, "U/%s",
- sid_to_fstring(tmp, user_sid));
+ sid_string = sid_string_tos(user_sid);
+ if (sid_string == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
- /* If we have an access denied cache entry and a cached info3 in the
- samlogon cache then do a query. This will force the rpc back end
- to return the info3 data. */
+ centry = wcache_fetch(cache, domain, "U/%s", sid_string);
+ TALLOC_FREE(sid_string);
+ if (centry == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
- if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) &&
+ /*
+ * If we have an access denied cache entry and a cached info3
+ * in the samlogon cache then do a query. This will force the
+ * rpc back end to return the info3 data.
+ */
+
+ if (NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED) &&
netsamlogon_cache_have(user_sid)) {
- DEBUG(10, ("query_user: cached access denied and have cached info3\n"));
+ DEBUG(10, ("query_user: cached access denied and have cached "
+ "info3\n"));
domain->last_status = NT_STATUS_OK;
centry_free(centry);
- goto do_query;
+ return NT_STATUS_NOT_FOUND;
}
- if (!centry)
- goto do_query;
-
/* if status is not ok then this is a negative hit
and the rest of the data doesn't matter */
status = centry->status;
@@ -1942,13 +1992,26 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
centry_sid(centry, &info->group_sid);
}
- DEBUG(10,("query_user: [Cached] - cached info for domain %s status: %s\n",
- domain->name, nt_errstr(status) ));
+ DEBUG(10,("query_user: [Cached] - cached info for domain %s status: "
+ "%s\n", domain->name, nt_errstr(status) ));
centry_free(centry);
return status;
+}
+
+/* Lookup user information from a rid */
+static NTSTATUS query_user(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *user_sid,
+ WINBIND_USERINFO *info)
+{
+ NTSTATUS status;
+
+ status = wcache_query_user(domain, mem_ctx, user_sid, info);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ return status;
+ }
-do_query:
ZERO_STRUCTP(info);
/* Return status value returned by seq number check */
@@ -1968,63 +2031,81 @@ do_query:
return status;
}
-
-/* Lookup groups a user is a member of. */
-static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
+NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain,
TALLOC_CTX *mem_ctx,
- const DOM_SID *user_sid,
- uint32 *num_groups, DOM_SID **user_gids)
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_sids,
+ struct dom_sid **psids)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
NTSTATUS status;
- unsigned int i;
+ uint32_t i, num_sids;
+ struct dom_sid *sids;
fstring sid_string;
- if (!cache->tdb)
- goto do_query;
+ if (cache->tdb == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
centry = wcache_fetch(cache, domain, "UG/%s",
sid_to_fstring(sid_string, user_sid));
+ if (centry == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
/* If we have an access denied cache entry and a cached info3 in the
samlogon cache then do a query. This will force the rpc back end
to return the info3 data. */
- if (NT_STATUS_V(domain->last_status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) &&
- netsamlogon_cache_have(user_sid)) {
- DEBUG(10, ("lookup_usergroups: cached access denied and have cached info3\n"));
+ if (NT_STATUS_EQUAL(domain->last_status, NT_STATUS_ACCESS_DENIED)
+ && netsamlogon_cache_have(user_sid)) {
+ DEBUG(10, ("lookup_usergroups: cached access denied and have "
+ "cached info3\n"));
domain->last_status = NT_STATUS_OK;
centry_free(centry);
- goto do_query;
+ return NT_STATUS_NOT_FOUND;
}
- if (!centry)
- goto do_query;
-
- *num_groups = centry_uint32(centry);
-
- if (*num_groups == 0)
- goto do_cached;
-
- (*user_gids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_groups);
- if (! (*user_gids)) {
- smb_panic_fn("lookup_usergroups out of memory");
+ num_sids = centry_uint32(centry);
+ sids = talloc_array(mem_ctx, struct dom_sid, num_sids);
+ if (sids == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
- for (i=0; i<(*num_groups); i++) {
- centry_sid(centry, &(*user_gids)[i]);
+
+ for (i=0; i<num_sids; i++) {
+ centry_sid(centry, &sids[i]);
}
-do_cached:
status = centry->status;
- DEBUG(10,("lookup_usergroups: [Cached] - cached info for domain %s status: %s\n",
- domain->name, nt_errstr(status) ));
+ DEBUG(10,("lookup_usergroups: [Cached] - cached info for domain %s "
+ "status: %s\n", domain->name, nt_errstr(status)));
centry_free(centry);
+
+ *pnum_sids = num_sids;
+ *psids = sids;
return status;
+}
+
+/* Lookup groups a user is a member of. */
+static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const DOM_SID *user_sid,
+ uint32 *num_groups, DOM_SID **user_gids)
+{
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ unsigned int i;
+ fstring sid_string;
+
+ status = wcache_lookup_usergroups(domain, mem_ctx, user_sid,
+ num_groups, user_gids);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ return status;
+ }
-do_query:
(*num_groups) = 0;
(*user_gids) = NULL;
@@ -2059,58 +2140,74 @@ skip_save:
return status;
}
-static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
- TALLOC_CTX *mem_ctx,
- uint32 num_sids, const DOM_SID *sids,
- uint32 *num_aliases, uint32 **alias_rids)
+static char *wcache_make_sidlist(TALLOC_CTX *mem_ctx, uint32_t num_sids,
+ const struct dom_sid *sids)
+{
+ uint32_t i;
+ char *sidlist;
+
+ sidlist = talloc_strdup(mem_ctx, "");
+ if (sidlist == NULL) {
+ return NULL;
+ }
+ for (i=0; i<num_sids; i++) {
+ fstring tmp;
+ sidlist = talloc_asprintf_append_buffer(
+ sidlist, "/%s", sid_to_fstring(tmp, &sids[i]));
+ if (sidlist == NULL) {
+ return NULL;
+ }
+ }
+ return sidlist;
+}
+
+NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx, uint32_t num_sids,
+ const struct dom_sid *sids,
+ uint32_t *pnum_aliases, uint32_t **paliases)
{
struct winbind_cache *cache = get_cache(domain);
struct cache_entry *centry = NULL;
+ uint32_t num_aliases;
+ uint32_t *aliases;
NTSTATUS status;
- char *sidlist = talloc_strdup(mem_ctx, "");
+ char *sidlist;
int i;
- if (!cache->tdb)
- goto do_query;
+ if (cache->tdb == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
if (num_sids == 0) {
- *num_aliases = 0;
- *alias_rids = NULL;
+ *pnum_aliases = 0;
+ *paliases = NULL;
return NT_STATUS_OK;
}
/* We need to cache indexed by the whole list of SIDs, the aliases
* resulting might come from any of the SIDs. */
- for (i=0; i<num_sids; i++) {
- fstring tmp;
- sidlist = talloc_asprintf(mem_ctx, "%s/%s", sidlist,
- sid_to_fstring(tmp, &sids[i]));
- if (sidlist == NULL)
- return NT_STATUS_NO_MEMORY;
+ sidlist = wcache_make_sidlist(talloc_tos(), num_sids, sids);
+ if (sidlist == NULL) {
+ return NT_STATUS_NO_MEMORY;
}
centry = wcache_fetch(cache, domain, "UA%s", sidlist);
+ TALLOC_FREE(sidlist);
+ if (centry == NULL) {
+ return NT_STATUS_NOT_FOUND;
+ }
- if (!centry)
- goto do_query;
-
- *num_aliases = centry_uint32(centry);
- *alias_rids = NULL;
-
- if (*num_aliases) {
- (*alias_rids) = TALLOC_ARRAY(mem_ctx, uint32, *num_aliases);
-
- if ((*alias_rids) == NULL) {
- centry_free(centry);
- return NT_STATUS_NO_MEMORY;
- }
- } else {
- (*alias_rids) = NULL;
+ num_aliases = centry_uint32(centry);
+ aliases = talloc_array(mem_ctx, uint32_t, num_aliases);
+ if (aliases == NULL) {
+ centry_free(centry);
+ return NT_STATUS_NO_MEMORY;
}
- for (i=0; i<(*num_aliases); i++)
- (*alias_rids)[i] = centry_uint32(centry);
+ for (i=0; i<num_aliases; i++) {
+ aliases[i] = centry_uint32(centry);
+ }
status = centry->status;
@@ -2118,9 +2215,29 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
"status %s\n", domain->name, nt_errstr(status)));
centry_free(centry);
+
+ *pnum_aliases = num_aliases;
+ *paliases = aliases;
+
return status;
+}
+
+static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 num_sids, const DOM_SID *sids,
+ uint32 *num_aliases, uint32 **alias_rids)
+{
+ struct cache_entry *centry = NULL;
+ NTSTATUS status;
+ char *sidlist;
+ int i;
+
+ status = wcache_lookup_useraliases(domain, mem_ctx, num_sids, sids,
+ num_aliases, alias_rids);
+ if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
+ return status;
+ }
- do_query:
(*num_aliases) = 0;
(*alias_rids) = NULL;
@@ -2130,6 +2247,11 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
DEBUG(10,("lookup_usergroups: [Cached] - doing backend query for info "
"for domain %s\n", domain->name ));
+ sidlist = wcache_make_sidlist(talloc_tos(), num_sids, sids);
+ if (sidlist == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
status = domain->backend->lookup_useraliases(domain, mem_ctx,
num_sids, sids,
num_aliases, alias_rids);
@@ -2625,36 +2747,14 @@ bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
enum lsa_SidType *type)
{
struct winbindd_domain *domain;
- struct winbind_cache *cache;
- struct cache_entry *centry = NULL;
NTSTATUS status;
- fstring tmp;
domain = find_lookup_domain_from_sid(sid);
if (domain == NULL) {
return false;
}
-
- cache = get_cache(domain);
-
- if (cache->tdb == NULL) {
- return false;
- }
-
- centry = wcache_fetch(cache, domain, "SN/%s",
- sid_to_fstring(tmp, sid));
- if (centry == NULL) {
- return false;
- }
-
- if (NT_STATUS_IS_OK(centry->status)) {
- *type = (enum lsa_SidType)centry_uint32(centry);
- *domain_name = centry_string(centry, mem_ctx);
- *name = centry_string(centry, mem_ctx);
- }
-
- status = centry->status;
- centry_free(centry);
+ status = wcache_sid_to_name(domain, sid, mem_ctx, domain_name, name,
+ type);
return NT_STATUS_IS_OK(status);
}
@@ -2665,46 +2765,22 @@ bool lookup_cached_name(TALLOC_CTX *mem_ctx,
enum lsa_SidType *type)
{
struct winbindd_domain *domain;
- struct winbind_cache *cache;
- struct cache_entry *centry = NULL;
NTSTATUS status;
- fstring uname;
- bool original_online_state;
+ bool original_online_state;
domain = find_lookup_domain_from_name(domain_name);
if (domain == NULL) {
return false;
}
- cache = get_cache(domain);
-
- if (cache->tdb == NULL) {
- return false;
- }
-
- fstrcpy(uname, name);
- strupper_m(uname);
-
/* If we are doing a cached logon, temporarily set the domain
offline so the cache won't expire the entry */
original_online_state = domain->online;
domain->online = false;
- centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
+ status = wcache_name_to_sid(domain, domain_name, name, sid, type);
domain->online = original_online_state;
- if (centry == NULL) {
- return false;
- }
-
- if (NT_STATUS_IS_OK(centry->status)) {
- *type = (enum lsa_SidType)centry_uint32(centry);
- centry_sid(centry, sid);
- }
-
- status = centry->status;
- centry_free(centry);
-
return NT_STATUS_IS_OK(status);
}
diff --git a/source3/winbindd/winbindd_domain.c b/source3/winbindd/winbindd_domain.c
index 8c52df3e16..5ff2e16abb 100644
--- a/source3/winbindd/winbindd_domain.c
+++ b/source3/winbindd/winbindd_domain.c
@@ -122,6 +122,10 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = {
.struct_cmd = WINBINDD_CCACHE_NTLMAUTH,
.struct_fn = winbindd_dual_ccache_ntlm_auth,
},{
+ .name = "NDRCMD",
+ .struct_cmd = WINBINDD_DUAL_NDRCMD,
+ .struct_fn = winbindd_dual_ndrcmd,
+ },{
.name = NULL,
}
};
diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c
index 1985dd8b12..2158834bdd 100644
--- a/source3/winbindd/winbindd_dual.c
+++ b/source3/winbindd/winbindd_dual.c
@@ -592,6 +592,8 @@ void setup_child(struct winbindd_child *child,
child->table = table;
child->queue = tevent_queue_create(NULL, "winbind_child");
SMB_ASSERT(child->queue != NULL);
+ child->rpccli = wbint_rpccli_create(NULL, child);
+ SMB_ASSERT(child->rpccli != NULL);
}
struct winbindd_child *children = NULL;
@@ -1307,6 +1309,16 @@ bool winbindd_reinit_after_fork(const char *logfilename)
return true;
}
+/*
+ * In a child there will be only one domain, reference that here.
+ */
+static struct winbindd_domain *child_domain;
+
+struct winbindd_domain *wb_child_domain(void)
+{
+ return child_domain;
+}
+
static bool fork_domain_child(struct winbindd_child *child)
{
int fdpair[2];
@@ -1321,6 +1333,7 @@ static bool fork_domain_child(struct winbindd_child *child)
} else {
DEBUG(10, ("fork_domain_child called without domain.\n"));
}
+ child_domain = child->domain;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
DEBUG(0, ("Could not open child pipe: %s\n",
diff --git a/source3/winbindd/winbindd_dual_ndr.c b/source3/winbindd/winbindd_dual_ndr.c
new file mode 100644
index 0000000000..f72d6615a0
--- /dev/null
+++ b/source3/winbindd/winbindd_dual_ndr.c
@@ -0,0 +1,273 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Provide parent->child communication based on NDR marshalling
+
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * This file implements an RPC between winbind parent and child processes,
+ * leveraging the autogenerated marshalling routines for MSRPC. This is not
+ * MSRPC, as it does not go through the whole DCERPC fragmentation, we just
+ * leverage much the same infrastructure we already have for it.
+ */
+
+#include "includes.h"
+#include "winbindd/winbindd.h"
+#include "winbindd/winbindd_proto.h"
+#include "librpc/gen_ndr/srv_wbint.h"
+
+struct wb_ndr_transport_priv {
+ struct winbindd_child *child;
+};
+
+struct wb_ndr_dispatch_state {
+ const struct ndr_interface_call *call;
+ void *r;
+ struct ndr_push *push;
+ struct winbindd_request request;
+ struct winbindd_response *response;
+};
+
+static void wb_ndr_dispatch_done(struct tevent_req *subreq);
+
+static struct tevent_req *wb_ndr_dispatch_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct rpc_pipe_client *cli,
+ const struct ndr_interface_table *table,
+ uint32_t opnum,
+ void *r)
+{
+ struct tevent_req *req, *subreq;
+ struct wb_ndr_dispatch_state *state;
+ struct wb_ndr_transport_priv *transport = talloc_get_type_abort(
+ cli->transport->priv, struct wb_ndr_transport_priv);
+ DATA_BLOB blob;
+ enum ndr_err_code ndr_err;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct wb_ndr_dispatch_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ state->r = r;
+ state->call = &table->calls[opnum];
+
+ state->push = ndr_push_init_ctx(state, NULL);
+ if (tevent_req_nomem(state->push, req)) {
+ return tevent_req_post(req, ev);
+ }
+
+ ndr_err = state->call->ndr_push(state->push, NDR_IN, r);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ tevent_req_nterror(req, ndr_map_error2ntstatus(ndr_err));
+ TALLOC_FREE(state->push);
+ return tevent_req_post(req, ev);
+ }
+
+ blob = ndr_push_blob(state->push);
+
+ state->request.cmd = WINBINDD_DUAL_NDRCMD;
+ state->request.data.ndrcmd = opnum;
+ state->request.extra_data.data = (char *)blob.data;
+ state->request.extra_len = blob.length;
+
+ subreq = wb_child_request_send(state, ev, transport->child,
+ &state->request);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, wb_ndr_dispatch_done, req);
+ return req;
+}
+
+static void wb_ndr_dispatch_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct wb_ndr_dispatch_state *state = tevent_req_data(
+ req, struct wb_ndr_dispatch_state);
+ int ret, err;
+
+ ret = wb_child_request_recv(subreq, state, &state->response, &err);
+ TALLOC_FREE(subreq);
+ if (ret == -1) {
+ tevent_req_nterror(req, map_nt_error_from_unix(err));
+ return;
+ }
+ tevent_req_done(req);
+}
+
+static NTSTATUS wb_ndr_dispatch_recv(struct tevent_req *req,
+ TALLOC_CTX *mem_ctx)
+{
+ struct wb_ndr_dispatch_state *state = tevent_req_data(
+ req, struct wb_ndr_dispatch_state);
+ NTSTATUS status;
+ struct ndr_pull *pull;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ blob.data = (uint8_t *)state->response->extra_data.data;
+ blob.length = state->response->length
+ - sizeof(struct winbindd_response);
+
+ pull = ndr_pull_init_blob(&blob, mem_ctx, NULL);
+ if (pull == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* have the ndr parser alloc memory for us */
+ pull->flags |= LIBNDR_FLAG_REF_ALLOC;
+ ndr_err = state->call->ndr_pull(pull, NDR_OUT, state->r);
+ TALLOC_FREE(pull);
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ return NT_STATUS_OK;
+}
+
+static NTSTATUS wb_ndr_dispatch(struct rpc_pipe_client *cli,
+ TALLOC_CTX *mem_ctx,
+ const struct ndr_interface_table *table,
+ uint32_t opnum, void *r)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct event_context *ev;
+ struct tevent_req *req;
+ NTSTATUS status = NT_STATUS_OK;
+
+ ev = event_context_init(frame);
+ if (ev == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ req = wb_ndr_dispatch_send(frame, ev, cli, table, opnum, r);
+ if (req == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto fail;
+ }
+
+ if (!tevent_req_poll(req, ev)) {
+ status = map_nt_error_from_unix(errno);
+ goto fail;
+ }
+
+ status = wb_ndr_dispatch_recv(req, mem_ctx);
+ fail:
+ TALLOC_FREE(frame);
+ return status;
+}
+
+struct rpc_pipe_client *wbint_rpccli_create(TALLOC_CTX *mem_ctx,
+ struct winbindd_child *child)
+{
+ struct rpc_pipe_client *result;
+ struct wb_ndr_transport_priv *transp;
+
+ result = talloc(mem_ctx, struct rpc_pipe_client);
+ if (result == NULL) {
+ return NULL;
+ }
+ result->abstract_syntax = ndr_table_wbint.syntax_id;
+ result->transfer_syntax = ndr_transfer_syntax;
+ result->dispatch = wb_ndr_dispatch;
+ result->dispatch_send = wb_ndr_dispatch_send;
+ result->dispatch_recv = wb_ndr_dispatch_recv;
+ result->max_xmit_frag = RPC_MAX_PDU_FRAG_LEN;
+ result->max_recv_frag = RPC_MAX_PDU_FRAG_LEN;
+ result->desthost = NULL;
+ result->srv_name_slash = NULL;
+
+ /*
+ * Initialize a fake transport. Due to our own wb_ndr_dispatch
+ * function we don't use all the fragmentation engine in
+ * cli_pipe, which would use all the _read and _write
+ * functions in rpc_cli_transport. But we need a place to
+ * store the child struct in, and we're re-using
+ * result->transport->priv for that.
+ */
+
+ result->transport = talloc_zero(result, struct rpc_cli_transport);
+ if (result->transport == NULL) {
+ TALLOC_FREE(result);
+ return NULL;
+ }
+ transp = talloc(result->transport, struct wb_ndr_transport_priv);
+ if (transp == NULL) {
+ TALLOC_FREE(result);
+ return NULL;
+ }
+ transp->child = child;
+ result->transport->priv = transp;
+ return result;
+}
+
+enum winbindd_result winbindd_dual_ndrcmd(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state)
+{
+ pipes_struct p;
+ struct api_struct *fns;
+ int num_fns;
+ bool ret;
+
+ wbint_get_pipe_fns(&fns, &num_fns);
+
+ if (state->request->data.ndrcmd >= num_fns) {
+ return WINBINDD_ERROR;
+ }
+
+ ZERO_STRUCT(p);
+ p.mem_ctx = talloc_stackframe();
+ p.in_data.data.buffer_size = state->request->extra_len;
+ p.in_data.data.data_p = state->request->extra_data.data;
+ prs_init(&p.out_data.rdata, 0, state->mem_ctx, false);
+
+ ret = fns[state->request->data.ndrcmd].fn(&p);
+ TALLOC_FREE(p.mem_ctx);
+ if (!ret) {
+ return WINBINDD_ERROR;
+ }
+
+ state->response->extra_data.data =
+ talloc_memdup(state->mem_ctx, p.out_data.rdata.data_p,
+ p.out_data.rdata.data_offset);
+ state->response->length += p.out_data.rdata.data_offset;
+ prs_mem_free(&p.out_data.rdata);
+ if (state->response->extra_data.data == NULL) {
+ return WINBINDD_ERROR;
+ }
+ return WINBINDD_OK;
+}
+
+/*
+ * Just a dummy to make srv_wbint.c happy
+ */
+NTSTATUS rpc_srv_register(int version, const char *clnt, const char *srv,
+ const struct ndr_interface_table *iface,
+ const struct api_struct *cmds, int size)
+{
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c
new file mode 100644
index 0000000000..9be295ffdc
--- /dev/null
+++ b/source3/winbindd/winbindd_dual_srv.c
@@ -0,0 +1,174 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ In-Child server implementation of the routines defined in wbint.idl
+
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd/winbindd.h"
+#include "winbindd/winbindd_proto.h"
+#include "librpc/gen_ndr/srv_wbint.h"
+
+void _wbint_Ping(pipes_struct *p, struct wbint_Ping *r)
+{
+ *r->out.out_data = r->in.in_data;
+}
+
+NTSTATUS _wbint_LookupSid(pipes_struct *p, struct wbint_LookupSid *r)
+{
+ struct winbindd_domain *domain = wb_child_domain();
+ char *dom_name;
+ char *name;
+ enum lsa_SidType type;
+ NTSTATUS status;
+
+ if (domain == NULL) {
+ return NT_STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
+ &dom_name, &name, &type);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ *r->out.domain = dom_name;
+ *r->out.name = name;
+ *r->out.type = type;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS _wbint_LookupName(pipes_struct *p, struct wbint_LookupName *r)
+{
+ struct winbindd_domain *domain = wb_child_domain();
+
+ if (domain == NULL) {
+ return NT_STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ return domain->methods->name_to_sid(
+ domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
+ r->out.sid, r->out.type);
+}
+
+NTSTATUS _wbint_Sid2Uid(pipes_struct *p, struct wbint_Sid2Uid *r)
+{
+ uid_t uid;
+ NTSTATUS status;
+
+ status = idmap_sid_to_uid(r->in.dom_name ? r->in.dom_name : "",
+ r->in.sid, &uid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ *r->out.uid = uid;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS _wbint_Sid2Gid(pipes_struct *p, struct wbint_Sid2Gid *r)
+{
+ gid_t gid;
+ NTSTATUS status;
+
+ status = idmap_sid_to_gid(r->in.dom_name ? r->in.dom_name : "",
+ r->in.sid, &gid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ *r->out.gid = gid;
+ return NT_STATUS_OK;
+}
+
+NTSTATUS _wbint_Uid2Sid(pipes_struct *p, struct wbint_Uid2Sid *r)
+{
+ NTSTATUS status;
+
+ status = idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
+ r->out.sid, r->in.uid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS _wbint_Gid2Sid(pipes_struct *p, struct wbint_Gid2Sid *r)
+{
+ NTSTATUS status;
+
+ status = idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
+ r->out.sid, r->in.gid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ return NT_STATUS_OK;
+}
+
+NTSTATUS _wbint_QueryUser(pipes_struct *p, struct wbint_QueryUser *r)
+{
+ struct winbindd_domain *domain = wb_child_domain();
+ WINBIND_USERINFO uinfo;
+ NTSTATUS status;
+
+ if (domain == NULL) {
+ return NT_STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ status = domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
+ &uinfo);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ r->out.info->acct_name = uinfo.acct_name;
+ r->out.info->full_name = uinfo.full_name;
+ r->out.info->homedir = uinfo.homedir;
+ r->out.info->shell = uinfo.shell;
+ r->out.info->primary_gid = uinfo.primary_gid;
+ sid_copy(&r->out.info->user_sid, &uinfo.user_sid);
+ sid_copy(&r->out.info->group_sid, &uinfo.group_sid);
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS _wbint_LookupUserAliases(pipes_struct *p,
+ struct wbint_LookupUserAliases *r)
+{
+ struct winbindd_domain *domain = wb_child_domain();
+
+ if (domain == NULL) {
+ return NT_STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ return domain->methods->lookup_useraliases(
+ domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
+ &r->out.rids->num_rids, &r->out.rids->rids);
+}
+
+NTSTATUS _wbint_LookupUserGroups(pipes_struct *p,
+ struct wbint_LookupUserGroups *r)
+{
+ struct winbindd_domain *domain = wb_child_domain();
+
+ if (domain == NULL) {
+ return NT_STATUS_REQUEST_NOT_ACCEPTED;
+ }
+
+ return domain->methods->lookup_usergroups(
+ domain, p->mem_ctx, r->in.sid,
+ &r->out.sids->num_sids, &r->out.sids->sids);
+}
diff --git a/source3/winbindd/winbindd_getgroups.c b/source3/winbindd/winbindd_getgroups.c
new file mode 100644
index 0000000000..9e6465696e
--- /dev/null
+++ b/source3/winbindd/winbindd_getgroups.c
@@ -0,0 +1,222 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GETGROUPS
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_getgroups_state {
+ struct tevent_context *ev;
+ fstring domname;
+ fstring username;
+ struct dom_sid sid;
+ enum lsa_SidType type;
+ int num_sids;
+ struct dom_sid *sids;
+ int next_sid;
+ int num_gids;
+ gid_t *gids;
+};
+
+static void winbindd_getgroups_lookupname_done(struct tevent_req *subreq);
+static void winbindd_getgroups_gettoken_done(struct tevent_req *subreq);
+static void winbindd_getgroups_sid2gid_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_getgroups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_getgroups_state *state;
+ char *domuser, *mapped_user;
+ struct winbindd_domain *domain;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_getgroups_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ /* Ensure null termination */
+ request->data.username[sizeof(request->data.username)-1]='\0';
+
+ DEBUG(3, ("getgroups %s\n", request->data.username));
+
+ domuser = request->data.username;
+
+ status = normalize_name_unmap(state, domuser, &mapped_user);
+
+ if (NT_STATUS_IS_OK(status)
+ || NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
+ /* normalize_name_unmapped did something */
+ domuser = mapped_user;
+ }
+
+ if (!parse_domain_user(domuser, state->domname, state->username)) {
+ DEBUG(5, ("Could not parse domain user: %s\n", domuser));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ domain = find_domain_from_name_noinit(state->domname);
+ if (domain == NULL) {
+ /* Retry with DNS name */
+ char *p = strchr(domuser, '@');
+ if (p != NULL) {
+ domain = find_domain_from_name_noinit(p+1);
+ }
+ }
+ if (domain == NULL) {
+ DEBUG(7, ("could not find domain entry for domain %s\n",
+ state->domname));
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
+ return tevent_req_post(req, ev);
+ }
+
+ if (lp_winbind_trusted_domains_only() && domain->primary) {
+ DEBUG(7,("winbindd_getgroups: My domain -- "
+ "rejecting getgroups() for %s\\%s.\n",
+ state->domname, state->username));
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_lookupname_send(state, ev, state->domname, state->username,
+ LOOKUP_NAME_NO_NSS);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_getgroups_lookupname_done,
+ req);
+ return req;
+}
+
+static void winbindd_getgroups_lookupname_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_getgroups_state *state = tevent_req_data(
+ req, struct winbindd_getgroups_state);
+ NTSTATUS status;
+
+ status = wb_lookupname_recv(subreq, &state->sid, &state->type);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ subreq = wb_gettoken_send(state, state->ev, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, winbindd_getgroups_gettoken_done, req);
+}
+
+static void winbindd_getgroups_gettoken_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_getgroups_state *state = tevent_req_data(
+ req, struct winbindd_getgroups_state);
+ NTSTATUS status;
+
+ status = wb_gettoken_recv(subreq, state, &state->num_sids,
+ &state->sids);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ /*
+ * Convert the group SIDs to gids. state->sids[0] contains the user
+ * sid, so start at index 1.
+ */
+
+ state->gids = talloc_array(state, gid_t, state->num_sids-1);
+ if (tevent_req_nomem(state->gids, req)) {
+ return;
+ }
+ state->num_gids = 0;
+ state->next_sid = 1;
+
+ subreq = wb_sid2gid_send(state, state->ev,
+ &state->sids[state->next_sid]);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, winbindd_getgroups_sid2gid_done, req);
+}
+
+static void winbindd_getgroups_sid2gid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_getgroups_state *state = tevent_req_data(
+ req, struct winbindd_getgroups_state);
+ NTSTATUS status;
+
+ status = wb_sid2gid_recv(subreq, &state->gids[state->num_gids]);
+ TALLOC_FREE(subreq);
+
+ /*
+ * In case of failure, just continue with the next gid
+ */
+ if (NT_STATUS_IS_OK(status)) {
+ state->num_gids += 1;
+ }
+ state->next_sid += 1;
+
+ if (state->next_sid >= state->num_sids) {
+ tevent_req_done(req);
+ return;
+ }
+
+ subreq = wb_sid2gid_send(state, state->ev,
+ &state->sids[state->next_sid]);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, winbindd_getgroups_sid2gid_done, req);
+}
+
+NTSTATUS winbindd_getgroups_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_getgroups_state *state = tevent_req_data(
+ req, struct winbindd_getgroups_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+
+ response->data.num_entries = state->num_gids;
+
+ if (state->num_gids > 0) {
+ response->extra_data.data = talloc_move(response,
+ &state->gids);
+ response->length += state->num_gids * sizeof(gid_t);
+ }
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_getpwnam.c b/source3/winbindd/winbindd_getpwnam.c
new file mode 100644
index 0000000000..80b618c4aa
--- /dev/null
+++ b/source3/winbindd/winbindd_getpwnam.c
@@ -0,0 +1,142 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GETPWNAM
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_getpwnam_state {
+ struct tevent_context *ev;
+ fstring domname;
+ fstring username;
+ struct dom_sid sid;
+ enum lsa_SidType type;
+ struct winbindd_pw pw;
+};
+
+static void winbindd_getpwnam_lookupname_done(struct tevent_req *subreq);
+static void winbindd_getpwnam_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_getpwnam_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_getpwnam_state *state;
+ char *domuser, *mapped_user;
+ NTSTATUS status;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_getpwnam_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ /* Ensure null termination */
+ request->data.username[sizeof(request->data.username)-1]='\0';
+
+ DEBUG(3, ("getpwnam %s\n", request->data.username));
+
+ domuser = request->data.username;
+
+ status = normalize_name_unmap(state, domuser, &mapped_user);
+
+ if (NT_STATUS_IS_OK(status)
+ || NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
+ /* normalize_name_unmapped did something */
+ domuser = mapped_user;
+ }
+
+ if (!parse_domain_user(domuser, state->domname, state->username)) {
+ DEBUG(5, ("Could not parse domain user: %s\n", domuser));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ if (lp_winbind_trusted_domains_only()
+ && strequal(state->domname, lp_workgroup())) {
+ DEBUG(7,("winbindd_getpwnam: My domain -- "
+ "rejecting getpwnam() for %s\\%s.\n",
+ state->domname, state->username));
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_lookupname_send(state, ev, state->domname, state->username,
+ LOOKUP_NAME_NO_NSS);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_getpwnam_lookupname_done,
+ req);
+ return req;
+}
+
+static void winbindd_getpwnam_lookupname_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_getpwnam_state *state = tevent_req_data(
+ req, struct winbindd_getpwnam_state);
+ NTSTATUS status;
+
+ status = wb_lookupname_recv(subreq, &state->sid, &state->type);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ subreq = wb_getpwsid_send(state, state->ev, &state->sid, &state->pw);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, winbindd_getpwnam_done, req);
+}
+
+static void winbindd_getpwnam_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
+
+ status = wb_getpwsid_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_getpwnam_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_getpwnam_state *state = tevent_req_data(
+ req, struct winbindd_getpwnam_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+ response->data.pw = state->pw;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_getpwsid.c b/source3/winbindd/winbindd_getpwsid.c
new file mode 100644
index 0000000000..135cbf6f61
--- /dev/null
+++ b/source3/winbindd/winbindd_getpwsid.c
@@ -0,0 +1,92 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GETPWSID
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_getpwsid_state {
+ struct dom_sid sid;
+ struct winbindd_pw pw;
+};
+
+static void winbindd_getpwsid_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_getpwsid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_getpwsid_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_getpwsid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ /* Ensure null termination */
+ request->data.sid[sizeof(request->data.sid)-1]='\0';
+
+ DEBUG(3, ("getpwsid %s\n", request->data.sid));
+
+ if (!string_to_sid(&state->sid, request->data.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n",
+ request->data.sid));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_getpwsid_send(state, ev, &state->sid, &state->pw);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_getpwsid_done, req);
+ return req;
+}
+
+static void winbindd_getpwsid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
+
+ status = wb_getpwsid_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_getpwsid_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_getpwsid_state *state = tevent_req_data(
+ req, struct winbindd_getpwsid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+ response->data.pw = state->pw;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_getpwuid.c b/source3/winbindd/winbindd_getpwuid.c
new file mode 100644
index 0000000000..0c667cfccc
--- /dev/null
+++ b/source3/winbindd/winbindd_getpwuid.c
@@ -0,0 +1,108 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GETPWUID
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_getpwuid_state {
+ struct tevent_context *ev;
+ struct dom_sid sid;
+ struct winbindd_pw pw;
+};
+
+static void winbindd_getpwuid_uid2sid_done(struct tevent_req *subreq);
+static void winbindd_getpwuid_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_getpwuid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_getpwuid_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_getpwuid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ DEBUG(3, ("getpwuid %d\n", (int)request->data.uid));
+
+ subreq = wb_uid2sid_send(state, ev, request->data.uid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_getpwuid_uid2sid_done,
+ req);
+ return req;
+}
+
+static void winbindd_getpwuid_uid2sid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_getpwuid_state *state = tevent_req_data(
+ req, struct winbindd_getpwuid_state);
+ NTSTATUS status;
+
+ status = wb_uid2sid_recv(subreq, &state->sid);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ subreq = wb_getpwsid_send(state, state->ev, &state->sid, &state->pw);
+ if (tevent_req_nomem(subreq, req)) {
+ return;
+ }
+ tevent_req_set_callback(subreq, winbindd_getpwuid_done, req);
+}
+
+static void winbindd_getpwuid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ NTSTATUS status;
+
+ status = wb_getpwsid_recv(subreq);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_getpwuid_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_getpwuid_state *state = tevent_req_data(
+ req, struct winbindd_getpwuid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+ response->data.pw = state->pw;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_getsidaliases.c b/source3/winbindd/winbindd_getsidaliases.c
new file mode 100644
index 0000000000..788c88f550
--- /dev/null
+++ b/source3/winbindd/winbindd_getsidaliases.c
@@ -0,0 +1,137 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GETSIDALIASES
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_getsidaliases_state {
+ struct dom_sid sid;
+ uint32_t num_aliases;
+ uint32_t *aliases;
+};
+
+static void winbindd_getsidaliases_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_getsidaliases_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_getsidaliases_state *state;
+ struct winbindd_domain *domain;
+ size_t num_sids;
+ struct dom_sid *sids;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_getsidaliases_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ /* Ensure null termination */
+ request->data.sid[sizeof(request->data.sid)-1]='\0';
+
+ DEBUG(3, ("getsidaliases %s\n", request->data.sid));
+
+ if (!string_to_sid(&state->sid, request->data.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n",
+ request->data.sid));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ domain = find_domain_from_sid_noinit(&state->sid);
+ if (domain == NULL) {
+ DEBUG(1,("could not find domain entry for sid %s\n",
+ request->data.sid));
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
+ return tevent_req_post(req, ev);
+ }
+
+ num_sids = 0;
+ sids = NULL;
+
+ if ((request->extra_data.data != NULL)
+ && !parse_sidlist(state, request->extra_data.data,
+ &sids, &num_sids)) {
+ DEBUG(1, ("Could not parse SID list: %s\n",
+ request->extra_data.data));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_lookupuseraliases_send(state, ev, domain, num_sids, sids);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_getsidaliases_done, req);
+ return req;
+}
+
+static void winbindd_getsidaliases_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_getsidaliases_state *state = tevent_req_data(
+ req, struct winbindd_getsidaliases_state);
+ NTSTATUS status;
+
+ status = wb_lookupuseraliases_recv(subreq, state, &state->num_aliases,
+ &state->aliases);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_getsidaliases_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_getsidaliases_state *state = tevent_req_data(
+ req, struct winbindd_getsidaliases_state);
+ NTSTATUS status;
+ int i;
+ char *sidlist;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ sidlist = talloc_strdup(response, "");
+ if (sidlist == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (i=0; i<state->num_aliases; i++) {
+ struct dom_sid sid;
+ fstring tmp;
+ sid_compose(&sid, &state->sid, state->aliases[i]);
+
+ sidlist = talloc_asprintf_append_buffer(
+ sidlist, "%s\n", sid_to_fstring(tmp, &sid));
+ if (sidlist == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ response->extra_data.data = sidlist;
+ response->length += talloc_get_size(sidlist);
+ response->data.num_entries = state->num_aliases;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_getuserdomgroups.c b/source3/winbindd/winbindd_getuserdomgroups.c
new file mode 100644
index 0000000000..e67768307f
--- /dev/null
+++ b/source3/winbindd/winbindd_getuserdomgroups.c
@@ -0,0 +1,121 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GETUSERDOMGROUPS
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_getuserdomgroups_state {
+ struct dom_sid sid;
+ int num_sids;
+ struct dom_sid *sids;
+};
+
+static void winbindd_getuserdomgroups_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_getuserdomgroups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_getuserdomgroups_state *state;
+ struct winbindd_domain *domain;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_getuserdomgroups_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ /* Ensure null termination */
+ request->data.sid[sizeof(request->data.sid)-1]='\0';
+
+ DEBUG(3, ("getuserdomgroups %s\n", request->data.sid));
+
+ if (!string_to_sid(&state->sid, request->data.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n",
+ request->data.sid));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ domain = find_domain_from_sid_noinit(&state->sid);
+ if (domain == NULL) {
+ DEBUG(1,("could not find domain entry for sid %s\n",
+ request->data.sid));
+ tevent_req_nterror(req, NT_STATUS_NO_SUCH_DOMAIN);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_lookupusergroups_send(state, ev, domain, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_getuserdomgroups_done, req);
+ return req;
+}
+
+static void winbindd_getuserdomgroups_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_getuserdomgroups_state *state = tevent_req_data(
+ req, struct winbindd_getuserdomgroups_state);
+ NTSTATUS status;
+
+ status = wb_lookupusergroups_recv(subreq, state, &state->num_sids,
+ &state->sids);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_getuserdomgroups_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_getuserdomgroups_state *state = tevent_req_data(
+ req, struct winbindd_getuserdomgroups_state);
+ NTSTATUS status;
+ int i;
+ char *sidlist;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ sidlist = talloc_strdup(response, "");
+ if (sidlist == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ for (i=0; i<state->num_sids; i++) {
+ fstring tmp;
+ sidlist = talloc_asprintf_append_buffer(
+ sidlist, "%s\n",
+ sid_to_fstring(tmp, &state->sids[i]));
+ if (sidlist == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+ }
+ response->extra_data.data = sidlist;
+ response->length += talloc_get_size(sidlist);
+ response->data.num_entries = state->num_sids;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_gid_to_sid.c b/source3/winbindd/winbindd_gid_to_sid.c
new file mode 100644
index 0000000000..b2cc3c2613
--- /dev/null
+++ b/source3/winbindd/winbindd_gid_to_sid.c
@@ -0,0 +1,87 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GID_TO_SID
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_gid_to_sid_state {
+ struct tevent_context *ev;
+ gid_t gid;
+ struct dom_sid sid;
+};
+
+static void winbindd_gid_to_sid_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_gid_to_sid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_gid_to_sid_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_gid_to_sid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ DEBUG(3, ("gid_to_sid %d\n", (int)request->data.gid));
+
+ subreq = wb_gid2sid_send(state, ev, request->data.gid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_gid_to_sid_done, req);
+ return req;
+}
+
+static void winbindd_gid_to_sid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_gid_to_sid_state *state = tevent_req_data(
+ req, struct winbindd_gid_to_sid_state);
+ NTSTATUS status;
+
+ status = wb_gid2sid_recv(subreq, &state->sid);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_gid_to_sid_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_gid_to_sid_state *state = tevent_req_data(
+ req, struct winbindd_gid_to_sid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+ sid_to_fstring(response->data.sid.sid, &state->sid);
+ response->data.sid.type = SID_NAME_USER;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c
index f78becb699..c1a898d73b 100644
--- a/source3/winbindd/winbindd_group.c
+++ b/source3/winbindd/winbindd_group.c
@@ -1559,178 +1559,6 @@ struct getgroups_state {
size_t num_token_gids;
};
-static void getgroups_usersid_recv(void *private_data, bool success,
- const DOM_SID *sid, enum lsa_SidType type);
-static void getgroups_tokensids_recv(void *private_data, bool success,
- DOM_SID *token_sids, size_t num_token_sids);
-static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid);
-
-void winbindd_getgroups(struct winbindd_cli_state *state)
-{
- struct getgroups_state *s;
- char *real_name = NULL;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-
- /* Ensure null termination */
- state->request->data.username
- [sizeof(state->request->data.username)-1]='\0';
-
- DEBUG(3, ("[%5lu]: getgroups %s\n", (unsigned long)state->pid,
- state->request->data.username));
-
- /* Parse domain and username */
-
- s = TALLOC_P(state->mem_ctx, struct getgroups_state);
- if (s == NULL) {
- DEBUG(0, ("talloc failed\n"));
- request_error(state);
- return;
- }
-
- s->state = state;
-
- nt_status = normalize_name_unmap(state->mem_ctx,
- state->request->data.username,
- &real_name);
-
- /* Reset the real_name pointer if we didn't do anything
- productive in the above call */
- if (!NT_STATUS_IS_OK(nt_status) &&
- !NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED))
- {
- real_name = state->request->data.username;
- }
-
- if (!parse_domain_user_talloc(state->mem_ctx, real_name,
- &s->domname, &s->username)) {
- DEBUG(5, ("Could not parse domain user: %s\n",
- real_name));
-
- /* error out if we do not have nested group support */
-
- if ( !lp_winbind_nested_groups() ) {
- request_error(state);
- return;
- }
-
- s->domname = talloc_strdup(state->mem_ctx,
- get_global_sam_name());
- s->username = talloc_strdup(state->mem_ctx,
- state->request->data.username);
- }
-
- /* Get info for the domain (either by short domain name or
- DNS name in the case of a UPN) */
-
- s->domain = find_domain_from_name_noinit(s->domname);
- if (!s->domain) {
- char *p = strchr(s->username, '@');
-
- if (p) {
- s->domain = find_domain_from_name_noinit(p+1);
- }
-
- }
-
- if (s->domain == NULL) {
- DEBUG(7, ("could not find domain entry for domain %s\n",
- s->domname));
- request_error(state);
- return;
- }
-
- if ( s->domain->primary && lp_winbind_trusted_domains_only()) {
- DEBUG(7,("winbindd_getgroups: My domain -- rejecting "
- "getgroups() for %s\\%s.\n", s->domname,
- s->username));
- request_error(state);
- return;
- }
-
- /* Get rid and name type from name. The following costs 1 packet */
-
- winbindd_lookupname_async(state->mem_ctx,
- s->domname, s->username,
- getgroups_usersid_recv,
- WINBINDD_GETGROUPS, s);
-}
-
-static void getgroups_usersid_recv(void *private_data, bool success,
- const DOM_SID *sid, enum lsa_SidType type)
-{
- struct getgroups_state *s =
- (struct getgroups_state *)private_data;
-
- if ((!success) ||
- ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER))) {
- request_error(s->state);
- return;
- }
-
- sid_copy(&s->user_sid, sid);
-
- winbindd_gettoken_async(s->state->mem_ctx, &s->user_sid,
- getgroups_tokensids_recv, s);
-}
-
-static void getgroups_tokensids_recv(void *private_data, bool success,
- DOM_SID *token_sids, size_t num_token_sids)
-{
- struct getgroups_state *s =
- (struct getgroups_state *)private_data;
-
- /* We need at least the user sid and the primary group in the token,
- * otherwise it's an error */
-
- if ((!success) || (num_token_sids < 2)) {
- request_error(s->state);
- return;
- }
-
- s->token_sids = token_sids;
- s->num_token_sids = num_token_sids;
- s->i = 0;
-
- s->token_gids = NULL;
- s->num_token_gids = 0;
-
- getgroups_sid2gid_recv(s, False, 0);
-}
-
-static void getgroups_sid2gid_recv(void *private_data, bool success, gid_t gid)
-{
- struct getgroups_state *s =
- (struct getgroups_state *)private_data;
-
- if (success) {
- if (!add_gid_to_array_unique(s->state->mem_ctx, gid,
- &s->token_gids,
- &s->num_token_gids)) {
- return;
- }
- }
-
- if (s->i < s->num_token_sids) {
- const DOM_SID *sid = &s->token_sids[s->i];
- s->i += 1;
-
- if (sid_equal(sid, &s->user_sid)) {
- getgroups_sid2gid_recv(s, False, 0);
- return;
- }
-
- winbindd_sid2gid_async(s->state->mem_ctx, sid,
- getgroups_sid2gid_recv, s);
- return;
- }
-
- s->state->response->data.num_entries = s->num_token_gids;
- if (s->num_token_gids) {
- s->state->response->extra_data.data = s->token_gids;
- s->state->response->length += s->num_token_gids * sizeof(gid_t);
- }
- request_ok(s->state);
-}
/* Get user supplementary sids. This is equivalent to the
winbindd_getgroups() function but it involves a SID->SIDs mapping
@@ -1815,32 +1643,6 @@ static void getusersids_recv(void *private_data, bool success, DOM_SID *sids,
request_ok(state);
}
-void winbindd_getuserdomgroups(struct winbindd_cli_state *state)
-{
- DOM_SID user_sid;
- struct winbindd_domain *domain;
-
- /* Ensure null termination */
- state->request->data.sid[sizeof(state->request->data.sid)-1]='\0';
-
- if (!string_to_sid(&user_sid, state->request->data.sid)) {
- DEBUG(1, ("Could not get convert sid %s from string\n",
- state->request->data.sid));
- request_error(state);
- return;
- }
-
- /* Get info for the domain */
- if ((domain = find_domain_from_sid_noinit(&user_sid)) == NULL) {
- DEBUG(0,("could not find domain entry for sid %s\n",
- sid_string_dbg(&user_sid)));
- request_error(state);
- return;
- }
-
- sendto_domain(state, domain);
-}
-
enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
@@ -1887,32 +1689,6 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma
return WINBINDD_OK;
}
-void winbindd_getsidaliases(struct winbindd_cli_state *state)
-{
- DOM_SID domain_sid;
- struct winbindd_domain *domain;
-
- /* Ensure null termination */
- state->request->data.sid[sizeof(state->request->data.sid)-1]='\0';
-
- if (!string_to_sid(&domain_sid, state->request->data.sid)) {
- DEBUG(1, ("Could not get convert sid %s from string\n",
- state->request->data.sid));
- request_error(state);
- return;
- }
-
- /* Get info for the domain */
- if ((domain = find_domain_from_sid_noinit(&domain_sid)) == NULL) {
- DEBUG(0,("could not find domain entry for sid %s\n",
- sid_string_dbg(&domain_sid)));
- request_error(state);
- return;
- }
-
- sendto_domain(state, domain);
-}
-
enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain,
struct winbindd_cli_state *state)
{
diff --git a/source3/winbindd/winbindd_idmap.c b/source3/winbindd/winbindd_idmap.c
index 6e24a9c212..7bcc58a014 100644
--- a/source3/winbindd/winbindd_idmap.c
+++ b/source3/winbindd/winbindd_idmap.c
@@ -565,6 +565,10 @@ static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = {
.struct_cmd = WINBINDD_ALLOCATE_GID,
.struct_fn = winbindd_dual_allocate_gid,
},{
+ .name = "NDRCMD",
+ .struct_cmd = WINBINDD_DUAL_NDRCMD,
+ .struct_fn = winbindd_dual_ndrcmd,
+ },{
.name = NULL,
}
};
diff --git a/source3/winbindd/winbindd_locator.c b/source3/winbindd/winbindd_locator.c
index 43dadfae29..b35d8dcf54 100644
--- a/source3/winbindd/winbindd_locator.c
+++ b/source3/winbindd/winbindd_locator.c
@@ -165,6 +165,10 @@ static const struct winbindd_child_dispatch_table locator_dispatch_table[] = {
.struct_cmd = WINBINDD_DSGETDCNAME,
.struct_fn = dual_dsgetdcname,
},{
+ .name = "NDRCMD",
+ .struct_cmd = WINBINDD_DUAL_NDRCMD,
+ .struct_fn = winbindd_dual_ndrcmd,
+ },{
.name = NULL,
}
};
diff --git a/source3/winbindd/winbindd_lookupname.c b/source3/winbindd/winbindd_lookupname.c
new file mode 100644
index 0000000000..0918076717
--- /dev/null
+++ b/source3/winbindd/winbindd_lookupname.c
@@ -0,0 +1,110 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GETPWNAM
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_lookupname_state {
+ struct tevent_context *ev;
+ struct dom_sid sid;
+ enum lsa_SidType type;
+};
+
+static void winbindd_lookupname_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_lookupname_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_lookupname_state *state;
+ char *domname, *name, *p;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_lookupname_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ /* Ensure null termination */
+ request->data.name.dom_name[
+ sizeof(request->data.name.dom_name)-1]='\0';
+ request->data.name.name[sizeof(request->data.name.name)-1]='\0';
+
+ /* cope with the name being a fully qualified name */
+ p = strstr(request->data.name.name, lp_winbind_separator());
+ if (p) {
+ *p = 0;
+ domname = request->data.name.name;
+ name = p+1;
+ } else if ((p = strchr(request->data.name.name, '@')) != NULL) {
+ /* upn */
+ domname = p + 1;
+ *p = 0;
+ name = request->data.name.name;
+ } else {
+ domname = request->data.name.dom_name;
+ name = request->data.name.name;
+ }
+
+ DEBUG(3, ("lookupname %s%s%s\n", domname, lp_winbind_separator(),
+ name));
+
+ subreq = wb_lookupname_send(state, ev, domname, name, 0);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_lookupname_done, req);
+ return req;
+}
+
+static void winbindd_lookupname_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_lookupname_state *state = tevent_req_data(
+ req, struct winbindd_lookupname_state);
+ NTSTATUS status;
+
+ status = wb_lookupname_recv(subreq, &state->sid, &state->type);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_lookupname_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_lookupname_state *state = tevent_req_data(
+ req, struct winbindd_lookupname_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+ sid_to_fstring(response->data.sid.sid, &state->sid);
+ response->data.sid.type = state->type;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_lookupsid.c b/source3/winbindd/winbindd_lookupsid.c
new file mode 100644
index 0000000000..7647f1d682
--- /dev/null
+++ b/source3/winbindd/winbindd_lookupsid.c
@@ -0,0 +1,101 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_GETPWNAM
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_lookupsid_state {
+ struct tevent_context *ev;
+ struct dom_sid sid;
+ enum lsa_SidType type;
+ const char *domname;
+ const char *name;
+};
+
+static void winbindd_lookupsid_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_lookupsid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_lookupsid_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_lookupsid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ /* Ensure null termination */
+ request->data.sid[sizeof(request->data.sid)-1]='\0';
+
+ DEBUG(3, ("lookupsid %s\n", request->data.sid));
+
+ if (!string_to_sid(&state->sid, request->data.sid)) {
+ DEBUG(5, ("%s not a SID\n", request->data.sid));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);;
+ }
+
+ subreq = wb_lookupsid_send(state, ev, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_lookupsid_done, req);
+ return req;
+}
+
+static void winbindd_lookupsid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_lookupsid_state *state = tevent_req_data(
+ req, struct winbindd_lookupsid_state);
+ NTSTATUS status;
+
+ status = wb_lookupsid_recv(subreq, state, &state->type,
+ &state->domname, &state->name);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_lookupsid_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_lookupsid_state *state = tevent_req_data(
+ req, struct winbindd_lookupsid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not lookup sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+
+ fstrcpy(response->data.name.dom_name, state->domname);
+ fstrcpy(response->data.name.name, state->name);
+ response->data.name.type = state->type;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_misc.c b/source3/winbindd/winbindd_misc.c
index 3f71910023..c6608316d1 100644
--- a/source3/winbindd/winbindd_misc.c
+++ b/source3/winbindd/winbindd_misc.c
@@ -741,12 +741,6 @@ static void domain_info_done(struct tevent_req *req)
request_ok(state->cli);
}
-void winbindd_ping(struct winbindd_cli_state *state)
-{
- DEBUG(3, ("[%5lu]: ping\n", (unsigned long)state->pid));
- request_ok(state);
-}
-
/* List various tidbits of information */
void winbindd_info(struct winbindd_cli_state *state)
diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h
index c9decf8cc4..a9a374a532 100644
--- a/source3/winbindd/winbindd_proto.h
+++ b/source3/winbindd/winbindd_proto.h
@@ -100,7 +100,7 @@ enum winbindd_result winbindd_dual_list_groups(struct winbindd_domain *domain,
struct winbindd_cli_state *state);
bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
size_t num_sids, char **result, ssize_t *len);
-bool parse_sidlist(TALLOC_CTX *mem_ctx, char *sidstr,
+bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
DOM_SID **sids, size_t *num_sids);
enum winbindd_result winbindd_dual_lookuprids(struct winbindd_domain *domain,
struct winbindd_cli_state *state);
@@ -149,6 +149,12 @@ bool wcache_invalidate_cache(void);
bool init_wcache(void);
bool initialize_winbindd_cache(void);
void close_winbindd_cache(void);
+NTSTATUS wcache_sid_to_name(struct winbindd_domain *domain,
+ const struct dom_sid *sid,
+ TALLOC_CTX *mem_ctx,
+ char **domain_name,
+ char **name,
+ enum lsa_SidType *type);
bool lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
char **domain_name, char **name,
enum lsa_SidType *type);
@@ -160,6 +166,25 @@ bool lookup_cached_name(TALLOC_CTX *mem_ctx,
void cache_name2sid(struct winbindd_domain *domain,
const char *domain_name, const char *name,
enum lsa_SidType type, const DOM_SID *sid);
+NTSTATUS wcache_name_to_sid(struct winbindd_domain *domain,
+ const char *domain_name,
+ const char *name,
+ struct dom_sid *sid,
+ enum lsa_SidType *type);
+NTSTATUS wcache_query_user(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ struct winbind_userinfo *info);
+NTSTATUS wcache_lookup_useraliases(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ uint32 num_sids, const DOM_SID *sids,
+ uint32 *pnum_aliases, uint32 **paliases);
+NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain,
+ TALLOC_CTX *mem_ctx,
+ const struct dom_sid *user_sid,
+ uint32_t *pnum_sids,
+ struct dom_sid **psids);
+
void wcache_flush_cache(void);
NTSTATUS wcache_count_cached_creds(struct winbindd_domain *domain, int *count);
NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DOM_SID *sid) ;
@@ -330,6 +355,7 @@ void winbind_msg_dump_domain_list(struct messaging_context *msg_ctx,
struct server_id server_id,
DATA_BLOB *data);
bool winbindd_reinit_after_fork(const char *logfilename);
+struct winbindd_domain *wb_child_domain(void);
/* The following definitions come from winbindd/winbindd_group.c */
@@ -492,6 +518,14 @@ enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain,
/* The following definitions come from winbindd/winbindd_user.c */
+bool fillup_pw_field(const char *lp_template,
+ const char *username,
+ const char *domname,
+ uid_t uid,
+ gid_t gid,
+ const char *in,
+ fstring out);
+
enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain,
struct winbindd_cli_state *state);
void winbindd_getpwnam(struct winbindd_cli_state *state);
@@ -594,4 +628,145 @@ NTSTATUS wb_ping_recv(struct tevent_req *req,
enum winbindd_result winbindd_dual_ping(struct winbindd_domain *domain,
struct winbindd_cli_state *state);
+struct rpc_pipe_client *wbint_rpccli_create(TALLOC_CTX *mem_ctx,
+ struct winbindd_child *child);
+enum winbindd_result winbindd_dual_ndrcmd(struct winbindd_domain *domain,
+ struct winbindd_cli_state *state);
+
+struct tevent_req *wb_lookupsid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *sid);
+NTSTATUS wb_lookupsid_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ enum lsa_SidType *type, const char **domain,
+ const char **name);
+
+struct tevent_req *winbindd_lookupsid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_lookupsid_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+struct tevent_req *wb_lookupname_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const char *dom_name, const char *name,
+ uint32_t flags);
+NTSTATUS wb_lookupname_recv(struct tevent_req *req, struct dom_sid *sid,
+ enum lsa_SidType *type);
+
+struct tevent_req *winbindd_lookupname_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_lookupname_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+struct tevent_req *wb_sid2uid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *sid);
+NTSTATUS wb_sid2uid_recv(struct tevent_req *req, uid_t *uid);
+
+struct tevent_req *winbindd_sid_to_uid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_sid_to_uid_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+struct tevent_req *wb_sid2gid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *sid);
+NTSTATUS wb_sid2gid_recv(struct tevent_req *req, gid_t *gid);
+
+struct tevent_req *winbindd_sid_to_gid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_sid_to_gid_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+struct tevent_req *wb_uid2sid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ uid_t uid);
+NTSTATUS wb_uid2sid_recv(struct tevent_req *req, struct dom_sid *sid);
+
+struct tevent_req *winbindd_uid_to_sid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_uid_to_sid_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+struct tevent_req *wb_gid2sid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ gid_t gid);
+NTSTATUS wb_gid2sid_recv(struct tevent_req *req, struct dom_sid *sid);
+
+struct tevent_req *winbindd_gid_to_sid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_gid_to_sid_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *user_sid);
+NTSTATUS wb_queryuser_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ struct winbind_userinfo **pinfo);
+
+struct tevent_req *wb_getpwsid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *user_sid,
+ struct winbindd_pw *pw);
+NTSTATUS wb_getpwsid_recv(struct tevent_req *req);
+
+struct tevent_req *winbindd_getpwsid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_getpwsid_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+struct tevent_req *winbindd_getpwnam_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_getpwnam_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+struct tevent_req *winbindd_getpwuid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_getpwuid_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+struct tevent_req *wb_lookupuseraliases_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_domain *domain,
+ int num_sids,
+ const struct dom_sid *sids);
+NTSTATUS wb_lookupuseraliases_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint32_t *num_aliases, uint32_t **aliases);
+struct tevent_req *winbindd_getsidaliases_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_getsidaliases_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_domain *domain,
+ const struct dom_sid *sid);
+NTSTATUS wb_lookupusergroups_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ int *num_sids, struct dom_sid **sids);
+
+struct tevent_req *winbindd_getuserdomgroups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_getuserdomgroups_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ const struct dom_sid *sid);
+NTSTATUS wb_gettoken_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ int *num_sids, struct dom_sid **sids);
+struct tevent_req *winbindd_getgroups_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request);
+NTSTATUS winbindd_getgroups_recv(struct tevent_req *req,
+ struct winbindd_response *response);
+
+
+
#endif /* _WINBINDD_PROTO_H_ */
diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c
index f8cf7db920..db000682ae 100644
--- a/source3/winbindd/winbindd_sid.c
+++ b/source3/winbindd/winbindd_sid.c
@@ -27,108 +27,6 @@
/* Convert a string */
-static void lookupsid_recv(void *private_data, bool success,
- const char *dom_name, const char *name,
- enum lsa_SidType type);
-
-void winbindd_lookupsid(struct winbindd_cli_state *state)
-{
- DOM_SID sid;
-
- /* Ensure null termination */
- state->request->data.sid[sizeof(state->request->data.sid)-1]='\0';
-
- DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid,
- state->request->data.sid));
-
- if (!string_to_sid(&sid, state->request->data.sid)) {
- DEBUG(5, ("%s not a SID\n", state->request->data.sid));
- request_error(state);
- return;
- }
-
- winbindd_lookupsid_async(state->mem_ctx, &sid, lookupsid_recv, state);
-}
-
-static void lookupsid_recv(void *private_data, bool success,
- const char *dom_name, const char *name,
- enum lsa_SidType type)
-{
- struct winbindd_cli_state *state =
- talloc_get_type_abort(private_data, struct winbindd_cli_state);
-
- if (!success) {
- DEBUG(5, ("lookupsid returned an error\n"));
- request_error(state);
- return;
- }
-
- fstrcpy(state->response->data.name.dom_name, dom_name);
- fstrcpy(state->response->data.name.name, name);
- state->response->data.name.type = type;
- request_ok(state);
-}
-
-/**
- * Look up the SID for a qualified name.
- **/
-
-static void lookupname_recv(void *private_data, bool success,
- const DOM_SID *sid, enum lsa_SidType type);
-
-void winbindd_lookupname(struct winbindd_cli_state *state)
-{
- char *name_domain, *name_user;
- char *p;
-
- /* Ensure null termination */
- state->request->data.name.dom_name[sizeof(state->request->data.name.dom_name)-1]='\0';
-
- /* Ensure null termination */
- state->request->data.name.name[sizeof(state->request->data.name.name)-1]='\0';
-
- /* cope with the name being a fully qualified name */
- p = strstr(state->request->data.name.name, lp_winbind_separator());
- if (p) {
- *p = 0;
- name_domain = state->request->data.name.name;
- name_user = p+1;
- } else if ((p = strchr(state->request->data.name.name, '@')) != NULL) {
- /* upn */
- name_domain = p + 1;
- *p = 0;
- name_user = state->request->data.name.name;
- } else {
- name_domain = state->request->data.name.dom_name;
- name_user = state->request->data.name.name;
- }
-
- DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
- name_domain, lp_winbind_separator(), name_user));
-
- winbindd_lookupname_async(state->mem_ctx, name_domain, name_user,
- lookupname_recv, WINBINDD_LOOKUPNAME,
- state);
-}
-
-static void lookupname_recv(void *private_data, bool success,
- const DOM_SID *sid, enum lsa_SidType type)
-{
- struct winbindd_cli_state *state =
- talloc_get_type_abort(private_data, struct winbindd_cli_state);
-
- if (!success) {
- DEBUG(5, ("lookupname returned an error\n"));
- request_error(state);
- return;
- }
-
- sid_to_fstring(state->response->data.sid.sid, sid);
- state->response->data.sid.type = type;
- request_ok(state);
- return;
-}
-
void winbindd_lookuprids(struct winbindd_cli_state *state)
{
struct winbindd_domain *domain;
@@ -157,228 +55,6 @@ void winbindd_lookuprids(struct winbindd_cli_state *state)
sendto_domain(state, domain);
}
-/* Convert a sid to a uid. We assume we only have one rid attached to the
- sid. */
-
-static void sid2uid_recv(void *private_data, bool success, uid_t uid)
-{
- struct winbindd_cli_state *state =
- talloc_get_type_abort(private_data, struct winbindd_cli_state);
- struct dom_sid sid;
-
- string_to_sid(&sid, state->request->data.sid);
-
- if (!success) {
- DEBUG(5, ("Could not convert sid %s\n",
- state->request->data.sid));
- request_error(state);
- return;
- }
-
- state->response->data.uid = uid;
- request_ok(state);
-}
-
-static void sid2uid_lookupsid_recv( void *private_data, bool success,
- const char *domain_name,
- const char *name,
- enum lsa_SidType type)
-{
- struct winbindd_cli_state *state =
- talloc_get_type_abort(private_data, struct winbindd_cli_state);
- DOM_SID sid;
-
- if (!string_to_sid(&sid, state->request->data.sid)) {
- DEBUG(1, ("sid2uid_lookupsid_recv: Could not get convert sid "
- "%s from string\n", state->request->data.sid));
- request_error(state);
- return;
- }
-
- if (!success) {
- DEBUG(5, ("sid2uid_lookupsid_recv Could not convert get sid type for %s\n",
- state->request->data.sid));
- goto fail;
- }
-
- if ( (type!=SID_NAME_USER) && (type!=SID_NAME_COMPUTER) ) {
- DEBUG(5,("sid2uid_lookupsid_recv: Sid %s is not a user or a computer.\n",
- state->request->data.sid));
- goto fail;
- }
-
- /* always use the async interface (may block) */
- winbindd_sid2uid_async(state->mem_ctx, &sid, sid2uid_recv, state);
- return;
-
- fail:
- /*
- * We have to set the cache ourselves here, the child which is
- * normally responsible was not queried yet.
- */
- idmap_cache_set_sid2uid(&sid, -1);
- request_error(state);
- return;
-}
-
-void winbindd_sid_to_uid(struct winbindd_cli_state *state)
-{
- DOM_SID sid;
- uid_t uid;
- bool expired;
-
- /* Ensure null termination */
- state->request->data.sid[sizeof(state->request->data.sid)-1]='\0';
-
- DEBUG(3, ("[%5lu]: sid to uid %s\n", (unsigned long)state->pid,
- state->request->data.sid));
-
- if (!string_to_sid(&sid, state->request->data.sid)) {
- DEBUG(1, ("Could not get convert sid %s from string\n",
- state->request->data.sid));
- request_error(state);
- return;
- }
-
- if (idmap_cache_find_sid2uid(&sid, &uid, &expired)) {
- DEBUG(10, ("idmap_cache_find_sid2uid found %d%s\n",
- (int)uid, expired ? " (expired)": ""));
- if (expired && IS_DOMAIN_ONLINE(find_our_domain())) {
- DEBUG(10, ("revalidating expired entry\n"));
- goto backend;
- }
- if (uid == -1) {
- DEBUG(10, ("Returning negative cache entry\n"));
- request_error(state);
- return;
- }
- DEBUG(10, ("Returning positive cache entry\n"));
- state->response->data.uid = uid;
- request_ok(state);
- return;
- }
-
- /* Validate the SID as a user. Hopefully this will hit cache.
- Needed to prevent DoS by exhausting the uid allocation
- range from random SIDs. */
-
- backend:
- winbindd_lookupsid_async( state->mem_ctx, &sid, sid2uid_lookupsid_recv, state );
-}
-
-/* Convert a sid to a gid. We assume we only have one rid attached to the
- sid.*/
-
-static void sid2gid_recv(void *private_data, bool success, gid_t gid)
-{
- struct winbindd_cli_state *state =
- talloc_get_type_abort(private_data, struct winbindd_cli_state);
- struct dom_sid sid;
-
- string_to_sid(&sid, state->request->data.sid);
-
- if (!success) {
- DEBUG(5, ("Could not convert sid %s\n",
- state->request->data.sid));
- request_error(state);
- return;
- }
-
- state->response->data.gid = gid;
- request_ok(state);
-}
-
-static void sid2gid_lookupsid_recv( void *private_data, bool success,
- const char *domain_name,
- const char *name,
- enum lsa_SidType type)
-{
- struct winbindd_cli_state *state =
- talloc_get_type_abort(private_data, struct winbindd_cli_state);
- DOM_SID sid;
-
- if (!string_to_sid(&sid, state->request->data.sid)) {
- DEBUG(1, ("sid2gid_lookupsid_recv: Could not get convert sid "
- "%s from string\n", state->request->data.sid));
- request_error(state);
- return;
- }
-
- if (!success) {
- DEBUG(5, ("sid2gid_lookupsid_recv: Could not get sid type for %s\n",
- state->request->data.sid));
- goto fail;
- }
-
- if ( (type!=SID_NAME_DOM_GRP) &&
- (type!=SID_NAME_ALIAS) &&
- (type!=SID_NAME_WKN_GRP) )
- {
- DEBUG(5,("sid2gid_lookupsid_recv: Sid %s is not a group.\n",
- state->request->data.sid));
- goto fail;
- }
-
- /* always use the async interface (may block) */
- winbindd_sid2gid_async(state->mem_ctx, &sid, sid2gid_recv, state);
- return;
-
- fail:
- /*
- * We have to set the cache ourselves here, the child which is
- * normally responsible was not queried yet.
- */
- idmap_cache_set_sid2gid(&sid, -1);
- request_error(state);
- return;
-}
-
-void winbindd_sid_to_gid(struct winbindd_cli_state *state)
-{
- DOM_SID sid;
- gid_t gid;
- bool expired;
-
- /* Ensure null termination */
- state->request->data.sid[sizeof(state->request->data.sid)-1]='\0';
-
- DEBUG(3, ("[%5lu]: sid to gid %s\n", (unsigned long)state->pid,
- state->request->data.sid));
-
- if (!string_to_sid(&sid, state->request->data.sid)) {
- DEBUG(1, ("Could not get convert sid %s from string\n",
- state->request->data.sid));
- request_error(state);
- return;
- }
-
- if (idmap_cache_find_sid2gid(&sid, &gid, &expired)) {
- DEBUG(10, ("idmap_cache_find_sid2gid found %d%s\n",
- (int)gid, expired ? " (expired)": ""));
- if (expired && IS_DOMAIN_ONLINE(find_our_domain())) {
- DEBUG(10, ("revalidating expired entry\n"));
- goto backend;
- }
- if (gid == -1) {
- DEBUG(10, ("Returning negative cache entry\n"));
- request_error(state);
- return;
- }
- DEBUG(10, ("Returning positive cache entry\n"));
- state->response->data.gid = gid;
- request_ok(state);
- return;
- }
-
- /* Validate the SID as a group. Hopefully this will hit cache.
- Needed to prevent DoS by exhausting the uid allocation
- range from random SIDs. */
-
- backend:
- winbindd_lookupsid_async( state->mem_ctx, &sid, sid2gid_lookupsid_recv,
- state );
-}
-
static void set_mapping_recv(void *private_data, bool success)
{
struct winbindd_cli_state *state =
@@ -495,122 +171,6 @@ void winbindd_set_hwm(struct winbindd_cli_state *state)
winbindd_set_hwm_async(state->mem_ctx, &xid, set_hwm_recv, state);
}
-/* Convert a uid to a sid */
-
-static void uid2sid_recv(void *private_data, bool success, const char *sidstr)
-{
- struct winbindd_cli_state *state =
- (struct winbindd_cli_state *)private_data;
- struct dom_sid sid;
-
- if (!success || !string_to_sid(&sid, sidstr)) {
- ZERO_STRUCT(sid);
- idmap_cache_set_sid2uid(&sid, state->request->data.uid);
- request_error(state);
- return;
- }
-
- DEBUG(10,("uid2sid: uid %lu has sid %s\n",
- (unsigned long)(state->request->data.uid), sidstr));
-
- idmap_cache_set_sid2uid(&sid, state->request->data.uid);
- fstrcpy(state->response->data.sid.sid, sidstr);
- state->response->data.sid.type = SID_NAME_USER;
- request_ok(state);
- return;
-}
-
-void winbindd_uid_to_sid(struct winbindd_cli_state *state)
-{
- struct dom_sid sid;
- bool expired;
-
- DEBUG(3, ("[%5lu]: uid to sid %lu\n", (unsigned long)state->pid,
- (unsigned long)state->request->data.uid));
-
- if (idmap_cache_find_uid2sid(state->request->data.uid, &sid,
- &expired)) {
- DEBUG(10, ("idmap_cache_find_uid2sid found %d%s\n",
- (int)state->request->data.uid,
- expired ? " (expired)": ""));
- if (expired && IS_DOMAIN_ONLINE(find_our_domain())) {
- DEBUG(10, ("revalidating expired entry\n"));
- goto backend;
- }
- if (is_null_sid(&sid)) {
- DEBUG(10, ("Returning negative cache entry\n"));
- request_error(state);
- return;
- }
- DEBUG(10, ("Returning positive cache entry\n"));
- sid_to_fstring(state->response->data.sid.sid, &sid);
- request_ok(state);
- return;
- }
-
- /* always go via the async interface (may block) */
- backend:
- winbindd_uid2sid_async(state->mem_ctx, state->request->data.uid, uid2sid_recv, state);
-}
-
-/* Convert a gid to a sid */
-
-static void gid2sid_recv(void *private_data, bool success, const char *sidstr)
-{
- struct winbindd_cli_state *state =
- (struct winbindd_cli_state *)private_data;
- struct dom_sid sid;
-
- if (!success || !string_to_sid(&sid, sidstr)) {
- ZERO_STRUCT(sid);
- idmap_cache_set_sid2gid(&sid, state->request->data.gid);
- request_error(state);
- return;
- }
- DEBUG(10,("gid2sid: gid %lu has sid %s\n",
- (unsigned long)(state->request->data.gid), sidstr));
-
- idmap_cache_set_sid2gid(&sid, state->request->data.gid);
- fstrcpy(state->response->data.sid.sid, sidstr);
- state->response->data.sid.type = SID_NAME_DOM_GRP;
- request_ok(state);
- return;
-}
-
-
-void winbindd_gid_to_sid(struct winbindd_cli_state *state)
-{
- struct dom_sid sid;
- bool expired;
-
- DEBUG(3, ("[%5lu]: gid to sid %lu\n", (unsigned long)state->pid,
- (unsigned long)state->request->data.gid));
-
- if (idmap_cache_find_gid2sid(state->request->data.gid, &sid,
- &expired)) {
- DEBUG(10, ("idmap_cache_find_gid2sid found %d%s\n",
- (int)state->request->data.gid,
- expired ? " (expired)": ""));
- if (expired && IS_DOMAIN_ONLINE(find_our_domain())) {
- DEBUG(10, ("revalidating expired entry\n"));
- goto backend;
- }
- if (is_null_sid(&sid)) {
- DEBUG(10, ("Returning negative cache entry\n"));
- request_error(state);
- return;
- }
- DEBUG(10, ("Returning positive cache entry\n"));
- sid_to_fstring(state->response->data.sid.sid, &sid);
- request_ok(state);
- return;
- }
-
- /* always use async calls (may block) */
- backend:
- winbindd_gid2sid_async(state->mem_ctx, state->request->data.gid, gid2sid_recv, state);
-}
-
void winbindd_allocate_uid(struct winbindd_cli_state *state)
{
if ( !state->privileged ) {
diff --git a/source3/winbindd/winbindd_sid_to_gid.c b/source3/winbindd/winbindd_sid_to_gid.c
new file mode 100644
index 0000000000..323b44d7f9
--- /dev/null
+++ b/source3/winbindd/winbindd_sid_to_gid.c
@@ -0,0 +1,94 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_SID_TO_GID
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_sid_to_gid_state {
+ struct dom_sid sid;
+ gid_t gid;
+};
+
+static void winbindd_sid_to_gid_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_sid_to_gid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_sid_to_gid_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_sid_to_gid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ /* Ensure null termination */
+ request->data.sid[sizeof(request->data.sid)-1]='\0';
+
+ DEBUG(3, ("sid to gid %s\n", request->data.sid));
+
+ if (!string_to_sid(&state->sid, request->data.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n",
+ request->data.sid));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_sid2gid_send(state, ev, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_sid_to_gid_done, req);
+ return req;
+}
+
+static void winbindd_sid_to_gid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_sid_to_gid_state *state = tevent_req_data(
+ req, struct winbindd_sid_to_gid_state);
+ NTSTATUS status;
+
+ status = wb_sid2gid_recv(subreq, &state->gid);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_sid_to_gid_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_sid_to_gid_state *state = tevent_req_data(
+ req, struct winbindd_sid_to_gid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+ response->data.gid = state->gid;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_sid_to_uid.c b/source3/winbindd/winbindd_sid_to_uid.c
new file mode 100644
index 0000000000..a6ff6cbaf4
--- /dev/null
+++ b/source3/winbindd/winbindd_sid_to_uid.c
@@ -0,0 +1,94 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_SID_TO_UID
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_sid_to_uid_state {
+ struct dom_sid sid;
+ uid_t uid;
+};
+
+static void winbindd_sid_to_uid_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_sid_to_uid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_sid_to_uid_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_sid_to_uid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ /* Ensure null termination */
+ request->data.sid[sizeof(request->data.sid)-1]='\0';
+
+ DEBUG(3, ("sid to uid %s\n", request->data.sid));
+
+ if (!string_to_sid(&state->sid, request->data.sid)) {
+ DEBUG(1, ("Could not get convert sid %s from string\n",
+ request->data.sid));
+ tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
+ return tevent_req_post(req, ev);
+ }
+
+ subreq = wb_sid2uid_send(state, ev, &state->sid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_sid_to_uid_done, req);
+ return req;
+}
+
+static void winbindd_sid_to_uid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_sid_to_uid_state *state = tevent_req_data(
+ req, struct winbindd_sid_to_uid_state);
+ NTSTATUS status;
+
+ status = wb_sid2uid_recv(subreq, &state->uid);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_sid_to_uid_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_sid_to_uid_state *state = tevent_req_data(
+ req, struct winbindd_sid_to_uid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+ response->data.uid = state->uid;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_uid_to_sid.c b/source3/winbindd/winbindd_uid_to_sid.c
new file mode 100644
index 0000000000..151fffd296
--- /dev/null
+++ b/source3/winbindd/winbindd_uid_to_sid.c
@@ -0,0 +1,87 @@
+/*
+ Unix SMB/CIFS implementation.
+ async implementation of WINBINDD_UID_TO_SID
+ Copyright (C) Volker Lendecke 2009
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "winbindd.h"
+
+struct winbindd_uid_to_sid_state {
+ struct tevent_context *ev;
+ uid_t uid;
+ struct dom_sid sid;
+};
+
+static void winbindd_uid_to_sid_done(struct tevent_req *subreq);
+
+struct tevent_req *winbindd_uid_to_sid_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct winbindd_request *request)
+{
+ struct tevent_req *req, *subreq;
+ struct winbindd_uid_to_sid_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct winbindd_uid_to_sid_state);
+ if (req == NULL) {
+ return NULL;
+ }
+ state->ev = ev;
+
+ DEBUG(3, ("uid_to_sid %d\n", (int)request->data.uid));
+
+ subreq = wb_uid2sid_send(state, ev, request->data.uid);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, winbindd_uid_to_sid_done, req);
+ return req;
+}
+
+static void winbindd_uid_to_sid_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct winbindd_uid_to_sid_state *state = tevent_req_data(
+ req, struct winbindd_uid_to_sid_state);
+ NTSTATUS status;
+
+ status = wb_uid2sid_recv(subreq, &state->sid);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ tevent_req_nterror(req, status);
+ return;
+ }
+ tevent_req_done(req);
+}
+
+NTSTATUS winbindd_uid_to_sid_recv(struct tevent_req *req,
+ struct winbindd_response *response)
+{
+ struct winbindd_uid_to_sid_state *state = tevent_req_data(
+ req, struct winbindd_uid_to_sid_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ DEBUG(5, ("Could not convert sid %s: %s\n",
+ sid_string_dbg(&state->sid), nt_errstr(status)));
+ return status;
+ }
+ sid_to_fstring(response->data.sid.sid, &state->sid);
+ response->data.sid.type = SID_NAME_USER;
+ return NT_STATUS_OK;
+}
diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c
index c445ef0bdc..240b0f524f 100644
--- a/source3/winbindd/winbindd_user.c
+++ b/source3/winbindd/winbindd_user.c
@@ -27,7 +27,7 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_WINBIND
-static bool fillup_pw_field(const char *lp_template,
+bool fillup_pw_field(const char *lp_template,
const char *username,
const char *domname,
uid_t uid,
@@ -195,386 +195,6 @@ enum winbindd_result winbindd_dual_userinfo(struct winbindd_domain *domain,
return WINBINDD_OK;
}
-struct getpwsid_state {
- struct winbindd_cli_state *state;
- struct winbindd_domain *domain;
- char *username;
- char *fullname;
- char *homedir;
- char *shell;
- DOM_SID user_sid;
- uid_t uid;
- DOM_SID group_sid;
- gid_t gid;
- bool username_mapped;
-};
-
-static void getpwsid_queryuser_recv(void *private_data, bool success,
- const char *acct_name,
- const char *full_name,
- const char *homedir,
- const char *shell,
- gid_t gid,
- uint32 group_rid);
-static void getpwsid_sid2uid_recv(void *private_data, bool success, uid_t uid);
-static void getpwsid_sid2gid_recv(void *private_data, bool success, gid_t gid);
-
-static void getpwsid_queryuser(struct winbindd_cli_state *state,
- const DOM_SID *sid)
-{
- struct getpwsid_state *s;
-
- s = TALLOC_ZERO_P(state->mem_ctx, struct getpwsid_state);
- if (s == NULL) {
- DEBUG(0, ("talloc failed\n"));
- goto error;
- }
-
- s->state = state;
- s->domain = find_domain_from_sid_noinit(sid);
- if (s->domain == NULL) {
- DEBUG(3, ("Could not find domain for sid %s\n",
- sid_string_dbg(sid)));
- goto error;
- }
-
- sid_copy(&s->user_sid, sid);
-
- query_user_async(s->state->mem_ctx, s->domain, sid,
- getpwsid_queryuser_recv, s);
- return;
-
- error:
- request_error(state);
-}
-
-static void getpwsid_queryuser_recv(void *private_data, bool success,
- const char *acct_name,
- const char *full_name,
- const char *homedir,
- const char *shell,
- gid_t gid,
- uint32 group_rid)
-{
- fstring username;
- struct getpwsid_state *s =
- talloc_get_type_abort(private_data, struct getpwsid_state);
- char *mapped_name;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-
- if (!success) {
- DEBUG(5, ("Could not query domain %s SID %s\n",
- s->domain->name, sid_string_dbg(&s->user_sid)));
- request_error(s->state);
- return;
- }
-
- if ( acct_name && *acct_name ) {
- fstrcpy( username, acct_name );
- } else {
- char *domain_name = NULL;
- enum lsa_SidType type;
- char *user_name = NULL;
- struct winbindd_domain *domain = NULL;
-
- domain = find_lookup_domain_from_sid(&s->user_sid);
- if (domain == NULL) {
- DEBUG(5, ("find_lookup_domain_from_sid(%s) failed\n",
- sid_string_dbg(&s->user_sid)));
- request_error(s->state);
- return;
- }
- winbindd_lookup_name_by_sid(s->state->mem_ctx, domain,
- &s->user_sid, &domain_name,
- &user_name, &type );
-
- /* If this still fails we are done. Just error out */
- if ( !user_name ) {
- DEBUG(5,("Could not obtain a name for SID %s\n",
- sid_string_dbg(&s->user_sid)));
- request_error(s->state);
- return;
- }
-
- fstrcpy( username, user_name );
- }
-
- strlower_m( username );
- s->username = talloc_strdup(s->state->mem_ctx, username);
-
- nt_status = normalize_name_map(s->state->mem_ctx, s->domain,
- s->username, &mapped_name);
-
- /* Basic removal of whitespace */
- if (NT_STATUS_IS_OK(nt_status)) {
- s->username = mapped_name;
- s->username_mapped = false;
- }
- /* Complete name replacement */
- else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) {
- s->username = mapped_name;
- s->username_mapped = true;
- }
- /* No change at all */
- else {
- s->username_mapped = false;
- }
-
- s->fullname = talloc_strdup(s->state->mem_ctx, full_name);
- s->homedir = talloc_strdup(s->state->mem_ctx, homedir);
- s->shell = talloc_strdup(s->state->mem_ctx, shell);
- s->gid = gid;
- sid_copy(&s->group_sid, &s->domain->sid);
- sid_append_rid(&s->group_sid, group_rid);
-
- winbindd_sid2uid_async(s->state->mem_ctx, &s->user_sid,
- getpwsid_sid2uid_recv, s);
-}
-
-static void getpwsid_sid2uid_recv(void *private_data, bool success, uid_t uid)
-{
- struct getpwsid_state *s =
- talloc_get_type_abort(private_data, struct getpwsid_state);
-
- if (!success) {
- DEBUG(5, ("Could not query uid for user %s\\%s\n",
- s->domain->name, s->username));
- request_error(s->state);
- return;
- }
-
- s->uid = uid;
- winbindd_sid2gid_async(s->state->mem_ctx, &s->group_sid,
- getpwsid_sid2gid_recv, s);
-}
-
-static void getpwsid_sid2gid_recv(void *private_data, bool success, gid_t gid)
-{
- struct getpwsid_state *s =
- talloc_get_type_abort(private_data, struct getpwsid_state);
- struct winbindd_pw *pw;
- fstring output_username;
-
- /* allow the nss backend to override the primary group ID.
- If the gid has already been set, then keep it.
- This makes me feel dirty. If the nss backend already
- gave us a gid, we don't really care whether the sid2gid()
- call worked or not. --jerry */
-
- if ( s->gid == (gid_t)-1 ) {
-
- if (!success) {
- DEBUG(5, ("Could not query gid for user %s\\%s\n",
- s->domain->name, s->username));
- goto failed;
- }
-
- /* take what the sid2gid() call gave us */
- s->gid = gid;
- }
-
- pw = &s->state->response->data.pw;
- pw->pw_uid = s->uid;
- pw->pw_gid = s->gid;
-
- /* allow username to be overridden by the alias mapping */
-
- if ( s->username_mapped ) {
- fstrcpy( output_username, s->username );
- } else {
- fill_domain_username(output_username, s->domain->name,
- s->username, True);
- }
-
- safe_strcpy(pw->pw_name, output_username, sizeof(pw->pw_name) - 1);
- safe_strcpy(pw->pw_gecos, s->fullname, sizeof(pw->pw_gecos) - 1);
-
- if (!fillup_pw_field(lp_template_homedir(), s->username,
- s->domain->name, pw->pw_uid, pw->pw_gid,
- s->homedir, pw->pw_dir)) {
- DEBUG(5, ("Could not compose homedir\n"));
- goto failed;
- }
-
- if (!fillup_pw_field(lp_template_shell(), s->username,
- s->domain->name, pw->pw_uid, pw->pw_gid,
- s->shell, pw->pw_shell)) {
- DEBUG(5, ("Could not compose shell\n"));
- goto failed;
- }
-
- /* Password - set to "*" as we can't generate anything useful here.
- Authentication can be done using the pam_winbind module. */
-
- safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1);
-
- request_ok(s->state);
- return;
-
- failed:
- request_error(s->state);
-}
-
-/* Return a password structure from a username. */
-
-static void getpwnam_name2sid_recv(void *private_data, bool success,
- const DOM_SID *sid, enum lsa_SidType type);
-
-void winbindd_getpwnam(struct winbindd_cli_state *state)
-{
- struct winbindd_domain *domain;
- fstring domname, username;
- char *mapped_user = NULL;
- char *domuser;
- NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
-
- domuser = state->request->data.username;
-
- /* Ensure null termination (it's an fstring) */
- domuser[sizeof(state->request->data.username)-1] = '\0';
-
- DEBUG(3, ("[%5lu]: getpwnam %s\n",
- (unsigned long)state->pid,
- domuser));
-
- nt_status = normalize_name_unmap(state->mem_ctx, domuser,
- &mapped_user);
-
- /* If we could not convert from an aliased name or a
- normalized name, then just use the original name */
-
- if (!NT_STATUS_IS_OK(nt_status) &&
- !NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED))
- {
- mapped_user = domuser;
- }
-
- if (!parse_domain_user(mapped_user, domname, username)) {
- DEBUG(5, ("Could not parse domain user: %s\n", domuser));
- request_error(state);
- return;
- }
-
- /* Get info for the domain */
-
- domain = find_domain_from_name_noinit(domname);
-
- if (domain == NULL) {
- DEBUG(7, ("could not find domain entry for domain %s. "
- "Using primary domain\n", domname));
- domain = find_our_domain();
- if (domain == NULL) {
- DEBUG(0, ("Cannot find my primary domain "
- "structure!\n"));
- request_error(state);
- return;
- }
- }
-
- if (strequal(domname, lp_workgroup()) &&
- lp_winbind_trusted_domains_only() ) {
- DEBUG(7,("winbindd_getpwnam: My domain -- "
- "rejecting getpwnam() for %s\\%s.\n",
- domname, username));
- request_error(state);
- return;
- }
-
- /* Get rid and name type from name. The following costs 1 packet */
-
- winbindd_lookupname_async(state->mem_ctx, domname, username,
- getpwnam_name2sid_recv, WINBINDD_GETPWNAM,
- state);
-}
-
-static void getpwnam_name2sid_recv(void *private_data, bool success,
- const DOM_SID *sid, enum lsa_SidType type)
-{
- struct winbindd_cli_state *state =
- (struct winbindd_cli_state *)private_data;
- fstring domname, username;
- char *domuser = state->request->data.username;
-
- if (!success) {
- DEBUG(5, ("Could not lookup name for user %s\n", domuser));
- request_error(state);
- return;
- }
-
- if ((type != SID_NAME_USER) && (type != SID_NAME_COMPUTER)) {
- DEBUG(5, ("%s is not a user\n", domuser));
- request_error(state);
- return;
- }
-
- if (parse_domain_user(domuser, domname, username)) {
- check_domain_trusted(domname, sid);
- }
-
- getpwsid_queryuser(state, sid);
-}
-
-static void getpwuid_recv(void *private_data, bool success, const char *sid)
-{
- struct winbindd_cli_state *state =
- (struct winbindd_cli_state *)private_data;
- DOM_SID user_sid;
-
- if (!success) {
- DEBUG(10,("uid2sid_recv: uid [%lu] to sid mapping failed\n.",
- (unsigned long)(state->request->data.uid)));
- request_error(state);
- return;
- }
-
- DEBUG(10,("uid2sid_recv: uid %lu has sid %s\n",
- (unsigned long)(state->request->data.uid), sid));
-
- if (!string_to_sid(&user_sid, sid)) {
- DEBUG(1,("uid2sid_recv: Could not convert sid %s "
- "from string\n,", sid));
- request_error(state);
- return;
- }
-
- getpwsid_queryuser(state, &user_sid);
-}
-
-/* Return a password structure given a uid number */
-void winbindd_getpwuid(struct winbindd_cli_state *state)
-{
- uid_t uid = state->request->data.uid;
-
- DEBUG(3, ("[%5lu]: getpwuid %lu\n",
- (unsigned long)state->pid,
- (unsigned long)uid));
-
- /* always query idmap via the async interface */
- /* if this turns to be too slow we will add here
- * a direct query to the cache */
- winbindd_uid2sid_async(state->mem_ctx, uid, getpwuid_recv, state);
-}
-
-/* Return a password structure given a sid */
-void winbindd_getpwsid(struct winbindd_cli_state *state)
-{
- DOM_SID sid;
-
- /* Ensure null termination */
- state->request->data.sid[sizeof(state->request->data.sid)-1]='\0';
-
- DEBUG(3, ("[%5lu]: getpwsid %s\n", (unsigned long)state->pid,
- state->request->data.sid));
-
- if (!string_to_sid(&sid, state->request->data.sid)) {
- DEBUG(5, ("%s not a SID\n", state->request->data.sid));
- request_error(state);
- return;
- }
-
- getpwsid_queryuser(state, &sid);
-}
-
/*
* set/get/endpwent functions
*/