s3: Remove unused winbindd_lookupname_async
[samba.git] / source3 / winbindd / winbindd_async.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Async helpers for blocking functions
5
6    Copyright (C) Volker Lendecke 2005
7    Copyright (C) Gerald Carter 2006
8
9    The helpers always consist of three functions: 
10
11    * A request setup function that takes the necessary parameters together
12      with a continuation function that is to be called upon completion
13
14    * A private continuation function that is internal only. This is to be
15      called by the lower-level functions in do_async(). Its only task is to
16      properly call the continuation function named above.
17
18    * A worker function that is called inside the appropriate child process.
19
20    This program is free software; you can redistribute it and/or modify
21    it under the terms of the GNU General Public License as published by
22    the Free Software Foundation; either version 3 of the License, or
23    (at your option) any later version.
24
25    This program is distributed in the hope that it will be useful,
26    but WITHOUT ANY WARRANTY; without even the implied warranty of
27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28    GNU General Public License for more details.
29
30    You should have received a copy of the GNU General Public License
31    along with this program.  If not, see <http://www.gnu.org/licenses/>.
32 */
33
34 #include "includes.h"
35 #include "winbindd.h"
36
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_WINBIND
39
40 struct do_async_state {
41         TALLOC_CTX *mem_ctx;
42         struct winbindd_request request;
43         struct winbindd_response response;
44         void (*cont)(TALLOC_CTX *mem_ctx,
45                      bool success,
46                      struct winbindd_response *response,
47                      void *c, void *private_data);
48         void *c, *private_data;
49 };
50
51 static void do_async_recv(void *private_data, bool success)
52 {
53         struct do_async_state *state =
54                 talloc_get_type_abort(private_data, struct do_async_state);
55
56         state->cont(state->mem_ctx, success, &state->response,
57                     state->c, state->private_data);
58 }
59
60 void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child,
61               const struct winbindd_request *request,
62               void (*cont)(TALLOC_CTX *mem_ctx, bool success,
63                            struct winbindd_response *response,
64                            void *c, void *private_data),
65               void *c, void *private_data)
66 {
67         struct do_async_state *state;
68
69         state = TALLOC_ZERO_P(mem_ctx, struct do_async_state);
70         if (state == NULL) {
71                 DEBUG(0, ("talloc failed\n"));
72                 cont(mem_ctx, False, NULL, c, private_data);
73                 return;
74         }
75
76         state->mem_ctx = mem_ctx;
77         state->request = *request;
78         state->request.length = sizeof(state->request);
79         state->cont = cont;
80         state->c = c;
81         state->private_data = private_data;
82
83         async_request(mem_ctx, child, &state->request,
84                       &state->response, do_async_recv, state);
85 }
86
87 static void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
88                             const struct winbindd_request *request,
89                             void (*cont)(TALLOC_CTX *mem_ctx, bool success,
90                                          struct winbindd_response *response,
91                                          void *c, void *private_data),
92                             void *c, void *private_data)
93 {
94         struct do_async_state *state;
95
96         state = TALLOC_ZERO_P(mem_ctx, struct do_async_state);
97         if (state == NULL) {
98                 DEBUG(0, ("talloc failed\n"));
99                 cont(mem_ctx, False, NULL, c, private_data);
100                 return;
101         }
102
103         state->mem_ctx = mem_ctx;
104         state->request = *request;
105         state->request.length = sizeof(state->request);
106         state->cont = cont;
107         state->c = c;
108         state->private_data = private_data;
109
110         async_domain_request(mem_ctx, domain, &state->request,
111                              &state->response, do_async_recv, state);
112 }
113
114 enum winbindd_result winbindd_dual_lookupsid(struct winbindd_domain *domain,
115                                              struct winbindd_cli_state *state)
116 {
117         enum lsa_SidType type;
118         DOM_SID sid;
119         char *name;
120         char *dom_name;
121
122         /* Ensure null termination */
123         state->request->data.sid[sizeof(state->request->data.sid)-1]='\0';
124
125         DEBUG(3, ("[%5lu]: lookupsid %s\n", (unsigned long)state->pid, 
126                   state->request->data.sid));
127
128         /* Lookup sid from PDC using lsa_lookup_sids() */
129
130         if (!string_to_sid(&sid, state->request->data.sid)) {
131                 DEBUG(5, ("%s not a SID\n", state->request->data.sid));
132                 return WINBINDD_ERROR;
133         }
134
135         /* Lookup the sid */
136
137         if (!winbindd_lookup_name_by_sid(state->mem_ctx, domain, &sid, 
138                                          &dom_name, &name, &type)) 
139         {
140                 TALLOC_FREE(dom_name);
141                 TALLOC_FREE(name);
142                 return WINBINDD_ERROR;
143         }
144
145         fstrcpy(state->response->data.name.dom_name, dom_name);
146         fstrcpy(state->response->data.name.name, name);
147         state->response->data.name.type = type;
148
149         TALLOC_FREE(dom_name);
150         TALLOC_FREE(name);
151         return WINBINDD_OK;
152 }
153
154 enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain,
155                                               struct winbindd_cli_state *state)
156 {
157         enum lsa_SidType type;
158         char *name_domain, *name_user;
159         DOM_SID sid;
160         char *p;
161
162         /* Ensure null termination */
163         state->request->data.name.dom_name[sizeof(state->request->data.name.dom_name)-1]='\0';
164
165         /* Ensure null termination */
166         state->request->data.name.name[sizeof(state->request->data.name.name)-1]='\0';
167
168         /* cope with the name being a fully qualified name */
169         p = strstr(state->request->data.name.name, lp_winbind_separator());
170         if (p) {
171                 *p = 0;
172                 name_domain = state->request->data.name.name;
173                 name_user = p+1;
174         } else {
175                 name_domain = state->request->data.name.dom_name;
176                 name_user = state->request->data.name.name;
177         }
178
179         DEBUG(3, ("[%5lu]: lookupname %s%s%s\n", (unsigned long)state->pid,
180                   name_domain, lp_winbind_separator(), name_user));
181
182         /* Lookup name from DC using lsa_lookup_names() */
183         if (!winbindd_lookup_sid_by_name(state->mem_ctx, state->request->original_cmd, domain, name_domain,
184                                          name_user, &sid, &type)) {
185                 return WINBINDD_ERROR;
186         }
187
188         sid_to_fstring(state->response->data.sid.sid, &sid);
189         state->response->data.sid.type = type;
190
191         return WINBINDD_OK;
192 }
193
194 bool print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids,
195                    size_t num_sids, char **result, ssize_t *len)
196 {
197         size_t i;
198         size_t buflen = 0;
199
200         *len = 0;
201         *result = NULL;
202         for (i=0; i<num_sids; i++) {
203                 fstring tmp;
204                 sprintf_append(mem_ctx, result, len, &buflen,
205                                "%s\n", sid_to_fstring(tmp, &sids[i]));
206         }
207
208         if ((num_sids != 0) && (*result == NULL)) {
209                 return False;
210         }
211
212         return True;
213 }
214
215 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
216                    DOM_SID **sids, size_t *num_sids)
217 {
218         const char *p, *q;
219
220         p = sidstr;
221         if (p == NULL)
222                 return False;
223
224         while (p[0] != '\0') {
225                 fstring tmp;
226                 size_t sidlen;
227                 DOM_SID sid;
228                 q = strchr(p, '\n');
229                 if (q == NULL) {
230                         DEBUG(0, ("Got invalid sidstr: %s\n", p));
231                         return False;
232                 }
233                 sidlen = PTR_DIFF(q, p);
234                 if (sidlen >= sizeof(tmp)-1) {
235                         return false;
236                 }
237                 memcpy(tmp, p, sidlen);
238                 tmp[sidlen] = '\0';
239                 q += 1;
240                 if (!string_to_sid(&sid, tmp)) {
241                         DEBUG(0, ("Could not parse sid %s\n", p));
242                         return False;
243                 }
244                 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
245                                                       num_sids)))
246                 {
247                         return False;
248                 }
249                 p = q;
250         }
251         return True;
252 }
253
254 static void getsidaliases_recv(TALLOC_CTX *mem_ctx, bool success,
255                                struct winbindd_response *response,
256                                void *c, void *private_data)
257 {
258         void (*cont)(void *priv, bool succ,
259                      DOM_SID *aliases, size_t num_aliases) =
260                 (void (*)(void *, bool, DOM_SID *, size_t))c;
261         char *aliases_str;
262         DOM_SID *sids = NULL;
263         size_t num_sids = 0;
264
265         if (!success) {
266                 DEBUG(5, ("Could not trigger getsidaliases\n"));
267                 cont(private_data, success, NULL, 0);
268                 return;
269         }
270
271         if (response->result != WINBINDD_OK) {
272                 DEBUG(5, ("getsidaliases returned an error\n"));
273                 cont(private_data, False, NULL, 0);
274                 return;
275         }
276
277         aliases_str = (char *)response->extra_data.data;
278
279         if (aliases_str == NULL) {
280                 DEBUG(10, ("getsidaliases return 0 SIDs\n"));
281                 cont(private_data, True, NULL, 0);
282                 return;
283         }
284
285         if (!parse_sidlist(mem_ctx, aliases_str, &sids, &num_sids)) {
286                 DEBUG(0, ("Could not parse sids\n"));
287                 cont(private_data, False, NULL, 0);
288                 return;
289         }
290
291         cont(private_data, True, sids, num_sids);
292 }
293
294 void winbindd_getsidaliases_async(struct winbindd_domain *domain,
295                                   TALLOC_CTX *mem_ctx,
296                                   const DOM_SID *sids, size_t num_sids,
297                                   void (*cont)(void *private_data,
298                                                bool success,
299                                                const DOM_SID *aliases,
300                                                size_t num_aliases),
301                                   void *private_data)
302 {
303         struct winbindd_request request;
304         char *sidstr = NULL;
305         ssize_t len;
306
307         if (num_sids == 0) {
308                 cont(private_data, True, NULL, 0);
309                 return;
310         }
311
312         if (!print_sidlist(mem_ctx, sids, num_sids, &sidstr, &len)) {
313                 cont(private_data, False, NULL, 0);
314                 return;
315         }
316
317         ZERO_STRUCT(request);
318         request.cmd = WINBINDD_DUAL_GETSIDALIASES;
319         request.extra_len = len;
320         request.extra_data.data = sidstr;
321
322         do_async_domain(mem_ctx, domain, &request, getsidaliases_recv,
323                         (void *)cont, private_data);
324 }
325
326 static void query_user_recv(TALLOC_CTX *mem_ctx, bool success,
327                             struct winbindd_response *response,
328                             void *c, void *private_data)
329 {
330         void (*cont)(void *priv, bool succ, const char *acct_name,
331                      const char *full_name, const char *homedir, 
332                      const char *shell, uint32 gid, uint32 group_rid) =
333                 (void (*)(void *, bool, const char *, const char *,
334                           const char *, const char *, uint32, uint32))c;
335
336         if (!success) {
337                 DEBUG(5, ("Could not trigger query_user\n"));
338                 cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
339                 return;
340         }
341
342         if (response->result != WINBINDD_OK) {
343                 DEBUG(5, ("query_user returned an error\n"));
344                 cont(private_data, False, NULL, NULL, NULL, NULL, -1, -1);
345                 return;
346         }
347
348         cont(private_data, True, response->data.user_info.acct_name,
349              response->data.user_info.full_name,
350              response->data.user_info.homedir,
351              response->data.user_info.shell,
352              response->data.user_info.primary_gid,
353              response->data.user_info.group_rid);
354 }
355
356 void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain,
357                       const DOM_SID *sid,
358                       void (*cont)(void *private_data, bool success,
359                                    const char *acct_name,
360                                    const char *full_name,
361                                    const char *homedir,
362                                    const char *shell,
363                                    gid_t gid,
364                                    uint32 group_rid),
365                       void *private_data)
366 {
367         struct winbindd_request request;
368         ZERO_STRUCT(request);
369         request.cmd = WINBINDD_DUAL_USERINFO;
370         sid_to_fstring(request.data.sid, sid);
371         do_async_domain(mem_ctx, domain, &request, query_user_recv,
372                         (void *)cont, private_data);
373 }
374
375 enum winbindd_result winbindd_dual_ping(struct winbindd_domain *domain,
376                                         struct winbindd_cli_state *state)
377 {
378         return WINBINDD_OK;
379 }