diff options
-rw-r--r-- | source3/Makefile.in | 1 | ||||
-rw-r--r-- | source3/winbindd/winbindd.c | 3 | ||||
-rw-r--r-- | source3/winbindd/winbindd_getgrnam.c | 190 | ||||
-rw-r--r-- | source3/winbindd/winbindd_group.c | 252 | ||||
-rw-r--r-- | source3/winbindd/winbindd_proto.h | 6 |
5 files changed, 199 insertions, 253 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index d96dc2aaf1..f1fac93d5b 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -1183,6 +1183,7 @@ WINBINDD_OBJ1 = \ winbindd/winbindd_getgroups.o \ winbindd/winbindd_show_sequence.o \ winbindd/winbindd_getgrgid.o \ + winbindd/winbindd_getgrnam.o \ auth/token_util.o \ ../nsswitch/libwbclient/wb_reqtrans.o \ smbd/connection.o diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index bbcfede030..554cb0a30a 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -435,7 +435,6 @@ static struct winbindd_dispatch_table { /* Group functions */ - { WINBINDD_GETGRNAM, winbindd_getgrnam, "GETGRNAM" }, { WINBINDD_SETGRENT, winbindd_setgrent, "SETGRENT" }, { WINBINDD_ENDGRENT, winbindd_endgrent, "ENDGRENT" }, { WINBINDD_GETGRENT, winbindd_getgrent, "GETGRENT" }, @@ -536,6 +535,8 @@ static struct winbindd_async_dispatch_table async_nonpriv_table[] = { winbindd_show_sequence_send, winbindd_show_sequence_recv }, { WINBINDD_GETGRGID, "GETGRGID", winbindd_getgrgid_send, winbindd_getgrgid_recv }, + { WINBINDD_GETGRNAM, "GETGRNAM", + winbindd_getgrnam_send, winbindd_getgrnam_recv }, { 0, NULL, NULL, NULL } }; diff --git a/source3/winbindd/winbindd_getgrnam.c b/source3/winbindd/winbindd_getgrnam.c new file mode 100644 index 0000000000..85e60a2757 --- /dev/null +++ b/source3/winbindd/winbindd_getgrnam.c @@ -0,0 +1,190 @@ +/* + Unix SMB/CIFS implementation. + async implementation of WINBINDD_GETGRNAM + Copyright (C) Volker Lendecke 2009 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "winbindd.h" + +struct winbindd_getgrnam_state { + struct tevent_context *ev; + fstring name_domain, name_group; + struct dom_sid sid; + const char *domname; + const char *name; + gid_t gid; + struct talloc_dict *members; +}; + +static void winbindd_getgrnam_lookupsid_done(struct tevent_req *subreq); +static void winbindd_getgrnam_done(struct tevent_req *subreq); + +struct tevent_req *winbindd_getgrnam_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct winbindd_request *request) +{ + struct tevent_req *req, *subreq; + struct winbindd_getgrnam_state *state; + struct winbindd_domain *domain; + char *tmp; + NTSTATUS nt_status; + + req = tevent_req_create(mem_ctx, &state, + struct winbindd_getgrnam_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + + /* Ensure null termination */ + request->data.groupname[sizeof(request->data.groupname)-1]='\0'; + + DEBUG(3, ("getgrnam %s\n", request->data.groupname)); + + nt_status = normalize_name_unmap(state, request->data.groupname, &tmp); + /* If we didn't map anything in the above call, just reset the + tmp pointer to the original string */ + if (!NT_STATUS_IS_OK(nt_status) && + !NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) + { + tmp = request->data.groupname; + } + + /* Parse domain and groupname */ + + parse_domain_user(tmp, state->name_domain, state->name_group); + + /* if no domain or our local domain and no local tdb group, default to + * our local domain for aliases */ + + if ( !*(state->name_domain) || strequal(state->name_domain, + get_global_sam_name()) ) { + fstrcpy(state->name_domain, get_global_sam_name()); + } + + /* Get info for the domain */ + + domain = find_domain_from_name_noinit(state->name_domain); + if (domain == NULL) { + DEBUG(3, ("could not get domain sid for domain %s\n", + state->name_domain)); + tevent_req_nterror(req, NT_STATUS_NO_SUCH_GROUP); + return tevent_req_post(req, ev); + } + + /* should we deal with users for our domain? */ + + if ( lp_winbind_trusted_domains_only() && domain->primary) { + DEBUG(7,("winbindd_getgrnam: My domain -- rejecting " + "getgrnam() for %s\\%s.\n", state->name_domain, + state->name_group)); + tevent_req_nterror(req, NT_STATUS_NO_SUCH_GROUP); + return tevent_req_post(req, ev); + } + + subreq = wb_lookupname_send(state, ev, domain->name, state->name_group, + 0); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(subreq, winbindd_getgrnam_lookupsid_done, + req); + return req; +} + +static void winbindd_getgrnam_lookupsid_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct winbindd_getgrnam_state *state = tevent_req_data( + req, struct winbindd_getgrnam_state); + enum lsa_SidType type; + NTSTATUS status; + + status = wb_lookupname_recv(subreq, &state->sid, &type); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + + if ( (type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) ) { + DEBUG(5,("getgrnam_recv: not a group!\n")); + tevent_req_nterror(req, NT_STATUS_NO_SUCH_GROUP); + return; + } + + subreq = wb_getgrsid_send(state, state->ev, &state->sid, + lp_winbind_expand_groups()); + if (tevent_req_nomem(subreq, req)) { + return; + } + tevent_req_set_callback(subreq, winbindd_getgrnam_done, req); +} + +static void winbindd_getgrnam_done(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct winbindd_getgrnam_state *state = tevent_req_data( + req, struct winbindd_getgrnam_state); + NTSTATUS status; + + status = wb_getgrsid_recv(subreq, state, &state->domname, &state->name, + &state->gid, &state->members); + TALLOC_FREE(subreq); + if (!NT_STATUS_IS_OK(status)) { + tevent_req_nterror(req, status); + return; + } + tevent_req_done(req); +} + +NTSTATUS winbindd_getgrnam_recv(struct tevent_req *req, + struct winbindd_response *response) +{ + struct winbindd_getgrnam_state *state = tevent_req_data( + req, struct winbindd_getgrnam_state); + NTSTATUS status; + int num_members; + char *buf; + + 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; + } + + if (!fill_grent(talloc_tos(), &response->data.gr, state->domname, + state->name, state->gid)) { + DEBUG(5, ("fill_grent failed\n")); + return NT_STATUS_NO_MEMORY; + } + + status = winbindd_print_groupmembers(state->members, response, + &num_members, &buf); + + response->data.gr.num_gr_mem = (uint32)num_members; + + /* Group membership lives at start of extra data */ + + response->data.gr.gr_mem_ofs = 0; + response->extra_data.data = buf; + response->length += talloc_get_size(response->extra_data.data); + + return NT_STATUS_OK; +} diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index f33b52f83f..6520c43f2f 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -755,258 +755,6 @@ done: return result; } -static void winbindd_getgrsid(struct winbindd_cli_state *state, DOM_SID group_sid); - -static void getgrnam_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; - - if (!success) { - DEBUG(5,("getgrnam_recv: lookupname failed!\n")); - request_error(state); - return; - } - - if ( (type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) ) { - DEBUG(5,("getgrnam_recv: not a group!\n")); - request_error(state); - return; - } - - winbindd_getgrsid( state, *sid ); -} - - -/* Return a group structure from a group name */ - -void winbindd_getgrnam(struct winbindd_cli_state *state) -{ - struct winbindd_domain *domain; - fstring name_domain, name_group; - char *tmp; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - - /* Ensure null termination */ - state->request->data.groupname[sizeof(state->request->data.groupname)-1]='\0'; - - DEBUG(3, ("[%5lu]: getgrnam %s\n", (unsigned long)state->pid, - state->request->data.groupname)); - - nt_status = normalize_name_unmap(state->mem_ctx, - state->request->data.groupname, - &tmp); - /* If we didn't map anything in the above call, just reset the - tmp pointer to the original string */ - if (!NT_STATUS_IS_OK(nt_status) && - !NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) - { - tmp = state->request->data.groupname; - } - - /* Parse domain and groupname */ - - memset(name_group, 0, sizeof(name_group)); - - name_domain[0] = '\0'; - name_group[0] = '\0'; - - parse_domain_user(tmp, name_domain, name_group); - - /* if no domain or our local domain and no local tdb group, default to - * our local domain for aliases */ - - if ( !*name_domain || strequal(name_domain, get_global_sam_name()) ) { - fstrcpy(name_domain, get_global_sam_name()); - } - - /* Get info for the domain */ - - if ((domain = find_domain_from_name_noinit(name_domain)) == NULL) { - DEBUG(3, ("could not get domain sid for domain %s\n", - name_domain)); - request_error(state); - return; - } - /* should we deal with users for our domain? */ - - if ( lp_winbind_trusted_domains_only() && domain->primary) { - DEBUG(7,("winbindd_getgrnam: My domain -- rejecting " - "getgrnam() for %s\\%s.\n", name_domain, name_group)); - request_error(state); - return; - } - - /* Get rid and name type from name */ - - fstrcpy( name_group, tmp ); - - winbindd_lookupname_async( state->mem_ctx, domain->name, name_group, - getgrnam_recv, WINBINDD_GETGRNAM, state ); -} - -struct getgrsid_state { - struct winbindd_cli_state *state; - struct winbindd_domain *domain; - char *group_name; - enum lsa_SidType group_type; - uid_t gid; - DOM_SID group_sid; -}; - -static void getgrsid_sid2gid_recv(void *private_data, bool success, gid_t gid) -{ - struct getgrsid_state *s = - (struct getgrsid_state *)private_data; - struct winbindd_domain *domain; - size_t gr_mem_len; - size_t num_gr_mem; - char *gr_mem; - fstring dom_name, group_name; - - if (!success) { - DEBUG(5,("getgrsid_sid2gid_recv: sid2gid failed!\n")); - request_error(s->state); - return; - } - - s->gid = gid; - - if ( !parse_domain_user( s->group_name, dom_name, group_name ) ) { - DEBUG(5,("getgrsid_sid2gid_recv: parse_domain_user() failed!\n")); - request_error(s->state); - return; - } - - - /* Fill in group structure */ - - if ( (domain = find_domain_from_name_noinit(dom_name)) == NULL ) { - DEBUG(1,("Can't find domain from name (%s)\n", dom_name)); - request_error(s->state); - return; - } - - if (!fill_grent(s->state->mem_ctx, &s->state->response->data.gr, - dom_name, group_name, gid) || - !fill_grent_mem(domain, s->state, &s->group_sid, s->group_type, - &num_gr_mem, &gr_mem, &gr_mem_len)) - { - request_error(s->state); - return; - } - - s->state->response->data.gr.num_gr_mem = (uint32)num_gr_mem; - - /* Group membership lives at start of extra data */ - - s->state->response->data.gr.gr_mem_ofs = 0; - - s->state->response->length += gr_mem_len; - s->state->response->extra_data.data = talloc_memdup( - s->state->mem_ctx, gr_mem, gr_mem_len); - if (s->state->response->extra_data.data == NULL) { - request_error(s->state); - return; - } - - request_ok(s->state); -} - -static void getgrsid_lookupsid_recv( void *private_data, bool success, - const char *dom_name, const char *name, - enum lsa_SidType name_type ) -{ - struct getgrsid_state *s = (struct getgrsid_state *)private_data; - char *mapped_name = NULL; - fstring raw_name; - NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; - - if (!success) { - DEBUG(5,("getgrsid_lookupsid_recv: lookupsid failed!\n")); - request_error(s->state); - return; - } - - /* either it's a domain group, a domain local group, or a - local group in an internal domain */ - - if ( !( (name_type==SID_NAME_DOM_GRP) || - ((name_type==SID_NAME_ALIAS) && - (s->domain->primary || s->domain->internal)) ) ) - { - DEBUG(1, ("name '%s\\%s' is not a local or domain group: %d\n", - dom_name, name, name_type)); - request_error(s->state); - return; - } - - /* normalize the name and ensure that we have the DOM\name - coming out of here */ - - fstrcpy(raw_name, name); - - nt_status = normalize_name_unmap(s->state->mem_ctx, raw_name, - &mapped_name); - - /* basic whitespace reversal */ - if (NT_STATUS_IS_OK(nt_status)) { - s->group_name = talloc_asprintf(s->state->mem_ctx, - "%s%c%s", - dom_name, - *lp_winbind_separator(), - mapped_name); - } - /* mapped from alias */ - else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_FILE_RENAMED)) { - s->group_name = mapped_name; - } - /* no mapping at all. use original string */ - else { - s->group_name = talloc_asprintf(s->state->mem_ctx, - "%s%c%s", - dom_name, - *lp_winbind_separator(), - raw_name); - } - - if (s->group_name == NULL) { - DEBUG(1, ("getgrsid_lookupsid_recv: group_name is NULL!\n")); - request_error(s->state); - return; - } - - s->group_type = name_type; - - winbindd_sid2gid_async(s->state->mem_ctx, &s->group_sid, - getgrsid_sid2gid_recv, s); -} - -static void winbindd_getgrsid( struct winbindd_cli_state *state, const DOM_SID group_sid ) -{ - struct getgrsid_state *s; - - if ( (s = TALLOC_ZERO_P(state->mem_ctx, struct getgrsid_state)) == NULL ) { - DEBUG(0, ("talloc failed\n")); - request_error(state); - return; - } - - s->state = state; - - if ( (s->domain = find_domain_from_sid_noinit(&group_sid)) == NULL ) { - DEBUG(3, ("Could not find domain for sid %s\n", - sid_string_dbg(&group_sid))); - request_error(state); - return; - } - - sid_copy(&s->group_sid, &group_sid); - - winbindd_lookupsid_async( s->state->mem_ctx, &group_sid, - getgrsid_lookupsid_recv, s ); -} - /* * set/get/endgrent functions */ diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index f68cc2ec40..d462d8a6e1 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -817,4 +817,10 @@ struct tevent_req *winbindd_getgrgid_send(TALLOC_CTX *mem_ctx, NTSTATUS winbindd_getgrgid_recv(struct tevent_req *req, struct winbindd_response *response); +struct tevent_req *winbindd_getgrnam_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct winbindd_request *request); +NTSTATUS winbindd_getgrnam_recv(struct tevent_req *req, + struct winbindd_response *response); + #endif /* _WINBINDD_PROTO_H_ */ |