From 6cf3db91499ebd245b08997a319edf36cfee3365 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 28 Jul 2009 15:06:11 -0400 Subject: s3:winbind: Add NDR-based parent-child communication to winbind --- source3/winbindd/winbindd.h | 1 + source3/winbindd/winbindd_domain.c | 4 + source3/winbindd/winbindd_dual.c | 13 ++ source3/winbindd/winbindd_dual_ndr.c | 273 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 30 ++++ source3/winbindd/winbindd_idmap.c | 4 + source3/winbindd/winbindd_locator.c | 4 + source3/winbindd/winbindd_proto.h | 6 + 8 files changed, 335 insertions(+) create mode 100644 source3/winbindd/winbindd_dual_ndr.c create mode 100644 source3/winbindd/winbindd_dual_srv.c (limited to 'source3/winbindd') 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_domain.c b/source3/winbindd/winbindd_domain.c index 8c52df3e16..5ff2e16abb 100644 --- a/source3/winbindd/winbindd_domain.c +++ b/source3/winbindd/winbindd_domain.c @@ -121,6 +121,10 @@ static const struct winbindd_child_dispatch_table domain_dispatch_table[] = { .name = "CCACHE_NTLM_AUTH", .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 . +*/ + +/* + * 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..5d2d7f389d --- /dev/null +++ b/source3/winbindd/winbindd_dual_srv.c @@ -0,0 +1,30 @@ +/* + 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 . +*/ + +#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; +} 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 @@ -564,6 +564,10 @@ static const struct winbindd_child_dispatch_table idmap_dispatch_table[] = { .name = "ALLOCATE_GID", .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 @@ -164,6 +164,10 @@ static const struct winbindd_child_dispatch_table locator_dispatch_table[] = { .name = "DSGETDCNAME", .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_proto.h b/source3/winbindd/winbindd_proto.h index c9decf8cc4..f9ef776c5d 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -330,6 +330,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 */ @@ -594,4 +595,9 @@ 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); + #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 2d6589fb0243cb2b73615de1aaea38a3059c08ed Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Aug 2009 12:16:11 +0200 Subject: s3:winbind: Make wcache_sid_to_name externally visible --- source3/winbindd/winbindd_cache.c | 85 ++++++++++++++++++++------------------- source3/winbindd/winbindd_proto.h | 6 +++ 2 files changed, 49 insertions(+), 42 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index bec2a714c8..f273f2c8d6 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -1678,42 +1678,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; @@ -2625,36 +2648,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); } diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index f9ef776c5d..182534a1fa 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -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); -- cgit From bb359c780aee3fd7e1074db93a28c95590ae5d36 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 3 Aug 2009 23:44:46 +0200 Subject: s3:winbind: Add async wb_lookupsid --- source3/winbindd/wb_lookupsid.c | 132 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 24 +++++++ source3/winbindd/winbindd_proto.h | 7 ++ 3 files changed, 163 insertions(+) create mode 100644 source3/winbindd/wb_lookupsid.c (limited to 'source3/winbindd') 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 . +*/ + +#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/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 5d2d7f389d..b4e18c82c1 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -28,3 +28,27 @@ 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; +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 182534a1fa..172e143ba0 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -606,4 +606,11 @@ struct rpc_pipe_client *wbint_rpccli_create(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ -- cgit From fa59f9720d56ffaf07c13376118c452a4162f3df Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 06:57:13 -0400 Subject: s3:winbind: Convert WINBINDD_LOOKUPSID to the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_lookupsid.c | 101 ++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 7 +++ source3/winbindd/winbindd_sid.c | 42 -------------- 4 files changed, 110 insertions(+), 43 deletions(-) create mode 100644 source3/winbindd/winbindd_lookupsid.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 4b6ebd2c42..e76a0de30f 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -469,7 +469,6 @@ static struct winbindd_dispatch_table { /* SID related functions */ - { WINBINDD_LOOKUPSID, winbindd_lookupsid, "LOOKUPSID" }, { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" }, { WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" }, @@ -526,6 +525,8 @@ 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 }, { 0, NULL, NULL, NULL } }; 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 . +*/ + +#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_proto.h b/source3/winbindd/winbindd_proto.h index 172e143ba0..9d4c09283a 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -613,4 +613,11 @@ 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); + + #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index f8cf7db920..287dfb7f6b 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -27,48 +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. **/ -- cgit From 74b45ba46cbf58c1bf9ef89f5f88509065cd81d2 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 06:58:28 -0400 Subject: s3:winbind: Remove old version of WINBINDD_PING --- source3/winbindd/winbindd.c | 1 - source3/winbindd/winbindd_misc.c | 6 ------ 2 files changed, 7 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index e76a0de30f..867e9df8d9 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -487,7 +487,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" }, 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) -- cgit From f6554611ab90aa113a7579ce3a9fef765c19d98c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Aug 2009 00:10:46 +0200 Subject: s3:winbind: Make wcache_name_to_sid visible externally --- source3/winbindd/winbindd_cache.c | 79 ++++++++++++++++++--------------------- source3/winbindd/winbindd_proto.h | 5 +++ 2 files changed, 42 insertions(+), 42 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index f273f2c8d6..87594542cf 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 @@ -2666,46 +2685,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_proto.h b/source3/winbindd/winbindd_proto.h index 9d4c09283a..e76e0cde1f 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -166,6 +166,11 @@ 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); 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) ; -- cgit From a5416770776c0ade8518e8875d47097662b026a6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 07:22:34 -0400 Subject: s3:winbind: Add async wb_lookupname --- source3/winbindd/wb_lookupname.c | 104 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 13 +++++ source3/winbindd/winbindd_proto.h | 7 +++ 3 files changed, 124 insertions(+) create mode 100644 source3/winbindd/wb_lookupname.c (limited to 'source3/winbindd') 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 . +*/ + +#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/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index b4e18c82c1..568084fd54 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -52,3 +52,16 @@ NTSTATUS _wbint_LookupSid(pipes_struct *p, struct wbint_LookupSid *r) *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); +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index e76e0cde1f..2b493b2a67 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -624,5 +624,12 @@ struct tevent_req *winbindd_lookupsid_send(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 9c6f4cd12a3e62165782e34226888648649a0fef Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 07:29:03 -0400 Subject: s3:winbind: Convert WINBINDD_LOOKUPNAME to the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_lookupname.c | 110 +++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 5 ++ source3/winbindd/winbindd_sid.c | 60 ------------------ 4 files changed, 117 insertions(+), 61 deletions(-) create mode 100644 source3/winbindd/winbindd_lookupname.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 867e9df8d9..a5374a99f4 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -469,7 +469,6 @@ static struct winbindd_dispatch_table { /* SID related functions */ - { WINBINDD_LOOKUPNAME, winbindd_lookupname, "LOOKUPNAME" }, { WINBINDD_LOOKUPRIDS, winbindd_lookuprids, "LOOKUPRIDS" }, /* Lookup related functions */ @@ -526,6 +525,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { wb_ping_send, wb_ping_recv }, { WINBINDD_LOOKUPSID, "LOOKUPSID", winbindd_lookupsid_send, winbindd_lookupsid_recv }, + { WINBINDD_LOOKUPNAME, "LOOKUPNAME", + winbindd_lookupname_send, winbindd_lookupname_recv }, { 0, NULL, NULL, 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 . +*/ + +#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_proto.h b/source3/winbindd/winbindd_proto.h index 2b493b2a67..678a9231de 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -631,5 +631,10 @@ struct tevent_req *wb_lookupname_send(TALLOC_CTX *mem_ctx, 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); #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 287dfb7f6b..ee1ee2b6bb 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -27,66 +27,6 @@ /* Convert a string */ -/** - * 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; -- cgit 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 From fb7150f23b154fe53a91f3433ea33cf680d4fa93 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 13:33:56 -0400 Subject: s3:winbind: Convert WINBINDD_SID_TO_UID to the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_proto.h | 5 ++ source3/winbindd/winbindd_sid.c | 109 --------------------------------- source3/winbindd/winbindd_sid_to_uid.c | 94 ++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 110 deletions(-) create mode 100644 source3/winbindd/winbindd_sid_to_uid.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index a5374a99f4..1d91a608c4 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -473,7 +473,6 @@ static struct winbindd_dispatch_table { /* 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" }, @@ -527,6 +526,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { 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 }, { 0, NULL, NULL, NULL } }; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 2a07ae2d4d..e326f49559 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -642,6 +642,11 @@ struct tevent_req *wb_sid2uid_send(TALLOC_CTX *mem_ctx, 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); #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index ee1ee2b6bb..ae3d369846 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -55,115 +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.*/ 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 . +*/ + +#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; +} -- cgit From 153ae58d7d37daffc7c5547ef9174baf64f9aaa7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 13:38:52 -0400 Subject: s3:winbind: Add async wb_sid2gid --- source3/winbindd/wb_sid2gid.c | 170 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 14 +++ source3/winbindd/winbindd_proto.h | 4 + 3 files changed, 188 insertions(+) create mode 100644 source3/winbindd/wb_sid2gid.c (limited to 'source3/winbindd') 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 . +*/ + +#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/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 3f449d5cd3..670e53d0a9 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -79,3 +79,17 @@ NTSTATUS _wbint_Sid2Uid(pipes_struct *p, struct wbint_Sid2Uid *r) *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; +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index e326f49559..d26a85796d 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -648,5 +648,9 @@ struct tevent_req *winbindd_sid_to_uid_send(TALLOC_CTX *mem_ctx, 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); #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 5db561a608a11895d8a9a038a98a9fcc7c867d59 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 13:42:22 -0400 Subject: s3:winbind: Convert WINBINDD_SID_TO_GID the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_proto.h | 6 ++ source3/winbindd/winbindd_sid.c | 113 --------------------------------- source3/winbindd/winbindd_sid_to_gid.c | 94 +++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 114 deletions(-) create mode 100644 source3/winbindd/winbindd_sid_to_gid.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 1d91a608c4..0f320850d2 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -473,7 +473,6 @@ static struct winbindd_dispatch_table { /* Lookup related functions */ - { 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" }, @@ -528,6 +527,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { 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 }, { 0, NULL, NULL, NULL } }; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index d26a85796d..d17d47a0d7 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -653,4 +653,10 @@ struct tevent_req *wb_sid2gid_send(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index ae3d369846..718345b5e3 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -55,119 +55,6 @@ void winbindd_lookuprids(struct winbindd_cli_state *state) sendto_domain(state, domain); } -/* 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 = 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 . +*/ + +#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; +} -- cgit From 3eff8e93e283828afdb3413aec2dae5c01b101b3 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 13:52:39 -0400 Subject: s3:winbind: Add async wb_uid2sid --- source3/winbindd/wb_uid2sid.c | 119 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 12 ++++ source3/winbindd/winbindd_proto.h | 6 ++ 3 files changed, 137 insertions(+) create mode 100644 source3/winbindd/wb_uid2sid.c (limited to 'source3/winbindd') 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 . +*/ + +#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_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 670e53d0a9..bad9cd585a 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -93,3 +93,15 @@ NTSTATUS _wbint_Sid2Gid(pipes_struct *p, struct wbint_Sid2Gid *r) *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; +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index d17d47a0d7..e0a43f5094 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -659,4 +659,10 @@ struct tevent_req *winbindd_sid_to_gid_send(TALLOC_CTX *mem_ctx, 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); + + #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 9b369ffcf0f113871b00de4229432a74fe436834 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 14:07:44 -0400 Subject: s3:winbind: Convert WINBINDD_UID_TO_SID the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_proto.h | 6 +++ source3/winbindd/winbindd_sid.c | 58 ----------------------- source3/winbindd/winbindd_uid_to_sid.c | 87 ++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 59 deletions(-) create mode 100644 source3/winbindd/winbindd_uid_to_sid.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 0f320850d2..9af63ff32e 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -473,7 +473,6 @@ static struct winbindd_dispatch_table { /* Lookup related functions */ - { 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" }, @@ -529,6 +528,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { 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 }, { 0, NULL, NULL, NULL } }; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index e0a43f5094..f1fb7e0a87 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -664,5 +664,11 @@ struct tevent_req *wb_uid2sid_send(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 718345b5e3..654f352ba3 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -171,64 +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) 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 . +*/ + +#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; +} -- cgit From 292f3f896fa5bc381c88526fc73a6224b8d286f0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 14:19:03 -0400 Subject: s3:winbind: Add async wb_gid2sid --- source3/winbindd/wb_gid2sid.c | 119 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 12 ++++ source3/winbindd/winbindd_proto.h | 5 ++ 3 files changed, 136 insertions(+) create mode 100644 source3/winbindd/wb_gid2sid.c (limited to 'source3/winbindd') 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 . +*/ + +#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/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index bad9cd585a..35fecbd08e 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -105,3 +105,15 @@ NTSTATUS _wbint_Uid2Sid(pipes_struct *p, struct wbint_Uid2Sid *r) } 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; +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index f1fb7e0a87..d8bd984590 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -670,5 +670,10 @@ struct tevent_req *winbindd_uid_to_sid_send(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 10685b37d4dc16dc75c48c08937f003af4968a0c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 14:22:17 -0400 Subject: s3:winbind: Convert WINBINDD_GID_TO_SID the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_gid_to_sid.c | 87 ++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 6 +++ source3/winbindd/winbindd_sid.c | 58 ----------------------- 4 files changed, 95 insertions(+), 59 deletions(-) create mode 100644 source3/winbindd/winbindd_gid_to_sid.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 9af63ff32e..4425517385 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -473,7 +473,6 @@ static struct winbindd_dispatch_table { /* Lookup related functions */ - { 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" }, @@ -530,6 +529,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { 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 }, { 0, NULL, NULL, NULL } }; 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 . +*/ + +#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_proto.h b/source3/winbindd/winbindd_proto.h index d8bd984590..38d5200aae 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -675,5 +675,11 @@ struct tevent_req *wb_gid2sid_send(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_sid.c b/source3/winbindd/winbindd_sid.c index 654f352ba3..db000682ae 100644 --- a/source3/winbindd/winbindd_sid.c +++ b/source3/winbindd/winbindd_sid.c @@ -171,64 +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 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 ) { -- cgit From 360227a0feb443fbbcc420295d5666da5823685a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 1 Aug 2009 10:20:13 -0400 Subject: s3:winbind: Make wcache_query_user externally visible --- source3/winbindd/winbindd_cache.c | 65 ++++++++++++++++++++++++++------------- source3/winbindd/winbindd_proto.h | 4 +++ 2 files changed, 47 insertions(+), 22 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 87594542cf..270b9f310d 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -1939,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; @@ -1984,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 */ diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 38d5200aae..1f0d5b5d5b 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -171,6 +171,10 @@ NTSTATUS wcache_name_to_sid(struct winbindd_domain *domain, 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); 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) ; -- cgit From 7077492778dbda30e5f865ae1d0ab0237e00f54f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 15:23:13 -0400 Subject: s3:winbind: Add async wb_queryuser --- source3/winbindd/wb_queryuser.c | 121 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 27 ++++++++ source3/winbindd/winbindd_proto.h | 5 ++ 3 files changed, 153 insertions(+) create mode 100644 source3/winbindd/wb_queryuser.c (limited to 'source3/winbindd') 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 . +*/ + +#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/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 35fecbd08e..202cca4434 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -117,3 +117,30 @@ NTSTATUS _wbint_Gid2Sid(pipes_struct *p, struct wbint_Gid2Sid *r) } 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; +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 1f0d5b5d5b..5f93391363 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -685,5 +685,10 @@ struct tevent_req *winbindd_gid_to_sid_send(TALLOC_CTX *mem_ctx, 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); #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 0418d38bc80dc8680834875629a3df8e1734b885 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 15:31:49 -0400 Subject: s3:winbind: Make fillup_pw_field publically available --- source3/winbindd/winbindd_proto.h | 8 ++++++++ source3/winbindd/winbindd_user.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 5f93391363..bfcf315231 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -508,6 +508,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); diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index c445ef0bdc..884a396142 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, -- cgit From afc82444fd367e8b8541e4a41a86966a288ed2ef Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 15:32:11 -0400 Subject: s3:winbind: Add async wb_getpwsid --- source3/winbindd/wb_getpwsid.c | 223 ++++++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 6 + 2 files changed, 229 insertions(+) create mode 100644 source3/winbindd/wb_getpwsid.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/wb_getpwsid.c b/source3/winbindd/wb_getpwsid.c new file mode 100644 index 0000000000..a823ba3953 --- /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 . +*/ + +#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(), state->pw->pw_name, + 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_homedir(), state->pw->pw_name, + state->user_domain->name, state->pw->pw_uid, + state->pw->pw_gid, state->userinfo->homedir, + 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/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index bfcf315231..ef977bb3b0 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -699,4 +699,10 @@ struct tevent_req *wb_queryuser_send(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 9dc401a20ec608d4d8ae25fb4e81c462e9ced415 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 15:35:24 -0400 Subject: s3:winbind: Convert WINBINDD_GETPWSID to the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_getpwsid.c | 92 ++++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 6 +++ source3/winbindd/winbindd_user.c | 20 -------- 4 files changed, 100 insertions(+), 21 deletions(-) create mode 100644 source3/winbindd/winbindd_getpwsid.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 4425517385..77e073c7c3 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -429,7 +429,6 @@ static struct winbindd_dispatch_table { { 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" }, @@ -531,6 +530,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { 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 }, { 0, NULL, NULL, NULL } }; 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 . +*/ + +#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_proto.h b/source3/winbindd/winbindd_proto.h index ef977bb3b0..6dcfdcfbbd 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -705,4 +705,10 @@ struct tevent_req *wb_getpwsid_send(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 884a396142..b1591475ac 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -555,26 +555,6 @@ void winbindd_getpwuid(struct winbindd_cli_state *state) 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 */ -- cgit From 5bbb7a0d143b34b6a2a2c4adb1114120cddd74bf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 15:37:54 -0400 Subject: s3:winbind: Convert WINBINDD_GETPWNAM to the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_getpwnam.c | 142 +++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 7 ++ source3/winbindd/winbindd_user.c | 97 ------------------------ 4 files changed, 151 insertions(+), 98 deletions(-) create mode 100644 source3/winbindd/winbindd_getpwnam.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 77e073c7c3..3b8358be0c 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -427,7 +427,6 @@ static struct winbindd_dispatch_table { /* User functions */ - { WINBINDD_GETPWNAM, winbindd_getpwnam, "GETPWNAM" }, { WINBINDD_GETPWUID, winbindd_getpwuid, "GETPWUID" }, { WINBINDD_SETPWENT, winbindd_setpwent, "SETPWENT" }, @@ -532,6 +531,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { 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 }, { 0, NULL, NULL, NULL } }; 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 . +*/ + +#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_proto.h b/source3/winbindd/winbindd_proto.h index 6dcfdcfbbd..80a4f46b67 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -711,4 +711,11 @@ struct tevent_req *winbindd_getpwsid_send(TALLOC_CTX *mem_ctx, 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); + + #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index b1591475ac..4778289aa8 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -417,103 +417,6 @@ static void getpwsid_sid2gid_recv(void *private_data, bool success, gid_t gid) /* 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 = -- cgit From bd9d7f75e352985f1b0e0785f0ba94dea19d2601 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 15:41:40 -0400 Subject: s3:winbind: Convert WINBINDD_GETPWUID to the new API --- source3/winbindd/winbindd.c | 4 +- source3/winbindd/winbindd_getpwuid.c | 108 ++++++++++++++ source3/winbindd/winbindd_proto.h | 6 + source3/winbindd/winbindd_user.c | 263 ----------------------------------- 4 files changed, 116 insertions(+), 265 deletions(-) create mode 100644 source3/winbindd/winbindd_getpwuid.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 3b8358be0c..0e13516a71 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -427,8 +427,6 @@ static struct winbindd_dispatch_table { /* User functions */ - { WINBINDD_GETPWUID, winbindd_getpwuid, "GETPWUID" }, - { WINBINDD_SETPWENT, winbindd_setpwent, "SETPWENT" }, { WINBINDD_ENDPWENT, winbindd_endpwent, "ENDPWENT" }, { WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" }, @@ -533,6 +531,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { winbindd_getpwsid_send, winbindd_getpwsid_recv }, { WINBINDD_GETPWNAM, "GETPWNAM", winbindd_getpwnam_send, winbindd_getpwnam_recv }, + { WINBINDD_GETPWUID, "GETPWUID", + winbindd_getpwuid_send, winbindd_getpwuid_recv }, { 0, NULL, NULL, NULL } }; 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 . +*/ + +#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_proto.h b/source3/winbindd/winbindd_proto.h index 80a4f46b67..c155589954 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -717,5 +717,11 @@ struct tevent_req *winbindd_getpwnam_send(TALLOC_CTX *mem_ctx, 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); + #endif /* _WINBINDD_PROTO_H_ */ diff --git a/source3/winbindd/winbindd_user.c b/source3/winbindd/winbindd_user.c index 4778289aa8..240b0f524f 100644 --- a/source3/winbindd/winbindd_user.c +++ b/source3/winbindd/winbindd_user.c @@ -195,269 +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 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); -} - /* * set/get/endpwent functions */ -- cgit From ff3ce9016a43906df55a0922f0697c91d255de88 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Aug 2009 16:52:19 +0200 Subject: s3:winbind: Make wcache_lookup_useraliases available publically --- source3/winbindd/winbindd_cache.c | 107 ++++++++++++++++++++++++++------------ source3/winbindd/winbindd_proto.h | 4 ++ 2 files changed, 78 insertions(+), 33 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index 270b9f310d..ea3f00e6d8 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2122,58 +2122,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; itdb) - 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; istatus; @@ -2181,9 +2197,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; @@ -2193,6 +2229,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); diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index c155589954..08c08222a6 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -175,6 +175,10 @@ 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); 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) ; -- cgit From f09a95aaff4542df4225f3828a0d737497f0f2e8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Aug 2009 17:17:27 +0200 Subject: s3:winbind: Make parse_sidlist take a const char * --- source3/winbindd/winbindd_async.c | 15 +++++++++++---- source3/winbindd/winbindd_proto.h | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'source3/winbindd') 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_proto.h b/source3/winbindd/winbindd_proto.h index 08c08222a6..2202537777 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); -- cgit From ce42ea3ab8c69a3f650d4c9bc787e4805aad928d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 15:54:05 -0400 Subject: s3:winbind: Add async wb_lookupuseraliases --- source3/winbindd/wb_lookupuseraliases.c | 101 ++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 14 +++++ source3/winbindd/winbindd_proto.h | 7 +++ 3 files changed, 122 insertions(+) create mode 100644 source3/winbindd/wb_lookupuseraliases.c (limited to 'source3/winbindd') 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 . +*/ + +#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/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 202cca4434..1a8cbd9b92 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -144,3 +144,17 @@ NTSTATUS _wbint_QueryUser(pipes_struct *p, struct wbint_QueryUser *r) 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); +} diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 2202537777..8dda3f8c8f 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -726,6 +726,13 @@ struct tevent_req *winbindd_getpwuid_send(TALLOC_CTX *mem_ctx, 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); #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 592822786d0a26bdf283ca4621c0df6f7f671869 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 15:58:45 -0400 Subject: s3:winbind: Convert WINBINDD_GETSIDALIASES to the new API --- source3/winbindd/winbindd.c | 4 +- source3/winbindd/winbindd_getsidaliases.c | 137 ++++++++++++++++++++++++++++++ source3/winbindd/winbindd_group.c | 26 ------ source3/winbindd/winbindd_proto.h | 5 ++ 4 files changed, 144 insertions(+), 28 deletions(-) create mode 100644 source3/winbindd/winbindd_getsidaliases.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 0e13516a71..9d37a008ed 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -435,8 +435,6 @@ static struct winbindd_dispatch_table { { WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" }, { WINBINDD_GETUSERDOMGROUPS, winbindd_getuserdomgroups, "GETUSERDOMGROUPS" }, - { WINBINDD_GETSIDALIASES, winbindd_getsidaliases, - "LOOKUPUSERALIASES" }, /* Group functions */ @@ -533,6 +531,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { winbindd_getpwnam_send, winbindd_getpwnam_recv }, { WINBINDD_GETPWUID, "GETPWUID", winbindd_getpwuid_send, winbindd_getpwuid_recv }, + { WINBINDD_GETSIDALIASES, "GETSIDALIASES", + winbindd_getsidaliases_send, winbindd_getsidaliases_recv }, { 0, NULL, NULL, NULL } }; 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 . +*/ + +#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; inum_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_group.c b/source3/winbindd/winbindd_group.c index f78becb699..0d3db1d83f 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1887,32 +1887,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_proto.h b/source3/winbindd/winbindd_proto.h index 8dda3f8c8f..f008ecda19 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -733,6 +733,11 @@ struct tevent_req *wb_lookupuseraliases_send(TALLOC_CTX *mem_ctx, 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); #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 718a26fd29036cc200cdc1c320733eafe84d2337 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 2 Aug 2009 18:01:54 +0200 Subject: s3:winbind: Make wcache_lookup_usergroups externally visible --- source3/winbindd/winbindd_cache.c | 76 ++++++++++++++++++++++++--------------- source3/winbindd/winbindd_proto.h | 5 +++ 2 files changed, 52 insertions(+), 29 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd_cache.c b/source3/winbindd/winbindd_cache.c index ea3f00e6d8..5dfdc5ae29 100644 --- a/source3/winbindd/winbindd_cache.c +++ b/source3/winbindd/winbindd_cache.c @@ -2031,63 +2031,81 @@ static NTSTATUS query_user(struct winbindd_domain *domain, 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; istatus; - 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; diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index f008ecda19..fd67abbf6d 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -179,6 +179,11 @@ 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) ; -- cgit From 1dc1ac00512a28bdc025b00fbfa676b0f5b15751 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 16:07:01 -0400 Subject: s3:winbind: Add async wb_lookupusergroups --- source3/winbindd/wb_lookupusergroups.c | 99 ++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_dual_srv.c | 14 +++++ source3/winbindd/winbindd_proto.h | 7 +++ 3 files changed, 120 insertions(+) create mode 100644 source3/winbindd/wb_lookupusergroups.c (limited to 'source3/winbindd') 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 . +*/ + +#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/winbindd_dual_srv.c b/source3/winbindd/winbindd_dual_srv.c index 1a8cbd9b92..9be295ffdc 100644 --- a/source3/winbindd/winbindd_dual_srv.c +++ b/source3/winbindd/winbindd_dual_srv.c @@ -158,3 +158,17 @@ NTSTATUS _wbint_LookupUserAliases(pipes_struct *p, 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_proto.h b/source3/winbindd/winbindd_proto.h index fd67abbf6d..42acb9eea6 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -184,6 +184,7 @@ NTSTATUS wcache_lookup_usergroups(struct winbindd_domain *domain, 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) ; @@ -743,6 +744,12 @@ struct tevent_req *winbindd_getsidaliases_send(TALLOC_CTX *mem_ctx, 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); #endif /* _WINBINDD_PROTO_H_ */ -- cgit From fec380818ffdd7fba58e8dd591049c4b2428ab7d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 16:20:18 -0400 Subject: s3:winbind: Convert WINBINDD_GETUSERDOMGROUPS to the new API --- source3/winbindd/winbindd.c | 4 +- source3/winbindd/winbindd_getuserdomgroups.c | 121 +++++++++++++++++++++++++++ source3/winbindd/winbindd_group.c | 26 ------ source3/winbindd/winbindd_proto.h | 7 ++ 4 files changed, 130 insertions(+), 28 deletions(-) create mode 100644 source3/winbindd/winbindd_getuserdomgroups.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 9d37a008ed..1a5e958d38 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -433,8 +433,6 @@ static struct winbindd_dispatch_table { { WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" }, { WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" }, - { WINBINDD_GETUSERDOMGROUPS, winbindd_getuserdomgroups, - "GETUSERDOMGROUPS" }, /* Group functions */ @@ -533,6 +531,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { winbindd_getpwuid_send, winbindd_getpwuid_recv }, { WINBINDD_GETSIDALIASES, "GETSIDALIASES", winbindd_getsidaliases_send, winbindd_getsidaliases_recv }, + { WINBINDD_GETUSERDOMGROUPS, "GETUSERDOMGROUPS", + winbindd_getuserdomgroups_send, winbindd_getuserdomgroups_recv }, { 0, NULL, NULL, NULL } }; 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 . +*/ + +#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; inum_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_group.c b/source3/winbindd/winbindd_group.c index 0d3db1d83f..12067f553f 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -1815,32 +1815,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) { diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 42acb9eea6..ed416de954 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -751,5 +751,12 @@ struct tevent_req *wb_lookupusergroups_send(TALLOC_CTX *mem_ctx, 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); + + #endif /* _WINBINDD_PROTO_H_ */ -- cgit From 01ea26bf28ab697af03c7ebc3a1261c240fe1360 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 4 Aug 2009 16:22:42 -0400 Subject: s3:winbind: Add async wb_gettoken --- source3/winbindd/wb_gettoken.c | 218 ++++++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_proto.h | 5 + 2 files changed, 223 insertions(+) create mode 100644 source3/winbindd/wb_gettoken.c (limited to 'source3/winbindd') 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 . +*/ + +#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 Date: Tue, 4 Aug 2009 16:26:07 -0400 Subject: s3:winbind: Convert WINBINDD_GETGROUPS to the new API --- source3/winbindd/winbindd.c | 3 +- source3/winbindd/winbindd_getgroups.c | 222 ++++++++++++++++++++++++++++++++++ source3/winbindd/winbindd_group.c | 172 -------------------------- source3/winbindd/winbindd_proto.h | 5 + 4 files changed, 229 insertions(+), 173 deletions(-) create mode 100644 source3/winbindd/winbindd_getgroups.c (limited to 'source3/winbindd') diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 1a5e958d38..348816b39c 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -431,7 +431,6 @@ static struct winbindd_dispatch_table { { WINBINDD_ENDPWENT, winbindd_endpwent, "ENDPWENT" }, { WINBINDD_GETPWENT, winbindd_getpwent, "GETPWENT" }, - { WINBINDD_GETGROUPS, winbindd_getgroups, "GETGROUPS" }, { WINBINDD_GETUSERSIDS, winbindd_getusersids, "GETUSERSIDS" }, /* Group functions */ @@ -533,6 +532,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { 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_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 . +*/ + +#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_group.c b/source3/winbindd/winbindd_group.c index 12067f553f..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 diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index df6df12dc3..a9a374a532 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -761,6 +761,11 @@ struct tevent_req *wb_gettoken_send(TALLOC_CTX *mem_ctx, 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); -- cgit From b9fb8da59148f574b03e44748fca7800f940db7a Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Sat, 8 Aug 2009 06:10:37 +0800 Subject: s3: Fix nss info substitution Signed-off-by: Bo Yang --- source3/winbindd/wb_getpwsid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source3/winbindd') diff --git a/source3/winbindd/wb_getpwsid.c b/source3/winbindd/wb_getpwsid.c index a823ba3953..fc696cb9a1 100644 --- a/source3/winbindd/wb_getpwsid.c +++ b/source3/winbindd/wb_getpwsid.c @@ -191,7 +191,7 @@ static void wb_getpwsid_sid2gid_done(struct tevent_req *subreq) fstrcpy(state->pw->pw_passwd, "*"); fstrcpy(state->pw->pw_gecos, state->userinfo->full_name); - if (!fillup_pw_field(lp_template_homedir(), state->pw->pw_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)) { @@ -200,9 +200,9 @@ static void wb_getpwsid_sid2gid_done(struct tevent_req *subreq) return; } - if (!fillup_pw_field(lp_template_homedir(), state->pw->pw_name, + 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->homedir, + 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); -- cgit