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