1/* 2 Unix SMB/CIFS implementation. 3 async implementation of WINBINDD_GETPWNAM 4 Copyright (C) Volker Lendecke 2009 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include "includes.h" 21#include "winbindd.h" 22 23struct winbindd_getpwnam_state { 24 struct tevent_context *ev; 25 fstring domname; 26 fstring username; 27 struct dom_sid sid; 28 enum lsa_SidType type; 29 struct winbindd_pw pw; 30}; 31 32static void winbindd_getpwnam_lookupname_done(struct tevent_req *subreq); 33static void winbindd_getpwnam_done(struct tevent_req *subreq); 34 35struct tevent_req *winbindd_getpwnam_send(TALLOC_CTX *mem_ctx, 36 struct tevent_context *ev, 37 struct winbindd_cli_state *cli, 38 struct winbindd_request *request) 39{ 40 struct tevent_req *req, *subreq; 41 struct winbindd_getpwnam_state *state; 42 char *domuser, *mapped_user; 43 NTSTATUS status; 44 45 req = tevent_req_create(mem_ctx, &state, 46 struct winbindd_getpwnam_state); 47 if (req == NULL) { 48 return NULL; 49 } 50 state->ev = ev; 51 52 /* Ensure null termination */ 53 request->data.username[sizeof(request->data.username)-1]='\0'; 54 55 DEBUG(3, ("getpwnam %s\n", request->data.username)); 56 57 domuser = request->data.username; 58 59 status = normalize_name_unmap(state, domuser, &mapped_user); 60 61 if (NT_STATUS_IS_OK(status) 62 || NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) { 63 /* normalize_name_unmapped did something */ 64 domuser = mapped_user; 65 } 66 67 if (!parse_domain_user(domuser, state->domname, state->username)) { 68 DEBUG(5, ("Could not parse domain user: %s\n", domuser)); 69 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER); 70 return tevent_req_post(req, ev); 71 } 72 73 if (lp_winbind_trusted_domains_only() 74 && strequal(state->domname, lp_workgroup())) { 75 DEBUG(7,("winbindd_getpwnam: My domain -- " 76 "rejecting getpwnam() for %s\\%s.\n", 77 state->domname, state->username)); 78 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER); 79 return tevent_req_post(req, ev); 80 } 81 82 subreq = wb_lookupname_send(state, ev, state->domname, state->username, 83 LOOKUP_NAME_NO_NSS); 84 if (tevent_req_nomem(subreq, req)) { 85 return tevent_req_post(req, ev); 86 } 87 tevent_req_set_callback(subreq, winbindd_getpwnam_lookupname_done, 88 req); 89 return req; 90} 91 92static void winbindd_getpwnam_lookupname_done(struct tevent_req *subreq) 93{ 94 struct tevent_req *req = tevent_req_callback_data( 95 subreq, struct tevent_req); 96 struct winbindd_getpwnam_state *state = tevent_req_data( 97 req, struct winbindd_getpwnam_state); 98 NTSTATUS status; 99 100 status = wb_lookupname_recv(subreq, &state->sid, &state->type); 101 TALLOC_FREE(subreq); 102 if (!NT_STATUS_IS_OK(status)) { 103 tevent_req_nterror(req, status); 104 return; 105 } 106 107 subreq = wb_getpwsid_send(state, state->ev, &state->sid, &state->pw); 108 if (tevent_req_nomem(subreq, req)) { 109 return; 110 } 111 tevent_req_set_callback(subreq, winbindd_getpwnam_done, req); 112} 113 114static void winbindd_getpwnam_done(struct tevent_req *subreq) 115{ 116 struct tevent_req *req = tevent_req_callback_data( 117 subreq, struct tevent_req); 118 NTSTATUS status; 119 120 status = wb_getpwsid_recv(subreq); 121 TALLOC_FREE(subreq); 122 if (!NT_STATUS_IS_OK(status)) { 123 tevent_req_nterror(req, status); 124 return; 125 } 126 tevent_req_done(req); 127} 128 129NTSTATUS winbindd_getpwnam_recv(struct tevent_req *req, 130 struct winbindd_response *response) 131{ 132 struct winbindd_getpwnam_state *state = tevent_req_data( 133 req, struct winbindd_getpwnam_state); 134 NTSTATUS status; 135 136 if (tevent_req_is_nterror(req, &status)) { 137 DEBUG(5, ("Could not convert sid %s: %s\n", 138 sid_string_dbg(&state->sid), nt_errstr(status))); 139 return status; 140 } 141 response->data.pw = state->pw; 142 return NT_STATUS_OK; 143} 144