80b618c4aa81fe022ea25ca47e89c3cca7d616cc
[metze/samba/wip.git] / source3 / winbindd / winbindd_getpwnam.c
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
23 struct 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
32 static void winbindd_getpwnam_lookupname_done(struct tevent_req *subreq);
33 static void winbindd_getpwnam_done(struct tevent_req *subreq);
34
35 struct tevent_req *winbindd_getpwnam_send(TALLOC_CTX *mem_ctx,
36                                           struct tevent_context *ev,
37                                           struct winbindd_request *request)
38 {
39         struct tevent_req *req, *subreq;
40         struct winbindd_getpwnam_state *state;
41         char *domuser, *mapped_user;
42         NTSTATUS status;
43
44         req = tevent_req_create(mem_ctx, &state,
45                                 struct winbindd_getpwnam_state);
46         if (req == NULL) {
47                 return NULL;
48         }
49         state->ev = ev;
50
51         /* Ensure null termination */
52         request->data.username[sizeof(request->data.username)-1]='\0';
53
54         DEBUG(3, ("getpwnam %s\n", request->data.username));
55
56         domuser = request->data.username;
57
58         status = normalize_name_unmap(state, domuser, &mapped_user);
59
60         if (NT_STATUS_IS_OK(status)
61             || NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
62                 /* normalize_name_unmapped did something */
63                 domuser = mapped_user;
64         }
65
66         if (!parse_domain_user(domuser, state->domname, state->username)) {
67                 DEBUG(5, ("Could not parse domain user: %s\n", domuser));
68                 tevent_req_nterror(req, NT_STATUS_INVALID_PARAMETER);
69                 return tevent_req_post(req, ev);
70         }
71
72         if (lp_winbind_trusted_domains_only()
73             && strequal(state->domname, lp_workgroup())) {
74                 DEBUG(7,("winbindd_getpwnam: My domain -- "
75                          "rejecting getpwnam() for %s\\%s.\n",
76                          state->domname, state->username));
77                 tevent_req_nterror(req, NT_STATUS_NO_SUCH_USER);
78                 return tevent_req_post(req, ev);
79         }
80
81         subreq = wb_lookupname_send(state, ev, state->domname, state->username,
82                                     LOOKUP_NAME_NO_NSS);
83         if (tevent_req_nomem(subreq, req)) {
84                 return tevent_req_post(req, ev);
85         }
86         tevent_req_set_callback(subreq, winbindd_getpwnam_lookupname_done,
87                                 req);
88         return req;
89 }
90
91 static void winbindd_getpwnam_lookupname_done(struct tevent_req *subreq)
92 {
93         struct tevent_req *req = tevent_req_callback_data(
94                 subreq, struct tevent_req);
95         struct winbindd_getpwnam_state *state = tevent_req_data(
96                 req, struct winbindd_getpwnam_state);
97         NTSTATUS status;
98
99         status = wb_lookupname_recv(subreq, &state->sid, &state->type);
100         TALLOC_FREE(subreq);
101         if (!NT_STATUS_IS_OK(status)) {
102                 tevent_req_nterror(req, status);
103                 return;
104         }
105
106         subreq = wb_getpwsid_send(state, state->ev, &state->sid, &state->pw);
107         if (tevent_req_nomem(subreq, req)) {
108                 return;
109         }
110         tevent_req_set_callback(subreq, winbindd_getpwnam_done, req);
111 }
112
113 static void winbindd_getpwnam_done(struct tevent_req *subreq)
114 {
115         struct tevent_req *req = tevent_req_callback_data(
116                 subreq, struct tevent_req);
117         NTSTATUS status;
118
119         status = wb_getpwsid_recv(subreq);
120         TALLOC_FREE(subreq);
121         if (!NT_STATUS_IS_OK(status)) {
122                 tevent_req_nterror(req, status);
123                 return;
124         }
125         tevent_req_done(req);
126 }
127
128 NTSTATUS winbindd_getpwnam_recv(struct tevent_req *req,
129                                 struct winbindd_response *response)
130 {
131         struct winbindd_getpwnam_state *state = tevent_req_data(
132                 req, struct winbindd_getpwnam_state);
133         NTSTATUS status;
134
135         if (tevent_req_is_nterror(req, &status)) {
136                 DEBUG(5, ("Could not convert sid %s: %s\n",
137                           sid_string_dbg(&state->sid), nt_errstr(status)));
138                 return status;
139         }
140         response->data.pw = state->pw;
141         return NT_STATUS_OK;
142 }