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