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