From ea286fed7adf93311b0ca14c3ff1e7bac74a0b9b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 13:28:59 -0400 Subject: s3:winbind: Add async wb_sid2uid --- source3/winbindd/wb_sid2uid.c | 168 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 14 +++ source3/winbindd/winbindd_proto.h | 7 ++ 3 files changed, 189 insertions(+) create mode 100644 source3/winbindd/wb_sid2uid.c (limited to 'source3/winbindd') 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 . +*/ + +#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/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 568084fd54..3f449d5cd3 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -65,3 +65,17 @@ NTSTATUS _wbint_LookupName(pipes_struct *p, struct wbint_LookupName *r) 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; +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 678a9231de..2a07ae2d4d 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -637,4 +637,11 @@ struct tevent_req *winbindd_lookupname_send(TALLOC_CTX *mem_ctx, 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); + + + #endif /* _WINBINDD_PROTO_H_ */ -- cgit