s4 winbind: Implement a stubbed out version of WINBINDD_DOMAIN_INFO
[metze/samba/wip.git] / source4 / winbind / wb_samba3_cmd.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Main winbindd samba3 server routines
4
5    Copyright (C) Stefan Metzmacher      2005
6    Copyright (C) Volker Lendecke        2005
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
8    Copyright (C) Kai Blin               2009
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14    
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19    
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "winbind/wb_server.h"
26 #include "winbind/wb_async_helpers.h"
27 #include "param/param.h"
28 #include "winbind/wb_helper.h"
29 #include "libcli/composite/composite.h"
30 #include "version.h"
31 #include "librpc/gen_ndr/netlogon.h"
32 #include "libcli/security/security.h"
33 #include "auth/ntlm/pam_errors.h"
34 #include "auth/credentials/credentials.h"
35 #include "smbd/service_task.h"
36
37 /* 
38    Send off the reply to an async Samba3 query, handling filling in the PAM, NTSTATUS and string errors.
39 */
40
41 static void wbsrv_samba3_async_auth_epilogue(NTSTATUS status,
42                                              struct wbsrv_samba3_call *s3call)
43 {
44         struct winbindd_response *resp = &s3call->response;
45         if (!NT_STATUS_IS_OK(status)) {
46                 resp->result = WINBINDD_ERROR;
47         } else {
48                 resp->result = WINBINDD_OK;
49         }
50         
51         WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
52                                 nt_errstr(status));
53         WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
54                                 get_friendly_nt_error_msg(status));
55
56         resp->data.auth.pam_error = nt_status_to_pam(status);
57         resp->data.auth.nt_status = NT_STATUS_V(status);
58
59         wbsrv_samba3_send_reply(s3call);
60 }
61
62 /* 
63    Send of a generic reply to a Samba3 query
64 */
65
66 static void wbsrv_samba3_async_epilogue(NTSTATUS status,
67                                         struct wbsrv_samba3_call *s3call)
68 {
69         struct winbindd_response *resp = &s3call->response;
70         if (NT_STATUS_IS_OK(status)) {
71                 resp->result = WINBINDD_OK;
72         } else {
73                 resp->result = WINBINDD_ERROR;
74         }
75
76         wbsrv_samba3_send_reply(s3call);
77 }
78
79 /* 
80    Boilerplate commands, simple queries without network traffic 
81 */
82
83 NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
84 {
85         s3call->response.result                 = WINBINDD_OK;
86         s3call->response.data.interface_version = WINBIND_INTERFACE_VERSION;
87         return NT_STATUS_OK;
88 }
89
90 NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
91 {
92         s3call->response.result                 = WINBINDD_OK;
93         s3call->response.data.info.winbind_separator = *lp_winbind_separator(s3call->wbconn->lp_ctx);
94         WBSRV_SAMBA3_SET_STRING(s3call->response.data.info.samba_version,
95                                 SAMBA_VERSION_STRING);
96         return NT_STATUS_OK;
97 }
98
99 NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
100 {
101         s3call->response.result                 = WINBINDD_OK;
102         WBSRV_SAMBA3_SET_STRING(s3call->response.data.domain_name,
103                                 lp_workgroup(s3call->wbconn->lp_ctx));
104         return NT_STATUS_OK;
105 }
106
107 NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
108 {
109         s3call->response.result                 = WINBINDD_OK;
110         WBSRV_SAMBA3_SET_STRING(s3call->response.data.netbios_name,
111                                 lp_netbios_name(s3call->wbconn->lp_ctx));
112         return NT_STATUS_OK;
113 }
114
115 NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
116 {
117         const char *path = s3call->wbconn->listen_socket->service->priv_socket_path;
118         s3call->response.result          = WINBINDD_OK;
119         s3call->response.extra_data.data = discard_const(path);
120
121         s3call->response.length += strlen(path) + 1;
122         return NT_STATUS_OK;
123 }
124
125 NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
126 {
127         s3call->response.result                 = WINBINDD_OK;
128         return NT_STATUS_OK;
129 }
130
131 NTSTATUS wbsrv_samba3_domain_info(struct wbsrv_samba3_call *s3call)
132 {
133         DEBUG(0, ("wbsrv_samba3_domain_info called, stub\n"));
134         s3call->response.result = WINBINDD_OK;
135         fstrcpy(s3call->response.data.domain_info.name,
136                 s3call->request.domain_name);
137         fstrcpy(s3call->response.data.domain_info.alt_name,
138                 s3call->request.domain_name);
139         fstrcpy(s3call->response.data.domain_info.sid, "S-1-2-3-4");
140         s3call->response.data.domain_info.native_mode = false;
141         s3call->response.data.domain_info.active_directory = false;
142         s3call->response.data.domain_info.primary = false;
143
144         return NT_STATUS_OK;
145 }
146
147 /* Plaintext authentication 
148    
149    This interface is used by ntlm_auth in it's 'basic' authentication
150    mode, as well as by pam_winbind to authenticate users where we are
151    given a plaintext password.
152 */
153
154 static void check_machacc_recv(struct composite_context *ctx);
155
156 NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
157 {
158         NTSTATUS status;
159         struct cli_credentials *creds;
160         struct composite_context *ctx;
161         struct wbsrv_service *service =
162                 s3call->wbconn->listen_socket->service;
163
164         /* Create a credentials structure */
165         creds = cli_credentials_init(s3call);
166         if (creds == NULL) {
167                 return NT_STATUS_NO_MEMORY;
168         }
169
170         cli_credentials_set_conf(creds, service->task->lp_ctx);
171
172         /* Connect the machine account to the credentials */
173         status = cli_credentials_set_machine_account(creds, service->task->lp_ctx);
174         if (!NT_STATUS_IS_OK(status)) {
175                 talloc_free(creds);
176                 return status;
177         }
178
179         ctx = wb_cmd_pam_auth_send(s3call, service, creds);
180
181         if (!ctx) {
182                 talloc_free(creds);
183                 return NT_STATUS_NO_MEMORY;
184         }
185
186         ctx->async.fn = check_machacc_recv;
187         ctx->async.private_data = s3call;
188         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
189         return NT_STATUS_OK;
190 }
191
192 static void check_machacc_recv(struct composite_context *ctx)
193 {
194         struct wbsrv_samba3_call *s3call =
195                 talloc_get_type(ctx->async.private_data,
196                                 struct wbsrv_samba3_call);
197         NTSTATUS status;
198
199         status = wb_cmd_pam_auth_recv(ctx);
200
201         if (!NT_STATUS_IS_OK(status)) goto done;
202
203  done:
204         wbsrv_samba3_async_auth_epilogue(status, s3call);
205 }
206
207 /*
208   Find the name of a suitable domain controller, by query on the
209   netlogon pipe to the DC.  
210 */
211
212 static void getdcname_recv_dc(struct composite_context *ctx);
213
214 NTSTATUS wbsrv_samba3_getdcname(struct wbsrv_samba3_call *s3call)
215 {
216         struct composite_context *ctx;
217         struct wbsrv_service *service =
218                 s3call->wbconn->listen_socket->service;
219
220         DEBUG(5, ("wbsrv_samba3_getdcname called\n"));
221
222         ctx = wb_cmd_getdcname_send(s3call, service,
223                                     s3call->request.domain_name);
224         NT_STATUS_HAVE_NO_MEMORY(ctx);
225
226         ctx->async.fn = getdcname_recv_dc;
227         ctx->async.private_data = s3call;
228         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
229         return NT_STATUS_OK;
230 }
231
232 static void getdcname_recv_dc(struct composite_context *ctx)
233 {
234         struct wbsrv_samba3_call *s3call =
235                 talloc_get_type(ctx->async.private_data,
236                                 struct wbsrv_samba3_call);
237         const char *dcname;
238         NTSTATUS status;
239
240         status = wb_cmd_getdcname_recv(ctx, s3call, &dcname);
241         if (!NT_STATUS_IS_OK(status)) goto done;
242
243         s3call->response.result = WINBINDD_OK;
244         WBSRV_SAMBA3_SET_STRING(s3call->response.data.dc_name, dcname);
245
246  done:
247         wbsrv_samba3_async_epilogue(status, s3call);
248 }
249
250 /* 
251    Lookup a user's domain groups
252 */
253
254 static void userdomgroups_recv_groups(struct composite_context *ctx);
255
256 NTSTATUS wbsrv_samba3_userdomgroups(struct wbsrv_samba3_call *s3call)
257 {
258         struct composite_context *ctx;
259         struct dom_sid *sid;
260
261         DEBUG(5, ("wbsrv_samba3_userdomgroups called\n"));
262
263         sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
264         if (sid == NULL) {
265                 DEBUG(5, ("Could not parse sid %s\n",
266                           s3call->request.data.sid));
267                 return NT_STATUS_NO_MEMORY;
268         }
269
270         ctx = wb_cmd_userdomgroups_send(
271                 s3call, s3call->wbconn->listen_socket->service, sid);
272         NT_STATUS_HAVE_NO_MEMORY(ctx);
273
274         ctx->async.fn = userdomgroups_recv_groups;
275         ctx->async.private_data = s3call;
276         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
277         return NT_STATUS_OK;
278 }
279
280 static void userdomgroups_recv_groups(struct composite_context *ctx)
281 {
282         struct wbsrv_samba3_call *s3call =
283                 talloc_get_type(ctx->async.private_data,
284                                 struct wbsrv_samba3_call);
285         int i, num_sids;
286         struct dom_sid **sids;
287         char *sids_string;
288         NTSTATUS status;
289
290         status = wb_cmd_userdomgroups_recv(ctx, s3call, &num_sids, &sids);
291         if (!NT_STATUS_IS_OK(status)) goto done;
292
293         sids_string = talloc_strdup(s3call, "");
294         if (sids_string == NULL) {
295                 status = NT_STATUS_NO_MEMORY;
296                 goto done;
297         }
298
299         for (i=0; i<num_sids; i++) {
300                 sids_string = talloc_asprintf_append_buffer(
301                         sids_string, "%s\n", dom_sid_string(s3call, sids[i]));
302         }
303
304         if (sids_string == NULL) {
305                 status = NT_STATUS_NO_MEMORY;
306                 goto done;
307         }
308
309         s3call->response.result = WINBINDD_OK;
310         s3call->response.extra_data.data = sids_string;
311         s3call->response.length += strlen(sids_string)+1;
312         s3call->response.data.num_entries = num_sids;
313
314  done:
315         wbsrv_samba3_async_epilogue(status, s3call);
316 }
317
318 /* 
319    Lookup the list of SIDs for a user 
320 */
321 static void usersids_recv_sids(struct composite_context *ctx);
322
323 NTSTATUS wbsrv_samba3_usersids(struct wbsrv_samba3_call *s3call)
324 {
325         struct composite_context *ctx;
326         struct dom_sid *sid;
327
328         DEBUG(5, ("wbsrv_samba3_usersids called\n"));
329
330         sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
331         if (sid == NULL) {
332                 DEBUG(5, ("Could not parse sid %s\n",
333                           s3call->request.data.sid));
334                 return NT_STATUS_NO_MEMORY;
335         }
336
337         ctx = wb_cmd_usersids_send(
338                 s3call, s3call->wbconn->listen_socket->service, sid);
339         NT_STATUS_HAVE_NO_MEMORY(ctx);
340
341         ctx->async.fn = usersids_recv_sids;
342         ctx->async.private_data = s3call;
343         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
344         return NT_STATUS_OK;
345 }
346
347 static void usersids_recv_sids(struct composite_context *ctx)
348 {
349         struct wbsrv_samba3_call *s3call =
350                 talloc_get_type(ctx->async.private_data,
351                                 struct wbsrv_samba3_call);
352         int i, num_sids;
353         struct dom_sid **sids;
354         char *sids_string;
355         NTSTATUS status;
356
357         status = wb_cmd_usersids_recv(ctx, s3call, &num_sids, &sids);
358         if (!NT_STATUS_IS_OK(status)) goto done;
359
360         sids_string = talloc_strdup(s3call, "");
361         if (sids_string == NULL) {
362                 status = NT_STATUS_NO_MEMORY;
363                 goto done;
364         }
365
366         for (i=0; i<num_sids; i++) {
367                 sids_string = talloc_asprintf_append_buffer(
368                         sids_string, "%s\n", dom_sid_string(s3call, sids[i]));
369                 if (sids_string == NULL) {
370                         status = NT_STATUS_NO_MEMORY;
371                         goto done;
372                 }
373         }
374
375         s3call->response.result = WINBINDD_OK;
376         s3call->response.extra_data.data = sids_string;
377         s3call->response.length += strlen(sids_string);
378         s3call->response.data.num_entries = num_sids;
379
380         /* Hmmmm. Nasty protocol -- who invented the zeros between the
381          * SIDs? Hmmm. Could have been me -- vl */
382
383         while (*sids_string != '\0') {
384                 if ((*sids_string) == '\n') {
385                         *sids_string = '\0';
386                 }
387                 sids_string += 1;
388         }
389
390  done:
391         wbsrv_samba3_async_epilogue(status, s3call);
392 }
393
394 /* 
395    Lookup a DOMAIN\\user style name, and return a SID
396 */
397
398 static void lookupname_recv_sid(struct composite_context *ctx);
399
400 NTSTATUS wbsrv_samba3_lookupname(struct wbsrv_samba3_call *s3call)
401 {
402         struct composite_context *ctx;
403         struct wbsrv_service *service =
404                 s3call->wbconn->listen_socket->service;
405
406         DEBUG(5, ("wbsrv_samba3_lookupname called\n"));
407
408         ctx = wb_cmd_lookupname_send(s3call, service,
409                                      s3call->request.data.name.dom_name,
410                                      s3call->request.data.name.name);
411         NT_STATUS_HAVE_NO_MEMORY(ctx);
412
413         /* setup the callbacks */
414         ctx->async.fn = lookupname_recv_sid;
415         ctx->async.private_data = s3call;
416         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
417         return NT_STATUS_OK;
418 }
419
420 static void lookupname_recv_sid(struct composite_context *ctx)
421 {
422         struct wbsrv_samba3_call *s3call =
423                 talloc_get_type(ctx->async.private_data,
424                                 struct wbsrv_samba3_call);
425         struct wb_sid_object *sid;
426         NTSTATUS status;
427
428         status = wb_cmd_lookupname_recv(ctx, s3call, &sid);
429         if (!NT_STATUS_IS_OK(status)) goto done;
430
431         s3call->response.result = WINBINDD_OK;
432         s3call->response.data.sid.type = sid->type;
433         WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid,
434                                 dom_sid_string(s3call, sid->sid));
435
436  done:
437         wbsrv_samba3_async_epilogue(status, s3call);
438 }
439
440 /* 
441    Lookup a SID, and return a DOMAIN\\user style name
442 */
443
444 static void lookupsid_recv_name(struct composite_context *ctx);
445
446 NTSTATUS wbsrv_samba3_lookupsid(struct wbsrv_samba3_call *s3call)
447 {
448         struct composite_context *ctx;
449         struct wbsrv_service *service =
450                 s3call->wbconn->listen_socket->service;
451         struct dom_sid *sid;
452
453         DEBUG(5, ("wbsrv_samba3_lookupsid called\n"));
454
455         sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
456         if (sid == NULL) {
457                 DEBUG(5, ("Could not parse sid %s\n",
458                           s3call->request.data.sid));
459                 return NT_STATUS_NO_MEMORY;
460         }
461
462         ctx = wb_cmd_lookupsid_send(s3call, service, sid);
463         NT_STATUS_HAVE_NO_MEMORY(ctx);
464
465         /* setup the callbacks */
466         ctx->async.fn = lookupsid_recv_name;
467         ctx->async.private_data = s3call;
468         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
469         return NT_STATUS_OK;
470 }
471
472 static void lookupsid_recv_name(struct composite_context *ctx)
473 {
474         struct wbsrv_samba3_call *s3call =
475                 talloc_get_type(ctx->async.private_data,
476                                 struct wbsrv_samba3_call);
477         struct wb_sid_object *sid;
478         NTSTATUS status;
479
480         status = wb_cmd_lookupsid_recv(ctx, s3call, &sid);
481         if (!NT_STATUS_IS_OK(status)) goto done;
482
483         s3call->response.result = WINBINDD_OK;
484         s3call->response.data.name.type = sid->type;
485         WBSRV_SAMBA3_SET_STRING(s3call->response.data.name.dom_name,
486                                 sid->domain);
487         WBSRV_SAMBA3_SET_STRING(s3call->response.data.name.name, sid->name);
488
489  done:
490         wbsrv_samba3_async_epilogue(status, s3call);
491 }
492
493 /*
494   Challenge-response authentication.  This interface is used by
495   ntlm_auth and the smbd auth subsystem to pass NTLM authentication
496   requests along a common pipe to the domain controller.  
497
498   The return value (in the async reply) may include the 'info3'
499   (effectivly most things you would want to know about the user), or
500   the NT and LM session keys seperated.
501 */
502
503 static void pam_auth_crap_recv(struct composite_context *ctx);
504
505 NTSTATUS wbsrv_samba3_pam_auth_crap(struct wbsrv_samba3_call *s3call)
506 {
507         struct composite_context *ctx;
508         struct wbsrv_service *service =
509                 s3call->wbconn->listen_socket->service;
510         DATA_BLOB chal, nt_resp, lm_resp;
511
512         DEBUG(5, ("wbsrv_samba3_pam_auth_crap called\n"));
513
514         chal.data       = s3call->request.data.auth_crap.chal;
515         chal.length     = sizeof(s3call->request.data.auth_crap.chal);
516         nt_resp.data    = (uint8_t *)s3call->request.data.auth_crap.nt_resp;
517         nt_resp.length  = s3call->request.data.auth_crap.nt_resp_len;
518         lm_resp.data    = (uint8_t *)s3call->request.data.auth_crap.lm_resp;
519         lm_resp.length  = s3call->request.data.auth_crap.lm_resp_len;
520
521         ctx = wb_cmd_pam_auth_crap_send(
522                 s3call, service,
523                 s3call->request.data.auth_crap.logon_parameters,
524                 s3call->request.data.auth_crap.domain,
525                 s3call->request.data.auth_crap.user,
526                 s3call->request.data.auth_crap.workstation,
527                 chal, nt_resp, lm_resp);
528         NT_STATUS_HAVE_NO_MEMORY(ctx);
529
530         ctx->async.fn = pam_auth_crap_recv;
531         ctx->async.private_data = s3call;
532         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
533         return NT_STATUS_OK;
534 }
535
536 static void pam_auth_crap_recv(struct composite_context *ctx)
537 {
538         struct wbsrv_samba3_call *s3call =
539                 talloc_get_type(ctx->async.private_data,
540                                 struct wbsrv_samba3_call);
541         NTSTATUS status;
542         DATA_BLOB info3;
543         struct netr_UserSessionKey user_session_key;
544         struct netr_LMSessionKey lm_key;
545         char *unix_username;
546         
547         status = wb_cmd_pam_auth_crap_recv(ctx, s3call, &info3,
548                                            &user_session_key, &lm_key, &unix_username);
549         if (!NT_STATUS_IS_OK(status)) goto done;
550
551         if (s3call->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
552                 memcpy(s3call->response.data.auth.user_session_key, 
553                        &user_session_key.key,
554                        sizeof(s3call->response.data.auth.user_session_key));
555         }
556
557         if (s3call->request.flags & WBFLAG_PAM_INFO3_NDR) {
558                 s3call->response.extra_data.data = info3.data;
559                 s3call->response.length += info3.length;
560         }
561
562         if (s3call->request.flags & WBFLAG_PAM_LMKEY) {
563                 memcpy(s3call->response.data.auth.first_8_lm_hash, 
564                        lm_key.key,
565                        sizeof(s3call->response.data.auth.first_8_lm_hash));
566         }
567         
568         if (s3call->request.flags & WBFLAG_PAM_UNIX_NAME) {
569                 s3call->response.extra_data.data = unix_username;
570                 s3call->response.length += strlen(unix_username)+1;
571         }
572
573  done:
574         wbsrv_samba3_async_auth_epilogue(status, s3call);
575 }
576
577 /* Plaintext authentication 
578    
579    This interface is used by ntlm_auth in it's 'basic' authentication
580    mode, as well as by pam_winbind to authenticate users where we are
581    given a plaintext password.
582 */
583
584 static void pam_auth_recv(struct composite_context *ctx);
585
586 NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
587 {
588         struct composite_context *ctx;
589         struct wbsrv_service *service =
590                 s3call->wbconn->listen_socket->service;
591         struct cli_credentials *credentials;
592         char *user, *domain;
593
594         if (!wb_samba3_split_username(s3call, s3call->wbconn->lp_ctx,
595                                  s3call->request.data.auth.user,
596                                  &domain, &user)) {
597                 return NT_STATUS_NO_SUCH_USER;
598         }
599
600         credentials = cli_credentials_init(s3call);
601         if (!credentials) {
602                 return NT_STATUS_NO_MEMORY;
603         }
604         cli_credentials_set_conf(credentials, service->task->lp_ctx);
605         cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
606         cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
607
608         cli_credentials_set_password(credentials, s3call->request.data.auth.pass, CRED_SPECIFIED);
609
610         ctx = wb_cmd_pam_auth_send(s3call, service, credentials);
611         NT_STATUS_HAVE_NO_MEMORY(ctx);
612
613         ctx->async.fn = pam_auth_recv;
614         ctx->async.private_data = s3call;
615         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
616         return NT_STATUS_OK;
617 }
618
619 static void pam_auth_recv(struct composite_context *ctx)
620 {
621         struct wbsrv_samba3_call *s3call =
622                 talloc_get_type(ctx->async.private_data,
623                                 struct wbsrv_samba3_call);
624         NTSTATUS status;
625
626         status = wb_cmd_pam_auth_recv(ctx);
627
628         if (!NT_STATUS_IS_OK(status)) goto done;
629
630  done:
631         wbsrv_samba3_async_auth_epilogue(status, s3call);
632 }
633
634 /* 
635    List trusted domains
636 */
637
638 static void list_trustdom_recv_doms(struct composite_context *ctx);
639
640 NTSTATUS wbsrv_samba3_list_trustdom(struct wbsrv_samba3_call *s3call)
641 {
642         struct composite_context *ctx;
643         struct wbsrv_service *service =
644                 s3call->wbconn->listen_socket->service;
645
646         DEBUG(5, ("wbsrv_samba3_list_trustdom called\n"));
647
648         ctx = wb_cmd_list_trustdoms_send(s3call, service);
649         NT_STATUS_HAVE_NO_MEMORY(ctx);
650
651         ctx->async.fn = list_trustdom_recv_doms;
652         ctx->async.private_data = s3call;
653         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
654         return NT_STATUS_OK;
655 }
656
657 static void list_trustdom_recv_doms(struct composite_context *ctx)
658 {
659         struct wbsrv_samba3_call *s3call =
660                 talloc_get_type(ctx->async.private_data,
661                                 struct wbsrv_samba3_call);
662         int i, num_domains;
663         struct wb_dom_info **domains;
664         NTSTATUS status;
665         char *result;
666
667         status = wb_cmd_list_trustdoms_recv(ctx, s3call, &num_domains,
668                                             &domains);
669         if (!NT_STATUS_IS_OK(status)) goto done;
670
671         result = talloc_strdup(s3call, "");
672         if (result == NULL) {
673                 status = NT_STATUS_NO_MEMORY;
674                 goto done;
675         }
676
677         for (i=0; i<num_domains; i++) {
678                 result = talloc_asprintf_append_buffer(
679                         result, "%s\\%s\\%s",
680                         domains[i]->name, domains[i]->name,
681                         dom_sid_string(s3call, domains[i]->sid));
682         }
683
684         if (result == NULL) {
685                 status = NT_STATUS_NO_MEMORY;
686                 goto done;
687         }
688
689         s3call->response.result = WINBINDD_OK;
690         if (num_domains > 0) {
691                 s3call->response.extra_data.data = result;
692                 s3call->response.length += strlen(result)+1;
693         }
694
695  done:
696         wbsrv_samba3_async_epilogue(status, s3call);
697 }
698
699 /* list groups */
700 static void list_groups_recv(struct composite_context *ctx);
701
702 NTSTATUS wbsrv_samba3_list_groups(struct wbsrv_samba3_call *s3call)
703 {
704         struct composite_context *ctx;
705         struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
706
707         DEBUG(5, ("wbsrv_samba4_list_groups called\n"));
708
709         ctx = wb_cmd_list_groups_send(s3call, service,
710                                       s3call->request.domain_name);
711         NT_STATUS_HAVE_NO_MEMORY(ctx);
712
713         ctx->async.fn = list_groups_recv;
714         ctx->async.private_data = s3call;
715         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
716         return NT_STATUS_OK;
717 }
718
719 static void list_groups_recv(struct composite_context *ctx)
720 {
721         struct wbsrv_samba3_call *s3call = talloc_get_type_abort(
722                                                 ctx->async.private_data,
723                                                 struct wbsrv_samba3_call);
724         uint32_t extra_data_len;
725         char *extra_data;
726         NTSTATUS status;
727
728         DEBUG(5, ("list_groups_recv called\n"));
729
730         status = wb_cmd_list_groups_recv(ctx, s3call, &extra_data_len,
731                         &extra_data);
732
733         if (NT_STATUS_IS_OK(status)) {
734                 s3call->response.extra_data.data = extra_data;
735                 s3call->response.length += extra_data_len;
736                 if (extra_data) {
737                         s3call->response.length += 1;
738                 }
739         }
740
741         wbsrv_samba3_async_epilogue(status, s3call);
742 }
743
744 /* List users */
745
746 static void list_users_recv(struct composite_context *ctx);
747
748 NTSTATUS wbsrv_samba3_list_users(struct wbsrv_samba3_call *s3call)
749 {
750         struct composite_context *ctx;
751         struct wbsrv_service *service =
752                 s3call->wbconn->listen_socket->service;
753
754         DEBUG(5, ("wbsrv_samba3_list_users called\n"));
755
756         ctx = wb_cmd_list_users_send(s3call, service,
757                         s3call->request.domain_name);
758         NT_STATUS_HAVE_NO_MEMORY(ctx);
759
760         ctx->async.fn = list_users_recv;
761         ctx->async.private_data = s3call;
762         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
763         return NT_STATUS_OK;
764 }
765
766 static void list_users_recv(struct composite_context *ctx)
767 {
768         struct wbsrv_samba3_call *s3call =
769                 talloc_get_type(ctx->async.private_data,
770                                 struct wbsrv_samba3_call);
771         uint32_t extra_data_len;
772         char *extra_data;
773         NTSTATUS status;
774
775         DEBUG(5, ("list_users_recv called\n"));
776
777         status = wb_cmd_list_users_recv(ctx, s3call, &extra_data_len,
778                         &extra_data);
779
780         if (NT_STATUS_IS_OK(status)) {
781                 s3call->response.extra_data.data = extra_data;
782                 s3call->response.length += extra_data_len;
783                 if (extra_data) {
784                         s3call->response.length += 1;
785                 }
786         }
787
788         wbsrv_samba3_async_epilogue(status, s3call);
789 }
790
791 /* NSS calls */
792
793 static void getpwnam_recv(struct composite_context *ctx);
794
795 NTSTATUS wbsrv_samba3_getpwnam(struct wbsrv_samba3_call *s3call)
796 {
797         struct composite_context *ctx;
798         struct wbsrv_service *service =
799                 s3call->wbconn->listen_socket->service;
800
801         DEBUG(5, ("wbsrv_samba3_getpwnam called\n"));
802
803         ctx = wb_cmd_getpwnam_send(s3call, service,
804                         s3call->request.data.username);
805         NT_STATUS_HAVE_NO_MEMORY(ctx);
806
807         ctx->async.fn = getpwnam_recv;
808         ctx->async.private_data = s3call;
809         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
810         return NT_STATUS_OK;
811 }
812
813 static void getpwnam_recv(struct composite_context *ctx)
814 {
815         struct wbsrv_samba3_call *s3call =
816                 talloc_get_type(ctx->async.private_data,
817                                 struct wbsrv_samba3_call);
818         NTSTATUS status;
819         struct winbindd_pw *pw;
820
821         DEBUG(5, ("getpwnam_recv called\n"));
822
823         status = wb_cmd_getpwnam_recv(ctx, s3call, &pw);
824         if(NT_STATUS_IS_OK(status))
825                 s3call->response.data.pw = *pw;
826
827         wbsrv_samba3_async_epilogue(status, s3call);
828 }
829
830 static void getpwuid_recv(struct composite_context *ctx);
831
832 NTSTATUS wbsrv_samba3_getpwuid(struct wbsrv_samba3_call *s3call)
833 {
834         struct composite_context *ctx;
835         struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
836
837         DEBUG(5, ("wbsrv_samba3_getpwuid called\n"));
838
839         ctx = wb_cmd_getpwuid_send(s3call, service,
840                         s3call->request.data.uid);
841         NT_STATUS_HAVE_NO_MEMORY(ctx);
842
843         ctx->async.fn = getpwuid_recv;
844         ctx->async.private_data = s3call;
845         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
846         return NT_STATUS_OK;
847 }
848
849 static void getpwuid_recv(struct composite_context *ctx)
850 {
851         struct wbsrv_samba3_call *s3call =
852                 talloc_get_type(ctx->async.private_data,
853                                 struct wbsrv_samba3_call);
854         NTSTATUS status;
855         struct winbindd_pw *pw;
856
857         DEBUG(5, ("getpwuid_recv called\n"));
858
859         status = wb_cmd_getpwuid_recv(ctx, s3call, &pw);
860         if (NT_STATUS_IS_OK(status))
861                 s3call->response.data.pw = *pw;
862
863         wbsrv_samba3_async_epilogue(status, s3call);
864 }
865
866 static void setpwent_recv(struct composite_context *ctx);
867
868 NTSTATUS wbsrv_samba3_setpwent(struct wbsrv_samba3_call *s3call)
869 {
870         struct composite_context *ctx;
871         struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
872
873         DEBUG(5, ("wbsrv_samba3_setpwent called\n"));
874
875         ctx = wb_cmd_setpwent_send(s3call, service);
876         NT_STATUS_HAVE_NO_MEMORY(ctx);
877
878         ctx->async.fn = setpwent_recv;
879         ctx->async.private_data = s3call;
880         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
881         return NT_STATUS_OK;
882 }
883
884 static void setpwent_recv(struct composite_context *ctx)
885 {
886         struct wbsrv_samba3_call *s3call =
887                 talloc_get_type(ctx->async.private_data,
888                                 struct wbsrv_samba3_call);
889         NTSTATUS status;
890         struct wbsrv_pwent *pwent;
891
892         DEBUG(5, ("setpwent_recv called\n"));
893
894         status = wb_cmd_setpwent_recv(ctx, s3call->wbconn, &pwent);
895         if (NT_STATUS_IS_OK(status)) {
896                 s3call->wbconn->protocol_private_data = pwent;
897         }
898
899         wbsrv_samba3_async_epilogue(status, s3call);
900 }
901
902 static void getpwent_recv(struct composite_context *ctx);
903
904 NTSTATUS wbsrv_samba3_getpwent(struct wbsrv_samba3_call *s3call)
905 {
906         struct composite_context *ctx;
907         struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
908         struct wbsrv_pwent *pwent;
909
910         DEBUG(5, ("wbsrv_samba3_getpwent called\n"));
911
912         NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
913
914         pwent = talloc_get_type(s3call->wbconn->protocol_private_data,
915                         struct wbsrv_pwent);
916         NT_STATUS_HAVE_NO_MEMORY(pwent);
917
918         ctx = wb_cmd_getpwent_send(s3call, service, pwent,
919                         s3call->request.data.num_entries);
920         NT_STATUS_HAVE_NO_MEMORY(ctx);
921
922         ctx->async.fn = getpwent_recv;
923         ctx->async.private_data = s3call;
924         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
925         return NT_STATUS_OK;
926 }
927
928 static void getpwent_recv(struct composite_context *ctx)
929 {
930         struct wbsrv_samba3_call *s3call =
931                 talloc_get_type(ctx->async.private_data,
932                                 struct wbsrv_samba3_call);
933         NTSTATUS status;
934         struct winbindd_pw *pw;
935         uint32_t num_users;
936
937         DEBUG(5, ("getpwent_recv called\n"));
938
939         status = wb_cmd_getpwent_recv(ctx, s3call, &pw, &num_users);
940         if (NT_STATUS_IS_OK(status)) {
941                 uint32_t extra_len = sizeof(struct winbindd_pw) * num_users;
942
943                 s3call->response.data.num_entries = num_users;
944                 s3call->response.extra_data.data = pw;
945                 s3call->response.length += extra_len;
946         }
947
948         wbsrv_samba3_async_epilogue(status, s3call);
949 }
950
951 NTSTATUS wbsrv_samba3_endpwent(struct wbsrv_samba3_call *s3call)
952 {
953         struct wbsrv_pwent *pwent =
954                 talloc_get_type(s3call->wbconn->protocol_private_data,
955                                 struct wbsrv_pwent);
956         DEBUG(5, ("wbsrv_samba3_endpwent called\n"));
957
958         talloc_free(pwent);
959
960         s3call->wbconn->protocol_private_data = NULL;
961         s3call->response.result = WINBINDD_OK;
962         return NT_STATUS_OK;
963 }
964
965
966 static void getgrnam_recv(struct composite_context *ctx);
967
968 NTSTATUS wbsrv_samba3_getgrnam(struct wbsrv_samba3_call *s3call)
969 {
970         struct composite_context *ctx;
971         struct wbsrv_service *service =
972                 s3call->wbconn->listen_socket->service;
973
974         DEBUG(5, ("wbsrv_samba3_getgrnam called\n"));
975
976         ctx = wb_cmd_getgrnam_send(s3call, service,
977                         s3call->request.data.groupname);
978         NT_STATUS_HAVE_NO_MEMORY(ctx);
979
980         ctx->async.fn = getgrnam_recv;
981         ctx->async.private_data = s3call;
982         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
983         return NT_STATUS_OK;
984 }
985
986 static void getgrnam_recv(struct composite_context *ctx)
987 {
988         struct wbsrv_samba3_call *s3call =
989                 talloc_get_type(ctx->async.private_data,
990                                 struct wbsrv_samba3_call);
991         NTSTATUS status;
992         struct winbindd_gr *gr;
993
994         DEBUG(5, ("getgrnam_recv called\n"));
995
996         status = wb_cmd_getgrnam_recv(ctx, s3call, &gr);
997         if(NT_STATUS_IS_OK(status))
998                 s3call->response.data.gr = *gr;
999
1000         wbsrv_samba3_async_epilogue(status, s3call);
1001 }
1002
1003 static void getgrgid_recv(struct composite_context *ctx);
1004
1005 NTSTATUS wbsrv_samba3_getgrgid(struct wbsrv_samba3_call *s3call)
1006 {
1007         struct composite_context *ctx;
1008         struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1009
1010         DEBUG(5, ("wbsrv_samba3_getgrgid called\n"));
1011
1012         ctx = wb_cmd_getgrgid_send(s3call, service,
1013                         s3call->request.data.gid);
1014         NT_STATUS_HAVE_NO_MEMORY(ctx);
1015
1016         ctx->async.fn = getgrgid_recv;
1017         ctx->async.private_data = s3call;
1018         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1019         return NT_STATUS_OK;
1020 }
1021
1022 static void getgrgid_recv(struct composite_context *ctx)
1023 {
1024         struct wbsrv_samba3_call *s3call =
1025                 talloc_get_type(ctx->async.private_data,
1026                                 struct wbsrv_samba3_call);
1027         NTSTATUS status;
1028         struct winbindd_gr *gr;
1029
1030         DEBUG(5, ("getgrgid_recv called\n"));
1031
1032         status = wb_cmd_getgrgid_recv(ctx, s3call, &gr);
1033         if (NT_STATUS_IS_OK(status))
1034                 s3call->response.data.gr = *gr;
1035
1036         wbsrv_samba3_async_epilogue(status, s3call);
1037 }
1038
1039 NTSTATUS wbsrv_samba3_getgroups(struct wbsrv_samba3_call *s3call)
1040 {
1041         DEBUG(5, ("wbsrv_samba3_getgroups called\n"));
1042         s3call->response.result = WINBINDD_ERROR;
1043         return NT_STATUS_OK;
1044 }
1045
1046 NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
1047 {
1048         DEBUG(5, ("wbsrv_samba3_setgrent called\n"));
1049         s3call->response.result = WINBINDD_OK;
1050         return NT_STATUS_OK;
1051 }
1052
1053 NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
1054 {
1055         DEBUG(5, ("wbsrv_samba3_getgrent called\n"));
1056         s3call->response.result = WINBINDD_ERROR;
1057         return NT_STATUS_OK;
1058 }
1059
1060 NTSTATUS wbsrv_samba3_endgrent(struct wbsrv_samba3_call *s3call)
1061 {
1062         DEBUG(5, ("wbsrv_samba3_endgrent called\n"));
1063         s3call->response.result = WINBINDD_OK;
1064         return NT_STATUS_OK;
1065 }
1066
1067 static void sid2uid_recv(struct composite_context *ctx);
1068
1069 NTSTATUS wbsrv_samba3_sid2uid(struct wbsrv_samba3_call *s3call)
1070 {
1071         struct composite_context *ctx;
1072         struct wbsrv_service *service =
1073                 s3call->wbconn->listen_socket->service;
1074         struct dom_sid *sid;
1075
1076         DEBUG(5, ("wbsrv_samba3_sid2uid called\n"));
1077
1078         sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
1079         NT_STATUS_HAVE_NO_MEMORY(sid);
1080
1081         ctx = wb_sid2uid_send(s3call, service, sid);
1082         NT_STATUS_HAVE_NO_MEMORY(ctx);
1083
1084         ctx->async.fn = sid2uid_recv;
1085         ctx->async.private_data = s3call;
1086         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1087         return NT_STATUS_OK;
1088
1089 }
1090
1091 static void sid2uid_recv(struct composite_context *ctx)
1092 {
1093         struct wbsrv_samba3_call *s3call =
1094                 talloc_get_type(ctx->async.private_data,
1095                                 struct wbsrv_samba3_call);
1096         NTSTATUS status;
1097
1098         DEBUG(5, ("sid2uid_recv called\n"));
1099
1100         status = wb_sid2uid_recv(ctx, &s3call->response.data.uid);
1101
1102         wbsrv_samba3_async_epilogue(status, s3call);
1103 }
1104
1105 static void sid2gid_recv(struct composite_context *ctx);
1106
1107 NTSTATUS wbsrv_samba3_sid2gid(struct wbsrv_samba3_call *s3call)
1108 {
1109         struct composite_context *ctx;
1110         struct wbsrv_service *service =
1111                 s3call->wbconn->listen_socket->service;
1112         struct dom_sid *sid;
1113
1114         DEBUG(5, ("wbsrv_samba3_sid2gid called\n"));
1115
1116         sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
1117         NT_STATUS_HAVE_NO_MEMORY(sid);
1118
1119         ctx = wb_sid2gid_send(s3call, service, sid);
1120         NT_STATUS_HAVE_NO_MEMORY(ctx);
1121
1122         ctx->async.fn = sid2gid_recv;
1123         ctx->async.private_data = s3call;
1124         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1125         return NT_STATUS_OK;
1126
1127 }
1128
1129 static void sid2gid_recv(struct composite_context *ctx)
1130 {
1131         struct wbsrv_samba3_call *s3call =
1132                 talloc_get_type(ctx->async.private_data,
1133                                 struct wbsrv_samba3_call);
1134         NTSTATUS status;
1135
1136         DEBUG(5, ("sid2gid_recv called\n"));
1137
1138         status = wb_sid2gid_recv(ctx, &s3call->response.data.gid);
1139
1140         wbsrv_samba3_async_epilogue(status, s3call);
1141 }
1142
1143 static void uid2sid_recv(struct composite_context *ctx);
1144
1145 NTSTATUS wbsrv_samba3_uid2sid(struct wbsrv_samba3_call *s3call)
1146 {
1147         struct composite_context *ctx;
1148         struct wbsrv_service *service =
1149                 s3call->wbconn->listen_socket->service;
1150
1151         DEBUG(5, ("wbsrv_samba3_uid2sid called\n"));
1152
1153         ctx = wb_uid2sid_send(s3call, service, s3call->request.data.uid);
1154         NT_STATUS_HAVE_NO_MEMORY(ctx);
1155
1156         ctx->async.fn = uid2sid_recv;
1157         ctx->async.private_data = s3call;
1158         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1159         return NT_STATUS_OK;
1160
1161 }
1162
1163 static void uid2sid_recv(struct composite_context *ctx)
1164 {
1165         struct wbsrv_samba3_call *s3call =
1166                 talloc_get_type(ctx->async.private_data,
1167                                 struct wbsrv_samba3_call);
1168         NTSTATUS status;
1169         struct dom_sid *sid;
1170         char *sid_str;
1171
1172         DEBUG(5, ("uid2sid_recv called\n"));
1173
1174         status = wb_uid2sid_recv(ctx, s3call, &sid);
1175         if(NT_STATUS_IS_OK(status)) {
1176                 sid_str = dom_sid_string(s3call, sid);
1177
1178                 /* If the conversion failed, bail out with a failure. */
1179                 if (sid_str == NULL)
1180                         wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1181
1182                 /* But we assume this worked, so we'll set the string. Work
1183                  * done. */
1184                 WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid, sid_str);
1185                 s3call->response.data.sid.type = SID_NAME_USER;
1186         }
1187
1188         wbsrv_samba3_async_epilogue(status, s3call);
1189 }
1190
1191 static void gid2sid_recv(struct composite_context *ctx);
1192
1193 NTSTATUS wbsrv_samba3_gid2sid(struct wbsrv_samba3_call *s3call)
1194 {
1195         struct composite_context *ctx;
1196         struct wbsrv_service *service =
1197                 s3call->wbconn->listen_socket->service;
1198
1199         DEBUG(5, ("wbsrv_samba3_gid2sid called\n"));
1200
1201         ctx = wb_gid2sid_send(s3call, service, s3call->request.data.gid);
1202         NT_STATUS_HAVE_NO_MEMORY(ctx);
1203
1204         ctx->async.fn = gid2sid_recv;
1205         ctx->async.private_data = s3call;
1206         s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1207         return NT_STATUS_OK;
1208
1209 }
1210
1211 static void gid2sid_recv(struct composite_context *ctx)
1212 {
1213         struct wbsrv_samba3_call *s3call =
1214                 talloc_get_type(ctx->async.private_data,
1215                                 struct wbsrv_samba3_call);
1216         NTSTATUS status;
1217         struct dom_sid *sid;
1218         char *sid_str;
1219
1220         DEBUG(5, ("gid2sid_recv called\n"));
1221
1222         status = wb_gid2sid_recv(ctx, s3call, &sid);
1223         if(NT_STATUS_IS_OK(status)) {
1224                 sid_str = dom_sid_string(s3call, sid);
1225
1226                 if (sid_str == NULL)
1227                         wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1228
1229                 WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid, sid_str);
1230                 s3call->response.data.sid.type = SID_NAME_DOMAIN;
1231         }
1232
1233         wbsrv_samba3_async_epilogue(status, s3call);
1234 }
1235