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