libwbclient: Fix wbcListUsers against too small num_entries
[nivanova/samba-autobuild/.git] / nsswitch / libwbclient / wbc_sid_async.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Winbind client API
5
6    Copyright (C) 2009,2010 Kai Blin  <kai@samba.org>
7
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Lesser General Public
10    License as published by the Free Software Foundation; either
11    version 3 of the License, or (at your option) any later version.
12
13    This library is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    Library General Public License for more details.
17
18    You should have received a copy of the GNU Lesser General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /* Required Headers */
23
24 #include "replace.h"
25 #include "libwbclient.h"
26 #include "../winbind_client.h"
27 #include "wbc_async.h"
28
29 struct wbc_lookup_name_state {
30         struct winbindd_request req;
31         struct wb_context *wb_ctx;
32         struct wbcDomainSid *sid;
33         enum wbcSidType name_type;
34 };
35
36 static void wbcLookupName_done(struct tevent_req *subreq);
37
38 /**
39  * @brief Request a conversion of a domaind and name to a domain sid
40  *
41  * @param mem_ctx       talloc context to allocate the request from
42  * @param ev            tevent context to use for async operation
43  * @param wb_ctx        winbind context to use
44  * @param *domain       Pointer to the domain to be resolved
45  * @param *name         Pointer to the name to be resolved
46  *
47  * @return tevent_req on success, NULL on error
48  **/
49
50 struct tevent_req *wbcLookupName_send(TALLOC_CTX *mem_ctx,
51                                       struct tevent_context *ev,
52                                       struct wb_context *wb_ctx,
53                                       const char *domain,
54                                       const char *name)
55 {
56         struct tevent_req *req, *subreq;
57         struct wbc_lookup_name_state *state;
58
59         req = tevent_req_create(mem_ctx, &state, struct wbc_lookup_name_state);
60         if (req == NULL) {
61                 return NULL;
62         }
63
64         ZERO_STRUCT(state->req);
65
66         state->req.cmd = WINBINDD_LOOKUPNAME;
67         strncpy(state->req.data.name.dom_name, domain,
68                 sizeof(state->req.data.name.dom_name)-1);
69         strncpy(state->req.data.name.name, name,
70                 sizeof(state->req.data.name.name)-1);
71         state->wb_ctx = wb_ctx;
72
73
74         subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
75         if (tevent_req_nomem(subreq, req)) {
76                 return tevent_req_post(req, ev);
77         }
78
79         tevent_req_set_callback(subreq, wbcLookupName_done, req);
80         return req;
81 }
82
83 static void wbcLookupName_done(struct tevent_req *subreq)
84 {
85         struct tevent_req *req = tevent_req_callback_data(
86                         subreq, struct tevent_req);
87         struct wbc_lookup_name_state *state = tevent_req_data(
88                         req, struct wbc_lookup_name_state);
89         struct winbindd_response *resp;
90         wbcErr wbc_status;
91
92         wbc_status = wb_trans_recv(subreq, state, &resp);
93         TALLOC_FREE(subreq);
94         if (!WBC_ERROR_IS_OK(wbc_status)) {
95                 tevent_req_error(req, wbc_status);
96                 return;
97         }
98
99         state->sid = talloc(state, struct wbcDomainSid);
100         if (tevent_req_nomem(state->sid, req)) {
101                 return;
102         }
103
104         wbc_status = wbcStringToSid(resp->data.sid.sid, state->sid);
105         if (!WBC_ERROR_IS_OK(wbc_status)) {
106                 wbcDebug(state->wb_ctx, WBC_DEBUG_ERROR,
107                          "wbcStringToSid returned %s!\n",
108                          wbcErrorString(wbc_status));
109                 tevent_req_error(req, wbc_status);
110                 return;
111         }
112
113         state->name_type = (enum wbcSidType)resp->data.sid.type;
114
115         TALLOC_FREE(resp);
116
117         tevent_req_done(req);
118 }
119
120 /**
121  * @brief Receive a conversion a SID to a domain and name
122  *
123  * @param *
124  * @param *pname        Resolved User or group name
125  * @param *pname_type   Pointer to the resolved SID type
126  *
127  * @return #wbcErr
128  */
129
130 wbcErr wbcLookupName_recv(struct tevent_req *req,
131                           struct wbcDomainSid *sid,
132                           enum wbcSidType *name_type)
133 {
134         struct wbc_lookup_name_state *state = tevent_req_data(
135                         req, struct wbc_lookup_name_state);
136         wbcErr wbc_status = WBC_ERR_SUCCESS;
137
138         if (!sid || !name_type) {
139                 wbcDebug(state->wb_ctx, WBC_DEBUG_TRACE,
140                 "Sid is %p, name_type is %p\n", sid, name_type);
141                 wbc_status = WBC_ERR_INVALID_PARAM;
142                 goto failed;
143         }
144
145         if (tevent_req_is_wbcerr(req, &wbc_status)) {
146                 goto failed;
147         }
148
149         memcpy(sid, state->sid, sizeof(struct wbcDomainSid));
150         *name_type = state->name_type;
151
152 failed:
153         tevent_req_received(req);
154         return wbc_status;
155 }
156
157
158 struct wbc_lookup_sid_state {
159         struct winbindd_request req;
160         char *domain;
161         char *name;
162         enum wbcSidType name_type;
163 };
164
165 static void wbcLookupSid_done(struct tevent_req *subreq);
166
167 /**
168  * @brief Request a conversion of a SID to a domain and name
169  *
170  * @param mem_ctx       talloc context to allocate the request from
171  * @param ev            tevent context to use for async operation
172  * @param wb_ctx        winbind context to use
173  * @param *sid          Pointer to the domain SID to be resolved
174  *
175  * @return tevent_req on success, NULL on error
176  **/
177
178 struct tevent_req *wbcLookupSid_send(TALLOC_CTX *mem_ctx,
179                                      struct tevent_context *ev,
180                                      struct wb_context *wb_ctx,
181                                      const struct wbcDomainSid *sid)
182 {
183         struct tevent_req *req, *subreq;
184         struct wbc_lookup_sid_state *state;
185         char *sid_string;
186         wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
187
188         req = tevent_req_create(mem_ctx, &state, struct wbc_lookup_sid_state);
189         if (req == NULL) {
190                 return NULL;
191         }
192
193         ZERO_STRUCT(state->req);
194
195         state->req.cmd = WINBINDD_LOOKUPSID;
196         wbc_status = wbcSidToString(sid, &sid_string);
197         if (!WBC_ERROR_IS_OK(wbc_status)) {
198                 tevent_req_error(req, wbc_status);
199                 return tevent_req_post(req, ev);
200         }
201         strncpy(state->req.data.sid, sid_string, sizeof(state->req.data.sid)-1);
202         wbcFreeMemory(sid_string);
203
204         subreq = wb_trans_send(state, ev, wb_ctx, false, &state->req);
205         if (tevent_req_nomem(subreq, req)) {
206                 return tevent_req_post(req, ev);
207         }
208
209         tevent_req_set_callback(subreq, wbcLookupSid_done, req);
210         return req;
211 }
212
213 static void wbcLookupSid_done(struct tevent_req *subreq)
214 {
215         struct tevent_req *req = tevent_req_callback_data(
216                         subreq, struct tevent_req);
217         struct wbc_lookup_sid_state *state = tevent_req_data(
218                         req, struct wbc_lookup_sid_state);
219         struct winbindd_response *resp;
220         wbcErr wbc_status;
221
222         wbc_status = wb_trans_recv(subreq, state, &resp);
223         TALLOC_FREE(subreq);
224         if (!WBC_ERROR_IS_OK(wbc_status)) {
225                 tevent_req_error(req, wbc_status);
226                 return;
227         }
228         state->domain = talloc_strdup(state, resp->data.name.dom_name);
229         if (tevent_req_nomem(state->domain, req)) {
230                 return;
231         }
232
233         state->name   = talloc_strdup(state, resp->data.name.name);
234         if (tevent_req_nomem(state->name, req)) {
235                 return;
236         }
237
238         state->name_type = (enum wbcSidType)resp->data.name.type;
239
240         TALLOC_FREE(resp);
241
242         tevent_req_done(req);
243 }
244
245 /**
246  * @brief Receive a conversion a SID to a domain and name
247  *
248  * @param *mem_ctx,     talloc context to move results to
249  * @param *pdomain      Resolved Domain name (possibly "")
250  * @param *pname        Resolved User or group name
251  * @param *pname_type   Pointer to the resolved SID type
252  *
253  * @return #wbcErr
254  */
255
256 wbcErr wbcLookupSid_recv(struct tevent_req *req,
257                          TALLOC_CTX *mem_ctx,
258                          char **pdomain,
259                          char **pname,
260                          enum wbcSidType *pname_type)
261 {
262         struct wbc_lookup_sid_state *state = tevent_req_data(
263                         req, struct wbc_lookup_sid_state);
264         wbcErr wbc_status;
265
266         if (tevent_req_is_wbcerr(req, &wbc_status)) {
267                 tevent_req_received(req);
268                 return wbc_status;
269         }
270
271         if (pdomain != NULL) {
272                 *pdomain = talloc_steal(mem_ctx, state->domain);
273         }
274
275         if (pname != NULL) {
276                 *pname   = talloc_steal(mem_ctx, state->name);
277         }
278
279         if (pname_type != NULL) {
280                 *pname_type = state->name_type;
281         }
282
283         tevent_req_received(req);
284         return WBC_ERR_SUCCESS;
285 }