s3:smbd/globals: change 'int am_parent' into 'struct smbd_parent_context *am_parent'
[Samba/vl.git] / source4 / winbind / wb_samba3_cmd.c
blob54b1dcc39c7e1b26da7b0217cf5d4d48d5d57eaf
1 /*
2 Unix SMB/CIFS implementation.
3 Main winbindd samba3 server routines
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
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.
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.
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/>.
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 "../libcli/auth/pam_errors.h"
33 #include "auth/credentials/credentials.h"
34 #include "smbd/service_task.h"
37 support the old Samba3 TXT form of the info3
39 static NTSTATUS wb_samba3_append_info3_as_txt(TALLOC_CTX *mem_ctx,
40 struct wbsrv_samba3_call *s3call,
41 DATA_BLOB info3b)
43 struct netr_SamInfo3 *info3;
44 char *ex;
45 uint32_t i;
46 enum ndr_err_code ndr_err;
48 info3 = talloc(mem_ctx, struct netr_SamInfo3);
49 NT_STATUS_HAVE_NO_MEMORY(info3);
51 /* The Samba3 protocol has a redundent 4 bytes at the start */
52 info3b.data += 4;
53 info3b.length -= 4;
55 ndr_err = ndr_pull_struct_blob(&info3b,
56 mem_ctx,
57 info3,
58 (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3);
59 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
60 return ndr_map_error2ntstatus(ndr_err);
63 s3call->response->data.auth.info3.logon_time =
64 nt_time_to_unix(info3->base.logon_time);
65 s3call->response->data.auth.info3.logoff_time =
66 nt_time_to_unix(info3->base.logoff_time);
67 s3call->response->data.auth.info3.kickoff_time =
68 nt_time_to_unix(info3->base.kickoff_time);
69 s3call->response->data.auth.info3.pass_last_set_time =
70 nt_time_to_unix(info3->base.last_password_change);
71 s3call->response->data.auth.info3.pass_can_change_time =
72 nt_time_to_unix(info3->base.allow_password_change);
73 s3call->response->data.auth.info3.pass_must_change_time =
74 nt_time_to_unix(info3->base.force_password_change);
76 s3call->response->data.auth.info3.logon_count = info3->base.logon_count;
77 s3call->response->data.auth.info3.bad_pw_count = info3->base.bad_password_count;
79 s3call->response->data.auth.info3.user_rid = info3->base.rid;
80 s3call->response->data.auth.info3.group_rid = info3->base.primary_gid;
81 fstrcpy(s3call->response->data.auth.info3.dom_sid, dom_sid_string(mem_ctx, info3->base.domain_sid));
83 s3call->response->data.auth.info3.num_groups = info3->base.groups.count;
84 s3call->response->data.auth.info3.user_flgs = info3->base.user_flags;
86 s3call->response->data.auth.info3.acct_flags = info3->base.acct_flags;
87 s3call->response->data.auth.info3.num_other_sids = info3->sidcount;
89 fstrcpy(s3call->response->data.auth.info3.user_name,
90 info3->base.account_name.string);
91 fstrcpy(s3call->response->data.auth.info3.full_name,
92 info3->base.full_name.string);
93 fstrcpy(s3call->response->data.auth.info3.logon_script,
94 info3->base.logon_script.string);
95 fstrcpy(s3call->response->data.auth.info3.profile_path,
96 info3->base.profile_path.string);
97 fstrcpy(s3call->response->data.auth.info3.home_dir,
98 info3->base.home_directory.string);
99 fstrcpy(s3call->response->data.auth.info3.dir_drive,
100 info3->base.home_drive.string);
102 fstrcpy(s3call->response->data.auth.info3.logon_srv,
103 info3->base.logon_server.string);
104 fstrcpy(s3call->response->data.auth.info3.logon_dom,
105 info3->base.logon_domain.string);
107 ex = talloc_strdup(mem_ctx, "");
108 NT_STATUS_HAVE_NO_MEMORY(ex);
110 for (i=0; i < info3->base.groups.count; i++) {
111 ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
112 info3->base.groups.rids[i].rid,
113 info3->base.groups.rids[i].attributes);
114 NT_STATUS_HAVE_NO_MEMORY(ex);
117 for (i=0; i < info3->sidcount; i++) {
118 char *sid;
120 sid = dom_sid_string(mem_ctx, info3->sids[i].sid);
121 NT_STATUS_HAVE_NO_MEMORY(sid);
123 ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n",
124 sid,
125 info3->sids[i].attributes);
126 NT_STATUS_HAVE_NO_MEMORY(ex);
128 talloc_free(sid);
131 s3call->response->extra_data.data = ex;
132 s3call->response->length += talloc_get_size(ex);
134 return NT_STATUS_OK;
138 Send off the reply to an async Samba3 query, handling filling in the PAM, NTSTATUS and string errors.
141 static void wbsrv_samba3_async_auth_epilogue(NTSTATUS status,
142 struct wbsrv_samba3_call *s3call)
144 struct winbindd_response *resp = s3call->response;
145 if (!NT_STATUS_IS_OK(status)) {
146 resp->result = WINBINDD_ERROR;
147 } else {
148 resp->result = WINBINDD_OK;
151 WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
152 nt_errstr(status));
153 WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
154 get_friendly_nt_error_msg(status));
156 resp->data.auth.pam_error = nt_status_to_pam(status);
157 resp->data.auth.nt_status = NT_STATUS_V(status);
159 wbsrv_samba3_send_reply(s3call);
163 Send of a generic reply to a Samba3 query
166 static void wbsrv_samba3_async_epilogue(NTSTATUS status,
167 struct wbsrv_samba3_call *s3call)
169 struct winbindd_response *resp = s3call->response;
170 if (NT_STATUS_IS_OK(status)) {
171 resp->result = WINBINDD_OK;
172 } else {
173 resp->result = WINBINDD_ERROR;
176 wbsrv_samba3_send_reply(s3call);
180 Boilerplate commands, simple queries without network traffic
183 NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
185 s3call->response->result = WINBINDD_OK;
186 s3call->response->data.interface_version = WINBIND_INTERFACE_VERSION;
187 return NT_STATUS_OK;
190 NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
192 s3call->response->result = WINBINDD_OK;
193 s3call->response->data.info.winbind_separator = *lpcfg_winbind_separator(s3call->wbconn->lp_ctx);
194 WBSRV_SAMBA3_SET_STRING(s3call->response->data.info.samba_version,
195 SAMBA_VERSION_STRING);
196 return NT_STATUS_OK;
199 NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
201 s3call->response->result = WINBINDD_OK;
202 WBSRV_SAMBA3_SET_STRING(s3call->response->data.domain_name,
203 lpcfg_workgroup(s3call->wbconn->lp_ctx));
204 return NT_STATUS_OK;
207 NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
209 s3call->response->result = WINBINDD_OK;
210 WBSRV_SAMBA3_SET_STRING(s3call->response->data.netbios_name,
211 lpcfg_netbios_name(s3call->wbconn->lp_ctx));
212 return NT_STATUS_OK;
215 NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
217 struct loadparm_context *lp_ctx = s3call->wbconn->listen_socket->service->task->lp_ctx;
218 const char *priv_socket_dir = lpcfg_winbindd_privileged_socket_directory(lp_ctx);
220 s3call->response->result = WINBINDD_OK;
221 s3call->response->extra_data.data = discard_const(priv_socket_dir);
223 s3call->response->length += strlen(priv_socket_dir) + 1;
224 return NT_STATUS_OK;
227 NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
229 s3call->response->result = WINBINDD_OK;
230 return NT_STATUS_OK;
233 NTSTATUS wbsrv_samba3_domain_info(struct wbsrv_samba3_call *s3call)
235 DEBUG(5, ("wbsrv_samba3_domain_info called, stub\n"));
236 s3call->response->result = WINBINDD_OK;
237 fstrcpy(s3call->response->data.domain_info.name,
238 s3call->request->domain_name);
239 fstrcpy(s3call->response->data.domain_info.alt_name,
240 s3call->request->domain_name);
241 fstrcpy(s3call->response->data.domain_info.sid, "S-1-2-3-4");
242 s3call->response->data.domain_info.native_mode = false;
243 s3call->response->data.domain_info.active_directory = false;
244 s3call->response->data.domain_info.primary = false;
246 return NT_STATUS_OK;
249 /* Plaintext authentication
251 This interface is used by ntlm_auth in it's 'basic' authentication
252 mode, as well as by pam_winbind to authenticate users where we are
253 given a plaintext password.
256 static void check_machacc_recv(struct composite_context *ctx);
258 NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
260 NTSTATUS status;
261 struct cli_credentials *creds;
262 struct composite_context *ctx;
263 struct wbsrv_service *service =
264 s3call->wbconn->listen_socket->service;
266 /* Create a credentials structure */
267 creds = cli_credentials_init(s3call);
268 if (creds == NULL) {
269 return NT_STATUS_NO_MEMORY;
272 cli_credentials_set_conf(creds, service->task->lp_ctx);
274 /* Connect the machine account to the credentials */
275 status = cli_credentials_set_machine_account(creds, service->task->lp_ctx);
276 if (!NT_STATUS_IS_OK(status)) {
277 talloc_free(creds);
278 return status;
281 ctx = wb_cmd_pam_auth_send(s3call, service, creds);
283 if (!ctx) {
284 talloc_free(creds);
285 return NT_STATUS_NO_MEMORY;
288 ctx->async.fn = check_machacc_recv;
289 ctx->async.private_data = s3call;
290 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
291 return NT_STATUS_OK;
294 static void check_machacc_recv(struct composite_context *ctx)
296 struct wbsrv_samba3_call *s3call =
297 talloc_get_type(ctx->async.private_data,
298 struct wbsrv_samba3_call);
299 NTSTATUS status;
301 status = wb_cmd_pam_auth_recv(ctx, s3call, NULL, NULL, NULL, NULL);
303 if (!NT_STATUS_IS_OK(status)) goto done;
305 done:
306 wbsrv_samba3_async_auth_epilogue(status, s3call);
310 Find the name of a suitable domain controller, by query on the
311 netlogon pipe to the DC.
314 static void getdcname_recv_dc(struct composite_context *ctx);
316 NTSTATUS wbsrv_samba3_getdcname(struct wbsrv_samba3_call *s3call)
318 struct composite_context *ctx;
319 struct wbsrv_service *service =
320 s3call->wbconn->listen_socket->service;
322 DEBUG(5, ("wbsrv_samba3_getdcname called\n"));
324 ctx = wb_cmd_getdcname_send(s3call, service,
325 s3call->request->domain_name);
326 NT_STATUS_HAVE_NO_MEMORY(ctx);
328 ctx->async.fn = getdcname_recv_dc;
329 ctx->async.private_data = s3call;
330 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
331 return NT_STATUS_OK;
334 static void getdcname_recv_dc(struct composite_context *ctx)
336 struct wbsrv_samba3_call *s3call =
337 talloc_get_type(ctx->async.private_data,
338 struct wbsrv_samba3_call);
339 const char *dcname;
340 NTSTATUS status;
342 status = wb_cmd_getdcname_recv(ctx, s3call, &dcname);
343 if (!NT_STATUS_IS_OK(status)) goto done;
345 s3call->response->result = WINBINDD_OK;
346 WBSRV_SAMBA3_SET_STRING(s3call->response->data.dc_name, dcname);
348 done:
349 wbsrv_samba3_async_epilogue(status, s3call);
353 Lookup a user's domain groups
356 static void userdomgroups_recv_groups(struct composite_context *ctx);
358 NTSTATUS wbsrv_samba3_userdomgroups(struct wbsrv_samba3_call *s3call)
360 struct composite_context *ctx;
361 struct dom_sid *sid;
363 DEBUG(5, ("wbsrv_samba3_userdomgroups called\n"));
365 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
366 if (sid == NULL) {
367 DEBUG(5, ("Could not parse sid %s\n",
368 s3call->request->data.sid));
369 return NT_STATUS_NO_MEMORY;
372 ctx = wb_cmd_userdomgroups_send(
373 s3call, s3call->wbconn->listen_socket->service, sid);
374 NT_STATUS_HAVE_NO_MEMORY(ctx);
376 ctx->async.fn = userdomgroups_recv_groups;
377 ctx->async.private_data = s3call;
378 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
379 return NT_STATUS_OK;
382 static void userdomgroups_recv_groups(struct composite_context *ctx)
384 struct wbsrv_samba3_call *s3call =
385 talloc_get_type(ctx->async.private_data,
386 struct wbsrv_samba3_call);
387 uint32_t i, num_sids;
388 struct dom_sid **sids;
389 char *sids_string;
390 NTSTATUS status;
392 status = wb_cmd_userdomgroups_recv(ctx, s3call, &num_sids, &sids);
393 if (!NT_STATUS_IS_OK(status)) goto done;
395 sids_string = talloc_strdup(s3call, "");
396 if (sids_string == NULL) {
397 status = NT_STATUS_NO_MEMORY;
398 goto done;
401 for (i=0; i<num_sids; i++) {
402 sids_string = talloc_asprintf_append_buffer(
403 sids_string, "%s\n", dom_sid_string(s3call, sids[i]));
406 if (sids_string == NULL) {
407 status = NT_STATUS_NO_MEMORY;
408 goto done;
411 s3call->response->result = WINBINDD_OK;
412 s3call->response->extra_data.data = sids_string;
413 s3call->response->length += strlen(sids_string)+1;
414 s3call->response->data.num_entries = num_sids;
416 done:
417 wbsrv_samba3_async_epilogue(status, s3call);
421 Lookup the list of SIDs for a user
423 static void usersids_recv_sids(struct composite_context *ctx);
425 NTSTATUS wbsrv_samba3_usersids(struct wbsrv_samba3_call *s3call)
427 struct composite_context *ctx;
428 struct dom_sid *sid;
430 DEBUG(5, ("wbsrv_samba3_usersids called\n"));
432 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
433 if (sid == NULL) {
434 DEBUG(5, ("Could not parse sid %s\n",
435 s3call->request->data.sid));
436 return NT_STATUS_NO_MEMORY;
439 ctx = wb_cmd_usersids_send(
440 s3call, s3call->wbconn->listen_socket->service, sid);
441 NT_STATUS_HAVE_NO_MEMORY(ctx);
443 ctx->async.fn = usersids_recv_sids;
444 ctx->async.private_data = s3call;
445 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
446 return NT_STATUS_OK;
449 static void usersids_recv_sids(struct composite_context *ctx)
451 struct wbsrv_samba3_call *s3call =
452 talloc_get_type(ctx->async.private_data,
453 struct wbsrv_samba3_call);
454 uint32_t i, num_sids;
455 struct dom_sid **sids;
456 char *sids_string;
457 NTSTATUS status;
459 status = wb_cmd_usersids_recv(ctx, s3call, &num_sids, &sids);
460 if (!NT_STATUS_IS_OK(status)) goto done;
462 sids_string = talloc_strdup(s3call, "");
463 if (sids_string == NULL) {
464 status = NT_STATUS_NO_MEMORY;
465 goto done;
468 for (i=0; i<num_sids; i++) {
469 sids_string = talloc_asprintf_append_buffer(
470 sids_string, "%s\n", dom_sid_string(s3call, sids[i]));
471 if (sids_string == NULL) {
472 status = NT_STATUS_NO_MEMORY;
473 goto done;
477 s3call->response->result = WINBINDD_OK;
478 s3call->response->extra_data.data = sids_string;
479 s3call->response->length += strlen(sids_string);
480 s3call->response->data.num_entries = num_sids;
482 /* Hmmmm. Nasty protocol -- who invented the zeros between the
483 * SIDs? Hmmm. Could have been me -- vl */
485 while (*sids_string != '\0') {
486 if ((*sids_string) == '\n') {
487 *sids_string = '\0';
489 sids_string += 1;
492 done:
493 wbsrv_samba3_async_epilogue(status, s3call);
497 Lookup a DOMAIN\\user style name, and return a SID
500 static void lookupname_recv_sid(struct composite_context *ctx);
502 NTSTATUS wbsrv_samba3_lookupname(struct wbsrv_samba3_call *s3call)
504 struct composite_context *ctx;
505 struct wbsrv_service *service =
506 s3call->wbconn->listen_socket->service;
508 DEBUG(5, ("wbsrv_samba3_lookupname called\n"));
510 ctx = wb_cmd_lookupname_send(s3call, service,
511 s3call->request->data.name.dom_name,
512 s3call->request->data.name.name);
513 NT_STATUS_HAVE_NO_MEMORY(ctx);
515 /* setup the callbacks */
516 ctx->async.fn = lookupname_recv_sid;
517 ctx->async.private_data = s3call;
518 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
519 return NT_STATUS_OK;
522 static void lookupname_recv_sid(struct composite_context *ctx)
524 struct wbsrv_samba3_call *s3call =
525 talloc_get_type(ctx->async.private_data,
526 struct wbsrv_samba3_call);
527 struct wb_sid_object *sid;
528 NTSTATUS status;
530 status = wb_cmd_lookupname_recv(ctx, s3call, &sid);
531 if (!NT_STATUS_IS_OK(status)) goto done;
533 s3call->response->result = WINBINDD_OK;
534 s3call->response->data.sid.type = sid->type;
535 WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid,
536 dom_sid_string(s3call, sid->sid));
538 done:
539 wbsrv_samba3_async_epilogue(status, s3call);
543 Lookup a SID, and return a DOMAIN\\user style name
546 static void lookupsid_recv_name(struct composite_context *ctx);
548 NTSTATUS wbsrv_samba3_lookupsid(struct wbsrv_samba3_call *s3call)
550 struct composite_context *ctx;
551 struct wbsrv_service *service =
552 s3call->wbconn->listen_socket->service;
553 struct dom_sid *sid;
555 DEBUG(5, ("wbsrv_samba3_lookupsid called\n"));
557 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
558 if (sid == NULL) {
559 DEBUG(5, ("Could not parse sid %s\n",
560 s3call->request->data.sid));
561 return NT_STATUS_NO_MEMORY;
564 ctx = wb_cmd_lookupsid_send(s3call, service, sid);
565 NT_STATUS_HAVE_NO_MEMORY(ctx);
567 /* setup the callbacks */
568 ctx->async.fn = lookupsid_recv_name;
569 ctx->async.private_data = s3call;
570 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
571 return NT_STATUS_OK;
574 static void lookupsid_recv_name(struct composite_context *ctx)
576 struct wbsrv_samba3_call *s3call =
577 talloc_get_type(ctx->async.private_data,
578 struct wbsrv_samba3_call);
579 struct wb_sid_object *sid;
580 NTSTATUS status;
582 status = wb_cmd_lookupsid_recv(ctx, s3call, &sid);
583 if (!NT_STATUS_IS_OK(status)) goto done;
585 s3call->response->result = WINBINDD_OK;
586 s3call->response->data.name.type = sid->type;
587 WBSRV_SAMBA3_SET_STRING(s3call->response->data.name.dom_name,
588 sid->domain);
589 WBSRV_SAMBA3_SET_STRING(s3call->response->data.name.name, sid->name);
591 done:
592 wbsrv_samba3_async_epilogue(status, s3call);
596 This is a stub function in order to limit error message in the pam_winbind module
598 NTSTATUS wbsrv_samba3_pam_logoff(struct wbsrv_samba3_call *s3call)
600 NTSTATUS status;
601 struct winbindd_response *resp = s3call->response;
603 status = NT_STATUS_OK;
605 DEBUG(5, ("wbsrv_samba3_pam_logoff called\n"));
606 DEBUG(10, ("Winbind logoff not implemented\n"));
607 resp->result = WINBINDD_OK;
609 WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
610 nt_errstr(status));
611 WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
612 get_friendly_nt_error_msg(status));
614 resp->data.auth.pam_error = nt_status_to_pam(status);
615 resp->data.auth.nt_status = NT_STATUS_V(status);
616 DEBUG(5, ("wbsrv_samba3_pam_logoff called\n"));
618 return NT_STATUS_OK;
622 Challenge-response authentication. This interface is used by
623 ntlm_auth and the smbd auth subsystem to pass NTLM authentication
624 requests along a common pipe to the domain controller.
626 The return value (in the async reply) may include the 'info3'
627 (effectivly most things you would want to know about the user), or
628 the NT and LM session keys seperated.
631 static void pam_auth_crap_recv(struct composite_context *ctx);
633 NTSTATUS wbsrv_samba3_pam_auth_crap(struct wbsrv_samba3_call *s3call)
635 struct composite_context *ctx;
636 struct wbsrv_service *service =
637 s3call->wbconn->listen_socket->service;
638 DATA_BLOB chal, nt_resp, lm_resp;
640 DEBUG(5, ("wbsrv_samba3_pam_auth_crap called\n"));
642 chal.data = s3call->request->data.auth_crap.chal;
643 chal.length = sizeof(s3call->request->data.auth_crap.chal);
644 nt_resp.data = (uint8_t *)s3call->request->data.auth_crap.nt_resp;
645 nt_resp.length = s3call->request->data.auth_crap.nt_resp_len;
646 lm_resp.data = (uint8_t *)s3call->request->data.auth_crap.lm_resp;
647 lm_resp.length = s3call->request->data.auth_crap.lm_resp_len;
649 ctx = wb_cmd_pam_auth_crap_send(
650 s3call, service,
651 s3call->request->data.auth_crap.logon_parameters,
652 s3call->request->data.auth_crap.domain,
653 s3call->request->data.auth_crap.user,
654 s3call->request->data.auth_crap.workstation,
655 chal, nt_resp, lm_resp);
656 NT_STATUS_HAVE_NO_MEMORY(ctx);
658 ctx->async.fn = pam_auth_crap_recv;
659 ctx->async.private_data = s3call;
660 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
661 return NT_STATUS_OK;
664 static void pam_auth_crap_recv(struct composite_context *ctx)
666 struct wbsrv_samba3_call *s3call =
667 talloc_get_type(ctx->async.private_data,
668 struct wbsrv_samba3_call);
669 NTSTATUS status;
670 DATA_BLOB info3;
671 struct netr_UserSessionKey user_session_key;
672 struct netr_LMSessionKey lm_key;
673 char *unix_username;
675 status = wb_cmd_pam_auth_crap_recv(ctx, s3call, &info3,
676 &user_session_key, &lm_key, &unix_username);
677 if (!NT_STATUS_IS_OK(status)) goto done;
679 if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
680 memcpy(s3call->response->data.auth.user_session_key,
681 &user_session_key.key,
682 sizeof(s3call->response->data.auth.user_session_key));
685 if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
686 status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
687 if (!NT_STATUS_IS_OK(status)) {
688 DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
689 nt_errstr(status)));
690 goto done;
694 if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
695 s3call->response->extra_data.data = info3.data;
696 s3call->response->length += info3.length;
699 if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
700 memcpy(s3call->response->data.auth.first_8_lm_hash,
701 lm_key.key,
702 sizeof(s3call->response->data.auth.first_8_lm_hash));
705 if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
706 WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
709 done:
710 wbsrv_samba3_async_auth_epilogue(status, s3call);
713 /* Plaintext authentication
715 This interface is used by ntlm_auth in it's 'basic' authentication
716 mode, as well as by pam_winbind to authenticate users where we are
717 given a plaintext password.
720 static void pam_auth_recv(struct composite_context *ctx);
722 NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
724 struct composite_context *ctx;
725 struct wbsrv_service *service =
726 s3call->wbconn->listen_socket->service;
727 struct cli_credentials *credentials;
728 char *user, *domain;
730 if (!wb_samba3_split_username(s3call, s3call->wbconn->lp_ctx,
731 s3call->request->data.auth.user,
732 &domain, &user)) {
733 return NT_STATUS_NO_SUCH_USER;
736 credentials = cli_credentials_init(s3call);
737 if (!credentials) {
738 return NT_STATUS_NO_MEMORY;
740 cli_credentials_set_conf(credentials, service->task->lp_ctx);
741 cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
742 cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
744 cli_credentials_set_password(credentials, s3call->request->data.auth.pass, CRED_SPECIFIED);
746 ctx = wb_cmd_pam_auth_send(s3call, service, credentials);
747 NT_STATUS_HAVE_NO_MEMORY(ctx);
749 ctx->async.fn = pam_auth_recv;
750 ctx->async.private_data = s3call;
751 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
752 return NT_STATUS_OK;
755 static void pam_auth_recv(struct composite_context *ctx)
757 struct wbsrv_samba3_call *s3call =
758 talloc_get_type(ctx->async.private_data,
759 struct wbsrv_samba3_call);
760 NTSTATUS status;
761 DATA_BLOB info3;
762 struct netr_UserSessionKey user_session_key;
763 struct netr_LMSessionKey lm_key;
764 char *unix_username;
766 status = wb_cmd_pam_auth_recv(ctx, s3call, &info3,
767 &user_session_key, &lm_key, &unix_username);
769 if (!NT_STATUS_IS_OK(status)) goto done;
771 if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
772 memcpy(s3call->response->data.auth.user_session_key,
773 &user_session_key.key,
774 sizeof(s3call->response->data.auth.user_session_key));
777 if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
778 status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
779 if (!NT_STATUS_IS_OK(status)) {
780 DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
781 nt_errstr(status)));
782 goto done;
786 if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
787 s3call->response->extra_data.data = info3.data;
788 s3call->response->length += info3.length;
791 if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
792 memcpy(s3call->response->data.auth.first_8_lm_hash,
793 lm_key.key,
794 sizeof(s3call->response->data.auth.first_8_lm_hash));
797 if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
798 WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
802 done:
803 wbsrv_samba3_async_auth_epilogue(status, s3call);
807 List trusted domains
810 static void list_trustdom_recv_doms(struct composite_context *ctx);
812 NTSTATUS wbsrv_samba3_list_trustdom(struct wbsrv_samba3_call *s3call)
814 struct composite_context *ctx;
815 struct wbsrv_service *service =
816 s3call->wbconn->listen_socket->service;
818 DEBUG(5, ("wbsrv_samba3_list_trustdom called\n"));
820 ctx = wb_cmd_list_trustdoms_send(s3call, service);
821 NT_STATUS_HAVE_NO_MEMORY(ctx);
823 ctx->async.fn = list_trustdom_recv_doms;
824 ctx->async.private_data = s3call;
825 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
826 return NT_STATUS_OK;
829 static void list_trustdom_recv_doms(struct composite_context *ctx)
831 struct wbsrv_samba3_call *s3call =
832 talloc_get_type(ctx->async.private_data,
833 struct wbsrv_samba3_call);
834 uint32_t i, num_domains;
835 struct wb_dom_info **domains;
836 NTSTATUS status;
837 char *result;
839 status = wb_cmd_list_trustdoms_recv(ctx, s3call, &num_domains,
840 &domains);
841 if (!NT_STATUS_IS_OK(status)) goto done;
843 result = talloc_strdup(s3call, "");
844 if (result == NULL) {
845 status = NT_STATUS_NO_MEMORY;
846 goto done;
849 for (i=0; i<num_domains; i++) {
850 result = talloc_asprintf_append_buffer(
851 result, "%s\\%s\\%s",
852 domains[i]->name, domains[i]->name,
853 dom_sid_string(s3call, domains[i]->sid));
856 if (result == NULL) {
857 status = NT_STATUS_NO_MEMORY;
858 goto done;
861 s3call->response->result = WINBINDD_OK;
862 if (num_domains > 0) {
863 s3call->response->extra_data.data = result;
864 s3call->response->length += strlen(result)+1;
865 s3call->response->data.num_entries = num_domains;
868 done:
869 wbsrv_samba3_async_epilogue(status, s3call);
872 /* list groups */
873 static void list_groups_recv(struct composite_context *ctx);
875 NTSTATUS wbsrv_samba3_list_groups(struct wbsrv_samba3_call *s3call)
877 struct composite_context *ctx;
878 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
880 DEBUG(5, ("wbsrv_samba4_list_groups called\n"));
882 ctx = wb_cmd_list_groups_send(s3call, service,
883 s3call->request->domain_name);
884 NT_STATUS_HAVE_NO_MEMORY(ctx);
886 ctx->async.fn = list_groups_recv;
887 ctx->async.private_data = s3call;
888 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
889 return NT_STATUS_OK;
892 static void list_groups_recv(struct composite_context *ctx)
894 struct wbsrv_samba3_call *s3call = talloc_get_type_abort(
895 ctx->async.private_data,
896 struct wbsrv_samba3_call);
897 uint32_t extra_data_len;
898 char *extra_data;
899 uint32_t num_groups;
900 NTSTATUS status;
902 DEBUG(5, ("list_groups_recv called\n"));
904 status = wb_cmd_list_groups_recv(ctx, s3call, &extra_data_len,
905 &extra_data, &num_groups);
907 if (NT_STATUS_IS_OK(status)) {
908 s3call->response->extra_data.data = extra_data;
909 s3call->response->length += extra_data_len;
910 if (extra_data) {
911 s3call->response->length += 1;
912 s3call->response->data.num_entries = num_groups;
916 wbsrv_samba3_async_epilogue(status, s3call);
919 /* List users */
921 static void list_users_recv(struct composite_context *ctx);
923 NTSTATUS wbsrv_samba3_list_users(struct wbsrv_samba3_call *s3call)
925 struct composite_context *ctx;
926 struct wbsrv_service *service =
927 s3call->wbconn->listen_socket->service;
929 DEBUG(5, ("wbsrv_samba3_list_users called\n"));
931 ctx = wb_cmd_list_users_send(s3call, service,
932 s3call->request->domain_name);
933 NT_STATUS_HAVE_NO_MEMORY(ctx);
935 ctx->async.fn = list_users_recv;
936 ctx->async.private_data = s3call;
937 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
938 return NT_STATUS_OK;
941 static void list_users_recv(struct composite_context *ctx)
943 struct wbsrv_samba3_call *s3call =
944 talloc_get_type(ctx->async.private_data,
945 struct wbsrv_samba3_call);
946 uint32_t extra_data_len;
947 char *extra_data;
948 uint32_t num_users;
949 NTSTATUS status;
951 DEBUG(5, ("list_users_recv called\n"));
953 status = wb_cmd_list_users_recv(ctx, s3call, &extra_data_len,
954 &extra_data, &num_users);
956 if (NT_STATUS_IS_OK(status)) {
957 s3call->response->extra_data.data = extra_data;
958 s3call->response->length += extra_data_len;
959 if (extra_data) {
960 s3call->response->length += 1;
961 s3call->response->data.num_entries = num_users;
965 wbsrv_samba3_async_epilogue(status, s3call);
968 /* NSS calls */
970 static void getpwnam_recv(struct composite_context *ctx);
972 NTSTATUS wbsrv_samba3_getpwnam(struct wbsrv_samba3_call *s3call)
974 struct composite_context *ctx;
975 struct wbsrv_service *service =
976 s3call->wbconn->listen_socket->service;
978 DEBUG(5, ("wbsrv_samba3_getpwnam called\n"));
980 ctx = wb_cmd_getpwnam_send(s3call, service,
981 s3call->request->data.username);
982 NT_STATUS_HAVE_NO_MEMORY(ctx);
984 ctx->async.fn = getpwnam_recv;
985 ctx->async.private_data = s3call;
986 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
987 return NT_STATUS_OK;
990 static void getpwnam_recv(struct composite_context *ctx)
992 struct wbsrv_samba3_call *s3call =
993 talloc_get_type(ctx->async.private_data,
994 struct wbsrv_samba3_call);
995 NTSTATUS status;
996 struct winbindd_pw *pw;
998 DEBUG(5, ("getpwnam_recv called\n"));
1000 status = wb_cmd_getpwnam_recv(ctx, s3call, &pw);
1001 if(NT_STATUS_IS_OK(status))
1002 s3call->response->data.pw = *pw;
1004 wbsrv_samba3_async_epilogue(status, s3call);
1007 static void getpwuid_recv(struct composite_context *ctx);
1009 NTSTATUS wbsrv_samba3_getpwuid(struct wbsrv_samba3_call *s3call)
1011 struct composite_context *ctx;
1012 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1014 DEBUG(5, ("wbsrv_samba3_getpwuid called\n"));
1016 ctx = wb_cmd_getpwuid_send(s3call, service,
1017 s3call->request->data.uid);
1018 NT_STATUS_HAVE_NO_MEMORY(ctx);
1020 ctx->async.fn = getpwuid_recv;
1021 ctx->async.private_data = s3call;
1022 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1023 return NT_STATUS_OK;
1026 static void getpwuid_recv(struct composite_context *ctx)
1028 struct wbsrv_samba3_call *s3call =
1029 talloc_get_type(ctx->async.private_data,
1030 struct wbsrv_samba3_call);
1031 NTSTATUS status;
1032 struct winbindd_pw *pw;
1034 DEBUG(5, ("getpwuid_recv called\n"));
1036 status = wb_cmd_getpwuid_recv(ctx, s3call, &pw);
1037 if (NT_STATUS_IS_OK(status))
1038 s3call->response->data.pw = *pw;
1040 wbsrv_samba3_async_epilogue(status, s3call);
1043 static void setpwent_recv(struct composite_context *ctx);
1045 NTSTATUS wbsrv_samba3_setpwent(struct wbsrv_samba3_call *s3call)
1047 struct composite_context *ctx;
1048 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1050 DEBUG(5, ("wbsrv_samba3_setpwent called\n"));
1052 ctx = wb_cmd_setpwent_send(s3call, service);
1053 NT_STATUS_HAVE_NO_MEMORY(ctx);
1055 ctx->async.fn = setpwent_recv;
1056 ctx->async.private_data = s3call;
1057 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1058 return NT_STATUS_OK;
1061 static void setpwent_recv(struct composite_context *ctx)
1063 struct wbsrv_samba3_call *s3call =
1064 talloc_get_type(ctx->async.private_data,
1065 struct wbsrv_samba3_call);
1066 NTSTATUS status;
1067 struct wbsrv_pwent *pwent;
1069 DEBUG(5, ("setpwent_recv called\n"));
1071 status = wb_cmd_setpwent_recv(ctx, s3call->wbconn, &pwent);
1072 if (NT_STATUS_IS_OK(status)) {
1073 s3call->wbconn->protocol_private_data = pwent;
1076 wbsrv_samba3_async_epilogue(status, s3call);
1079 static void getpwent_recv(struct composite_context *ctx);
1081 NTSTATUS wbsrv_samba3_getpwent(struct wbsrv_samba3_call *s3call)
1083 struct composite_context *ctx;
1084 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1085 struct wbsrv_pwent *pwent;
1087 DEBUG(5, ("wbsrv_samba3_getpwent called\n"));
1089 NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
1091 pwent = talloc_get_type(s3call->wbconn->protocol_private_data,
1092 struct wbsrv_pwent);
1093 NT_STATUS_HAVE_NO_MEMORY(pwent);
1095 ctx = wb_cmd_getpwent_send(s3call, service, pwent,
1096 s3call->request->data.num_entries);
1097 NT_STATUS_HAVE_NO_MEMORY(ctx);
1099 ctx->async.fn = getpwent_recv;
1100 ctx->async.private_data = s3call;
1101 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1102 return NT_STATUS_OK;
1105 static void getpwent_recv(struct composite_context *ctx)
1107 struct wbsrv_samba3_call *s3call =
1108 talloc_get_type(ctx->async.private_data,
1109 struct wbsrv_samba3_call);
1110 NTSTATUS status;
1111 struct winbindd_pw *pw;
1112 uint32_t num_users;
1114 DEBUG(5, ("getpwent_recv called\n"));
1116 status = wb_cmd_getpwent_recv(ctx, s3call, &pw, &num_users);
1117 if (NT_STATUS_IS_OK(status)) {
1118 uint32_t extra_len = sizeof(struct winbindd_pw) * num_users;
1120 s3call->response->data.num_entries = num_users;
1121 s3call->response->extra_data.data = pw;
1122 s3call->response->length += extra_len;
1125 wbsrv_samba3_async_epilogue(status, s3call);
1128 NTSTATUS wbsrv_samba3_endpwent(struct wbsrv_samba3_call *s3call)
1130 struct wbsrv_pwent *pwent =
1131 talloc_get_type(s3call->wbconn->protocol_private_data,
1132 struct wbsrv_pwent);
1133 DEBUG(5, ("wbsrv_samba3_endpwent called\n"));
1135 talloc_free(pwent);
1137 s3call->wbconn->protocol_private_data = NULL;
1138 s3call->response->result = WINBINDD_OK;
1139 return NT_STATUS_OK;
1143 static void getgrnam_recv(struct composite_context *ctx);
1145 NTSTATUS wbsrv_samba3_getgrnam(struct wbsrv_samba3_call *s3call)
1147 struct composite_context *ctx;
1148 struct wbsrv_service *service =
1149 s3call->wbconn->listen_socket->service;
1151 DEBUG(5, ("wbsrv_samba3_getgrnam called\n"));
1153 ctx = wb_cmd_getgrnam_send(s3call, service,
1154 s3call->request->data.groupname);
1155 NT_STATUS_HAVE_NO_MEMORY(ctx);
1157 ctx->async.fn = getgrnam_recv;
1158 ctx->async.private_data = s3call;
1159 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1160 return NT_STATUS_OK;
1163 static void getgrnam_recv(struct composite_context *ctx)
1165 struct wbsrv_samba3_call *s3call =
1166 talloc_get_type(ctx->async.private_data,
1167 struct wbsrv_samba3_call);
1168 NTSTATUS status;
1169 struct winbindd_gr *gr;
1171 DEBUG(5, ("getgrnam_recv called\n"));
1173 status = wb_cmd_getgrnam_recv(ctx, s3call, &gr);
1174 if(NT_STATUS_IS_OK(status))
1175 s3call->response->data.gr = *gr;
1177 wbsrv_samba3_async_epilogue(status, s3call);
1180 static void getgrgid_recv(struct composite_context *ctx);
1182 NTSTATUS wbsrv_samba3_getgrgid(struct wbsrv_samba3_call *s3call)
1184 struct composite_context *ctx;
1185 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1187 DEBUG(5, ("wbsrv_samba3_getgrgid called\n"));
1189 ctx = wb_cmd_getgrgid_send(s3call, service,
1190 s3call->request->data.gid);
1191 NT_STATUS_HAVE_NO_MEMORY(ctx);
1193 ctx->async.fn = getgrgid_recv;
1194 ctx->async.private_data = s3call;
1195 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1196 return NT_STATUS_OK;
1199 static void getgrgid_recv(struct composite_context *ctx)
1201 struct wbsrv_samba3_call *s3call =
1202 talloc_get_type(ctx->async.private_data,
1203 struct wbsrv_samba3_call);
1204 NTSTATUS status;
1205 struct winbindd_gr *gr;
1207 DEBUG(5, ("getgrgid_recv called\n"));
1209 status = wb_cmd_getgrgid_recv(ctx, s3call, &gr);
1210 if (NT_STATUS_IS_OK(status))
1211 s3call->response->data.gr = *gr;
1213 wbsrv_samba3_async_epilogue(status, s3call);
1216 static void getgroups_recv(struct composite_context *ctx);
1218 NTSTATUS wbsrv_samba3_getgroups(struct wbsrv_samba3_call *s3call)
1220 struct composite_context *ctx;
1221 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1223 DEBUG(5, ("wbsrv_samba3_getgroups called\n"));
1224 /* S3 code do the same so why not ... */
1225 s3call->request->data.username[sizeof(s3call->request->data.username)-1]='\0';
1226 ctx = wb_cmd_getgroups_send(s3call, service, s3call->request->data.username);
1227 NT_STATUS_HAVE_NO_MEMORY(ctx);
1229 ctx->async.fn = getgroups_recv;
1230 ctx->async.private_data = s3call;
1231 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1232 return NT_STATUS_OK;
1235 static void getgroups_recv(struct composite_context *ctx)
1237 struct wbsrv_samba3_call *s3call =
1238 talloc_get_type(ctx->async.private_data,
1239 struct wbsrv_samba3_call);
1240 gid_t *gids;
1241 uint32_t num_groups;
1242 NTSTATUS status;
1243 DEBUG(5, ("getgroups_recv called\n"));
1245 status = wb_cmd_getgroups_recv(ctx, s3call, &gids, &num_groups);
1246 if (NT_STATUS_IS_OK(status)) {
1247 uint32_t extra_len = sizeof(gid_t) * num_groups;
1249 s3call->response->data.num_entries = num_groups;
1250 s3call->response->extra_data.data = gids;
1251 s3call->response->length += extra_len;
1252 } else {
1253 s3call->response->result = WINBINDD_ERROR;
1256 wbsrv_samba3_async_epilogue(status, s3call);
1259 static void setgrent_recv(struct composite_context *ctx);
1261 NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
1263 struct composite_context *ctx;
1264 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1266 DEBUG(5, ("wbsrv_samba3_setgrent called\n"));
1268 ctx = wb_cmd_setgrent_send(s3call, service);
1269 NT_STATUS_HAVE_NO_MEMORY(ctx);
1271 ctx->async.fn = setgrent_recv;
1272 ctx->async.private_data = s3call;
1273 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1274 return NT_STATUS_OK;
1277 static void setgrent_recv(struct composite_context *ctx)
1279 struct wbsrv_samba3_call *s3call =
1280 talloc_get_type(ctx->async.private_data,
1281 struct wbsrv_samba3_call);
1282 NTSTATUS status;
1283 struct wbsrv_grent *grent;
1285 DEBUG(5, ("setpwent_recv called\n"));
1287 status = wb_cmd_setgrent_recv(ctx, s3call->wbconn, &grent);
1288 if (NT_STATUS_IS_OK(status)) {
1289 s3call->wbconn->protocol_private_data = grent;
1292 wbsrv_samba3_async_epilogue(status, s3call);
1295 static void getgrent_recv(struct composite_context *ctx);
1297 NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
1299 struct composite_context *ctx;
1300 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1301 struct wbsrv_grent *grent;
1303 DEBUG(5, ("wbsrv_samba3_getgrent called\n"));
1305 NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
1307 grent = talloc_get_type(s3call->wbconn->protocol_private_data,
1308 struct wbsrv_grent);
1309 NT_STATUS_HAVE_NO_MEMORY(grent);
1311 ctx = wb_cmd_getgrent_send(s3call, service, grent,
1312 s3call->request->data.num_entries);
1313 NT_STATUS_HAVE_NO_MEMORY(ctx);
1315 ctx->async.fn = getgrent_recv;
1316 ctx->async.private_data = s3call;
1317 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1318 return NT_STATUS_OK;
1321 static void getgrent_recv(struct composite_context *ctx)
1323 struct wbsrv_samba3_call *s3call =
1324 talloc_get_type(ctx->async.private_data,
1325 struct wbsrv_samba3_call);
1326 NTSTATUS status;
1327 struct winbindd_gr *gr;
1328 uint32_t num_groups;
1330 DEBUG(5, ("getgrent_recv called\n"));
1332 status = wb_cmd_getgrent_recv(ctx, s3call, &gr, &num_groups);
1333 if (NT_STATUS_IS_OK(status)) {
1334 uint32_t extra_len = sizeof(struct winbindd_gr) * num_groups;
1336 s3call->response->data.num_entries = num_groups;
1337 s3call->response->extra_data.data = gr;
1338 s3call->response->length += extra_len;
1341 wbsrv_samba3_async_epilogue(status, s3call);
1344 NTSTATUS wbsrv_samba3_endgrent(struct wbsrv_samba3_call *s3call)
1346 DEBUG(5, ("wbsrv_samba3_endgrent called\n"));
1347 s3call->response->result = WINBINDD_OK;
1348 return NT_STATUS_OK;
1351 static void sid2uid_recv(struct composite_context *ctx);
1353 NTSTATUS wbsrv_samba3_sid2uid(struct wbsrv_samba3_call *s3call)
1355 struct composite_context *ctx;
1356 struct wbsrv_service *service =
1357 s3call->wbconn->listen_socket->service;
1358 struct dom_sid *sid;
1360 DEBUG(5, ("wbsrv_samba3_sid2uid called\n"));
1362 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
1363 NT_STATUS_HAVE_NO_MEMORY(sid);
1365 ctx = wb_sid2uid_send(s3call, service, sid);
1366 NT_STATUS_HAVE_NO_MEMORY(ctx);
1368 ctx->async.fn = sid2uid_recv;
1369 ctx->async.private_data = s3call;
1370 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1371 return NT_STATUS_OK;
1375 static void sid2uid_recv(struct composite_context *ctx)
1377 struct wbsrv_samba3_call *s3call =
1378 talloc_get_type(ctx->async.private_data,
1379 struct wbsrv_samba3_call);
1380 NTSTATUS status;
1382 DEBUG(5, ("sid2uid_recv called\n"));
1384 status = wb_sid2uid_recv(ctx, &s3call->response->data.uid);
1386 wbsrv_samba3_async_epilogue(status, s3call);
1389 static void sid2gid_recv(struct composite_context *ctx);
1391 NTSTATUS wbsrv_samba3_sid2gid(struct wbsrv_samba3_call *s3call)
1393 struct composite_context *ctx;
1394 struct wbsrv_service *service =
1395 s3call->wbconn->listen_socket->service;
1396 struct dom_sid *sid;
1398 DEBUG(5, ("wbsrv_samba3_sid2gid called\n"));
1400 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
1401 NT_STATUS_HAVE_NO_MEMORY(sid);
1403 ctx = wb_sid2gid_send(s3call, service, sid);
1404 NT_STATUS_HAVE_NO_MEMORY(ctx);
1406 ctx->async.fn = sid2gid_recv;
1407 ctx->async.private_data = s3call;
1408 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1409 return NT_STATUS_OK;
1413 static void sid2gid_recv(struct composite_context *ctx)
1415 struct wbsrv_samba3_call *s3call =
1416 talloc_get_type(ctx->async.private_data,
1417 struct wbsrv_samba3_call);
1418 NTSTATUS status;
1420 DEBUG(5, ("sid2gid_recv called\n"));
1422 status = wb_sid2gid_recv(ctx, &s3call->response->data.gid);
1424 wbsrv_samba3_async_epilogue(status, s3call);
1427 static void uid2sid_recv(struct composite_context *ctx);
1429 NTSTATUS wbsrv_samba3_uid2sid(struct wbsrv_samba3_call *s3call)
1431 struct composite_context *ctx;
1432 struct wbsrv_service *service =
1433 s3call->wbconn->listen_socket->service;
1435 DEBUG(5, ("wbsrv_samba3_uid2sid called\n"));
1437 ctx = wb_uid2sid_send(s3call, service, s3call->request->data.uid);
1438 NT_STATUS_HAVE_NO_MEMORY(ctx);
1440 ctx->async.fn = uid2sid_recv;
1441 ctx->async.private_data = s3call;
1442 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1443 return NT_STATUS_OK;
1447 static void uid2sid_recv(struct composite_context *ctx)
1449 struct wbsrv_samba3_call *s3call =
1450 talloc_get_type(ctx->async.private_data,
1451 struct wbsrv_samba3_call);
1452 NTSTATUS status;
1453 struct dom_sid *sid;
1454 char *sid_str;
1456 DEBUG(5, ("uid2sid_recv called\n"));
1458 status = wb_uid2sid_recv(ctx, s3call, &sid);
1459 if(NT_STATUS_IS_OK(status)) {
1460 sid_str = dom_sid_string(s3call, sid);
1462 /* If the conversion failed, bail out with a failure. */
1463 if (sid_str == NULL)
1464 wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1466 /* But we assume this worked, so we'll set the string. Work
1467 * done. */
1468 WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
1469 s3call->response->data.sid.type = SID_NAME_USER;
1472 wbsrv_samba3_async_epilogue(status, s3call);
1475 static void gid2sid_recv(struct composite_context *ctx);
1477 NTSTATUS wbsrv_samba3_gid2sid(struct wbsrv_samba3_call *s3call)
1479 struct composite_context *ctx;
1480 struct wbsrv_service *service =
1481 s3call->wbconn->listen_socket->service;
1483 DEBUG(5, ("wbsrv_samba3_gid2sid called\n"));
1485 ctx = wb_gid2sid_send(s3call, service, s3call->request->data.gid);
1486 NT_STATUS_HAVE_NO_MEMORY(ctx);
1488 ctx->async.fn = gid2sid_recv;
1489 ctx->async.private_data = s3call;
1490 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1491 return NT_STATUS_OK;
1495 static void gid2sid_recv(struct composite_context *ctx)
1497 struct wbsrv_samba3_call *s3call =
1498 talloc_get_type(ctx->async.private_data,
1499 struct wbsrv_samba3_call);
1500 NTSTATUS status;
1501 struct dom_sid *sid;
1502 char *sid_str;
1504 DEBUG(5, ("gid2sid_recv called\n"));
1506 status = wb_gid2sid_recv(ctx, s3call, &sid);
1507 if(NT_STATUS_IS_OK(status)) {
1508 sid_str = dom_sid_string(s3call, sid);
1510 if (sid_str == NULL)
1511 wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1513 WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
1514 s3call->response->data.sid.type = SID_NAME_DOMAIN;
1517 wbsrv_samba3_async_epilogue(status, s3call);
1520 static void sids2xids_recv(struct composite_context *ctx)
1522 struct wbsrv_samba3_call *s3call =
1523 talloc_get_type(ctx->async.private_data,
1524 struct wbsrv_samba3_call);
1525 NTSTATUS status;
1526 struct id_map *ids;
1527 unsigned i, count;
1528 struct winbindd_response *resp = s3call->response;
1530 DEBUG(5, ("sids2xids_recv called\n"));
1532 status = wb_sids2xids_recv(ctx, &ids, &count);
1533 if (!NT_STATUS_IS_OK(status)) {
1534 goto done;
1537 /* fill in extra_data with the list of IDs. Each is prefixed
1538 * by 'U' or 'G' for user and group, and followed by a
1539 * newline */
1540 resp->extra_data.data = talloc_strdup(resp, "");
1541 if (resp->extra_data.data == NULL) {
1542 status = NT_STATUS_NO_MEMORY;
1543 goto done;
1546 for (i=0; i<count; i++) {
1547 char type_char = '*';
1548 if (ids[i].status != ID_MAPPED) {
1549 resp->extra_data.data = talloc_asprintf_append_buffer(resp->extra_data.data, "\n");
1550 if (resp->extra_data.data == NULL) {
1551 status = NT_STATUS_NO_MEMORY;
1552 goto done;
1554 continue;
1556 switch (ids[i].xid.type) {
1557 case ID_TYPE_UID:
1558 type_char = 'U';
1559 break;
1560 case ID_TYPE_GID:
1561 type_char = 'G';
1562 break;
1563 case ID_TYPE_BOTH:
1564 type_char = 'B';
1565 break;
1566 case ID_TYPE_NOT_SPECIFIED:
1567 type_char = 'N';
1568 break;
1570 resp->extra_data.data = talloc_asprintf_append_buffer(resp->extra_data.data, "%c%u\n",
1571 type_char, (unsigned)ids[i].xid.id);
1572 if (resp->extra_data.data == NULL) {
1573 status = NT_STATUS_NO_MEMORY;
1574 goto done;
1577 resp->length += strlen(resp->extra_data.data) + 1;
1579 done:
1580 wbsrv_samba3_async_epilogue(status, s3call);
1584 NTSTATUS wbsrv_samba3_sids2xids(struct wbsrv_samba3_call *s3call)
1586 struct composite_context *ctx;
1587 struct wbsrv_service *service =
1588 s3call->wbconn->listen_socket->service;
1589 struct id_map *ids = NULL;
1590 unsigned count = 0;
1591 char *saveptr = NULL;
1592 char *sidstr;
1594 DEBUG(5, ("wbsrv_samba3_sids2xids called\n"));
1596 for (sidstr = strtok_r(s3call->request->extra_data.data, "\n", &saveptr);
1597 sidstr;
1598 sidstr = strtok_r(NULL, "\n", &saveptr)) {
1599 count += 1;
1600 ids = talloc_realloc(s3call, ids, struct id_map, count);
1601 NT_STATUS_HAVE_NO_MEMORY(ids);
1602 ids[count-1].sid = dom_sid_parse_talloc(ids, sidstr);
1603 NT_STATUS_HAVE_NO_MEMORY(ids->sid);
1606 ctx = wb_sids2xids_send(s3call, service, count, ids);
1607 NT_STATUS_HAVE_NO_MEMORY(ctx);
1609 ctx->async.fn = sids2xids_recv;
1610 ctx->async.private_data = s3call;
1611 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1612 return NT_STATUS_OK;