s4-winbind: Correctly reject the unsupported WBFLAG_PAM_AUTH_PAC flag
[Samba.git] / source4 / winbind / wb_samba3_cmd.c
blob4c4033df574ae72178629292a447b276967e0c6d
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 redundant 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 DEBUG(3, ("request interface version (version = %d)\n", WINBIND_INTERFACE_VERSION));
187 s3call->response->result = WINBINDD_OK;
188 s3call->response->data.interface_version = WINBIND_INTERFACE_VERSION;
189 return NT_STATUS_OK;
192 NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
194 s3call->response->result = WINBINDD_OK;
195 s3call->response->data.info.winbind_separator = *lpcfg_winbind_separator(s3call->wbconn->lp_ctx);
196 WBSRV_SAMBA3_SET_STRING(s3call->response->data.info.samba_version,
197 SAMBA_VERSION_STRING);
198 return NT_STATUS_OK;
201 NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
203 s3call->response->result = WINBINDD_OK;
204 WBSRV_SAMBA3_SET_STRING(s3call->response->data.domain_name,
205 lpcfg_workgroup(s3call->wbconn->lp_ctx));
206 return NT_STATUS_OK;
209 NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
211 s3call->response->result = WINBINDD_OK;
212 WBSRV_SAMBA3_SET_STRING(s3call->response->data.netbios_name,
213 lpcfg_netbios_name(s3call->wbconn->lp_ctx));
214 return NT_STATUS_OK;
217 NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
219 struct loadparm_context *lp_ctx = s3call->wbconn->listen_socket->service->task->lp_ctx;
220 const char *priv_socket_dir = lpcfg_winbindd_privileged_socket_directory(lp_ctx);
222 s3call->response->result = WINBINDD_OK;
223 s3call->response->extra_data.data = discard_const(priv_socket_dir);
225 s3call->response->length += strlen(priv_socket_dir) + 1;
226 return NT_STATUS_OK;
229 NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
231 s3call->response->result = WINBINDD_OK;
232 return NT_STATUS_OK;
235 NTSTATUS wbsrv_samba3_domain_info(struct wbsrv_samba3_call *s3call)
237 DEBUG(5, ("wbsrv_samba3_domain_info called, stub\n"));
238 s3call->response->result = WINBINDD_OK;
239 fstrcpy(s3call->response->data.domain_info.name,
240 s3call->request->domain_name);
241 fstrcpy(s3call->response->data.domain_info.alt_name,
242 s3call->request->domain_name);
243 fstrcpy(s3call->response->data.domain_info.sid, "S-1-2-3-4");
244 s3call->response->data.domain_info.native_mode = false;
245 s3call->response->data.domain_info.active_directory = false;
246 s3call->response->data.domain_info.primary = false;
248 return NT_STATUS_OK;
251 /* Plaintext authentication
253 This interface is used by ntlm_auth in it's 'basic' authentication
254 mode, as well as by pam_winbind to authenticate users where we are
255 given a plaintext password.
258 static void check_machacc_recv(struct composite_context *ctx);
260 NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
262 NTSTATUS status;
263 struct cli_credentials *creds;
264 struct composite_context *ctx;
265 struct wbsrv_service *service =
266 s3call->wbconn->listen_socket->service;
268 /* Create a credentials structure */
269 creds = cli_credentials_init(s3call);
270 if (creds == NULL) {
271 return NT_STATUS_NO_MEMORY;
274 cli_credentials_set_conf(creds, service->task->lp_ctx);
276 /* Connect the machine account to the credentials */
277 status = cli_credentials_set_machine_account(creds, service->task->lp_ctx);
278 if (!NT_STATUS_IS_OK(status)) {
279 talloc_free(creds);
280 return status;
283 ctx = wb_cmd_pam_auth_send(s3call, service, creds);
285 if (!ctx) {
286 talloc_free(creds);
287 return NT_STATUS_NO_MEMORY;
290 ctx->async.fn = check_machacc_recv;
291 ctx->async.private_data = s3call;
292 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
293 return NT_STATUS_OK;
296 static void check_machacc_recv(struct composite_context *ctx)
298 struct wbsrv_samba3_call *s3call =
299 talloc_get_type(ctx->async.private_data,
300 struct wbsrv_samba3_call);
301 NTSTATUS status;
303 status = wb_cmd_pam_auth_recv(ctx, s3call, NULL, NULL, NULL, NULL);
305 if (!NT_STATUS_IS_OK(status)) goto done;
307 done:
308 wbsrv_samba3_async_auth_epilogue(status, s3call);
312 Find the name of a suitable domain controller, by query on the
313 netlogon pipe to the DC.
316 static void getdcname_recv_dc(struct composite_context *ctx);
318 NTSTATUS wbsrv_samba3_getdcname(struct wbsrv_samba3_call *s3call)
320 struct composite_context *ctx;
321 struct wbsrv_service *service =
322 s3call->wbconn->listen_socket->service;
324 DEBUG(5, ("wbsrv_samba3_getdcname called\n"));
326 ctx = wb_cmd_getdcname_send(s3call, service,
327 s3call->request->domain_name);
328 NT_STATUS_HAVE_NO_MEMORY(ctx);
330 ctx->async.fn = getdcname_recv_dc;
331 ctx->async.private_data = s3call;
332 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
333 return NT_STATUS_OK;
336 static void getdcname_recv_dc(struct composite_context *ctx)
338 struct wbsrv_samba3_call *s3call =
339 talloc_get_type(ctx->async.private_data,
340 struct wbsrv_samba3_call);
341 const char *dcname;
342 NTSTATUS status;
344 status = wb_cmd_getdcname_recv(ctx, s3call, &dcname);
345 if (!NT_STATUS_IS_OK(status)) goto done;
347 s3call->response->result = WINBINDD_OK;
348 WBSRV_SAMBA3_SET_STRING(s3call->response->data.dc_name, dcname);
350 done:
351 wbsrv_samba3_async_epilogue(status, s3call);
355 Lookup a user's domain groups
358 static void userdomgroups_recv_groups(struct composite_context *ctx);
360 NTSTATUS wbsrv_samba3_userdomgroups(struct wbsrv_samba3_call *s3call)
362 struct composite_context *ctx;
363 struct dom_sid *sid;
365 DEBUG(5, ("wbsrv_samba3_userdomgroups called\n"));
367 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
368 if (sid == NULL) {
369 DEBUG(5, ("Could not parse sid %s\n",
370 s3call->request->data.sid));
371 return NT_STATUS_NO_MEMORY;
374 ctx = wb_cmd_userdomgroups_send(
375 s3call, s3call->wbconn->listen_socket->service, sid);
376 NT_STATUS_HAVE_NO_MEMORY(ctx);
378 ctx->async.fn = userdomgroups_recv_groups;
379 ctx->async.private_data = s3call;
380 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
381 return NT_STATUS_OK;
384 static void userdomgroups_recv_groups(struct composite_context *ctx)
386 struct wbsrv_samba3_call *s3call =
387 talloc_get_type(ctx->async.private_data,
388 struct wbsrv_samba3_call);
389 uint32_t i, num_sids;
390 struct dom_sid **sids;
391 char *sids_string;
392 NTSTATUS status;
394 status = wb_cmd_userdomgroups_recv(ctx, s3call, &num_sids, &sids);
395 if (!NT_STATUS_IS_OK(status)) goto done;
397 sids_string = talloc_strdup(s3call, "");
398 if (sids_string == NULL) {
399 status = NT_STATUS_NO_MEMORY;
400 goto done;
403 for (i=0; i<num_sids; i++) {
404 sids_string = talloc_asprintf_append_buffer(
405 sids_string, "%s\n", dom_sid_string(s3call, sids[i]));
408 if (sids_string == NULL) {
409 status = NT_STATUS_NO_MEMORY;
410 goto done;
413 s3call->response->result = WINBINDD_OK;
414 s3call->response->extra_data.data = sids_string;
415 s3call->response->length += strlen(sids_string)+1;
416 s3call->response->data.num_entries = num_sids;
418 done:
419 wbsrv_samba3_async_epilogue(status, s3call);
423 Lookup the list of SIDs for a user
425 static void usersids_recv_sids(struct composite_context *ctx);
427 NTSTATUS wbsrv_samba3_usersids(struct wbsrv_samba3_call *s3call)
429 struct composite_context *ctx;
430 struct dom_sid *sid;
432 DEBUG(5, ("wbsrv_samba3_usersids called\n"));
434 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
435 if (sid == NULL) {
436 DEBUG(5, ("Could not parse sid %s\n",
437 s3call->request->data.sid));
438 return NT_STATUS_NO_MEMORY;
441 ctx = wb_cmd_usersids_send(
442 s3call, s3call->wbconn->listen_socket->service, sid);
443 NT_STATUS_HAVE_NO_MEMORY(ctx);
445 ctx->async.fn = usersids_recv_sids;
446 ctx->async.private_data = s3call;
447 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
448 return NT_STATUS_OK;
451 static void usersids_recv_sids(struct composite_context *ctx)
453 struct wbsrv_samba3_call *s3call =
454 talloc_get_type(ctx->async.private_data,
455 struct wbsrv_samba3_call);
456 uint32_t i, num_sids;
457 struct dom_sid **sids;
458 char *sids_string;
459 NTSTATUS status;
461 status = wb_cmd_usersids_recv(ctx, s3call, &num_sids, &sids);
462 if (!NT_STATUS_IS_OK(status)) goto done;
464 sids_string = talloc_strdup(s3call, "");
465 if (sids_string == NULL) {
466 status = NT_STATUS_NO_MEMORY;
467 goto done;
470 for (i=0; i<num_sids; i++) {
471 sids_string = talloc_asprintf_append_buffer(
472 sids_string, "%s\n", dom_sid_string(s3call, sids[i]));
473 if (sids_string == NULL) {
474 status = NT_STATUS_NO_MEMORY;
475 goto done;
479 s3call->response->result = WINBINDD_OK;
480 s3call->response->extra_data.data = sids_string;
481 s3call->response->length += strlen(sids_string);
482 s3call->response->data.num_entries = num_sids;
484 /* Hmmmm. Nasty protocol -- who invented the zeros between the
485 * SIDs? Hmmm. Could have been me -- vl */
487 while (*sids_string != '\0') {
488 if ((*sids_string) == '\n') {
489 *sids_string = '\0';
491 sids_string += 1;
494 done:
495 wbsrv_samba3_async_epilogue(status, s3call);
499 Lookup a DOMAIN\\user style name, and return a SID
502 static void lookupname_recv_sid(struct composite_context *ctx);
504 NTSTATUS wbsrv_samba3_lookupname(struct wbsrv_samba3_call *s3call)
506 struct composite_context *ctx;
507 struct wbsrv_service *service =
508 s3call->wbconn->listen_socket->service;
510 DEBUG(5, ("wbsrv_samba3_lookupname called\n"));
512 ctx = wb_cmd_lookupname_send(s3call, service,
513 s3call->request->data.name.dom_name,
514 s3call->request->data.name.name);
515 NT_STATUS_HAVE_NO_MEMORY(ctx);
517 /* setup the callbacks */
518 ctx->async.fn = lookupname_recv_sid;
519 ctx->async.private_data = s3call;
520 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
521 return NT_STATUS_OK;
524 static void lookupname_recv_sid(struct composite_context *ctx)
526 struct wbsrv_samba3_call *s3call =
527 talloc_get_type(ctx->async.private_data,
528 struct wbsrv_samba3_call);
529 struct wb_sid_object *sid;
530 NTSTATUS status;
532 status = wb_cmd_lookupname_recv(ctx, s3call, &sid);
533 if (!NT_STATUS_IS_OK(status)) goto done;
535 s3call->response->result = WINBINDD_OK;
536 s3call->response->data.sid.type = sid->type;
537 WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid,
538 dom_sid_string(s3call, sid->sid));
540 done:
541 wbsrv_samba3_async_epilogue(status, s3call);
545 Lookup a SID, and return a DOMAIN\\user style name
548 static void lookupsid_recv_name(struct composite_context *ctx);
550 NTSTATUS wbsrv_samba3_lookupsid(struct wbsrv_samba3_call *s3call)
552 struct composite_context *ctx;
553 struct wbsrv_service *service =
554 s3call->wbconn->listen_socket->service;
555 struct dom_sid *sid;
557 DEBUG(5, ("wbsrv_samba3_lookupsid called\n"));
559 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
560 if (sid == NULL) {
561 DEBUG(5, ("Could not parse sid %s\n",
562 s3call->request->data.sid));
563 return NT_STATUS_NO_MEMORY;
566 ctx = wb_cmd_lookupsid_send(s3call, service, sid);
567 NT_STATUS_HAVE_NO_MEMORY(ctx);
569 /* setup the callbacks */
570 ctx->async.fn = lookupsid_recv_name;
571 ctx->async.private_data = s3call;
572 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
573 return NT_STATUS_OK;
576 static void lookupsid_recv_name(struct composite_context *ctx)
578 struct wbsrv_samba3_call *s3call =
579 talloc_get_type(ctx->async.private_data,
580 struct wbsrv_samba3_call);
581 struct wb_sid_object *sid;
582 NTSTATUS status;
584 status = wb_cmd_lookupsid_recv(ctx, s3call, &sid);
585 if (!NT_STATUS_IS_OK(status)) goto done;
587 s3call->response->result = WINBINDD_OK;
588 s3call->response->data.name.type = sid->type;
589 WBSRV_SAMBA3_SET_STRING(s3call->response->data.name.dom_name,
590 sid->domain);
591 WBSRV_SAMBA3_SET_STRING(s3call->response->data.name.name, sid->name);
593 done:
594 wbsrv_samba3_async_epilogue(status, s3call);
598 This is a stub function in order to limit error message in the pam_winbind module
600 NTSTATUS wbsrv_samba3_pam_logoff(struct wbsrv_samba3_call *s3call)
602 NTSTATUS status;
603 struct winbindd_response *resp = s3call->response;
605 status = NT_STATUS_OK;
607 DEBUG(5, ("wbsrv_samba3_pam_logoff called\n"));
608 DEBUG(10, ("Winbind logoff not implemented\n"));
609 resp->result = WINBINDD_OK;
611 WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
612 nt_errstr(status));
613 WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
614 get_friendly_nt_error_msg(status));
616 resp->data.auth.pam_error = nt_status_to_pam(status);
617 resp->data.auth.nt_status = NT_STATUS_V(status);
618 DEBUG(5, ("wbsrv_samba3_pam_logoff called\n"));
620 return NT_STATUS_OK;
624 Challenge-response authentication. This interface is used by
625 ntlm_auth and the smbd auth subsystem to pass NTLM authentication
626 requests along a common pipe to the domain controller.
628 The return value (in the async reply) may include the 'info3'
629 (effectivly most things you would want to know about the user), or
630 the NT and LM session keys separated.
633 static void pam_auth_crap_recv(struct composite_context *ctx);
635 NTSTATUS wbsrv_samba3_pam_auth_crap(struct wbsrv_samba3_call *s3call)
637 struct composite_context *ctx;
638 struct wbsrv_service *service =
639 s3call->wbconn->listen_socket->service;
640 DATA_BLOB chal, nt_resp, lm_resp;
642 DEBUG(5, ("wbsrv_samba3_pam_auth_crap called\n"));
643 if (s3call->request->flags & WBFLAG_PAM_AUTH_PAC) {
644 DEBUG(3, ("PAC validation not supported in this winbind implementation\n"));
645 return NT_STATUS_INVALID_PARAMETER;
648 chal.data = s3call->request->data.auth_crap.chal;
649 chal.length = sizeof(s3call->request->data.auth_crap.chal);
650 nt_resp.data = (uint8_t *)s3call->request->data.auth_crap.nt_resp;
651 nt_resp.length = s3call->request->data.auth_crap.nt_resp_len;
652 lm_resp.data = (uint8_t *)s3call->request->data.auth_crap.lm_resp;
653 lm_resp.length = s3call->request->data.auth_crap.lm_resp_len;
655 ctx = wb_cmd_pam_auth_crap_send(
656 s3call, service,
657 s3call->request->data.auth_crap.logon_parameters,
658 s3call->request->data.auth_crap.domain,
659 s3call->request->data.auth_crap.user,
660 s3call->request->data.auth_crap.workstation,
661 chal, nt_resp, lm_resp);
662 NT_STATUS_HAVE_NO_MEMORY(ctx);
664 ctx->async.fn = pam_auth_crap_recv;
665 ctx->async.private_data = s3call;
666 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
667 return NT_STATUS_OK;
670 static void pam_auth_crap_recv(struct composite_context *ctx)
672 struct wbsrv_samba3_call *s3call =
673 talloc_get_type(ctx->async.private_data,
674 struct wbsrv_samba3_call);
675 NTSTATUS status;
676 DATA_BLOB info3;
677 struct netr_UserSessionKey user_session_key;
678 struct netr_LMSessionKey lm_key;
679 char *unix_username;
681 status = wb_cmd_pam_auth_crap_recv(ctx, s3call, &info3,
682 &user_session_key, &lm_key, &unix_username);
683 if (!NT_STATUS_IS_OK(status)) goto done;
685 if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
686 memcpy(s3call->response->data.auth.user_session_key,
687 &user_session_key.key,
688 sizeof(s3call->response->data.auth.user_session_key));
691 if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
692 status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
693 if (!NT_STATUS_IS_OK(status)) {
694 DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
695 nt_errstr(status)));
696 goto done;
700 if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
701 s3call->response->extra_data.data = info3.data;
702 s3call->response->length += info3.length;
705 if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
706 memcpy(s3call->response->data.auth.first_8_lm_hash,
707 lm_key.key,
708 sizeof(s3call->response->data.auth.first_8_lm_hash));
711 if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
712 WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
715 done:
716 wbsrv_samba3_async_auth_epilogue(status, s3call);
719 /* Plaintext authentication
721 This interface is used by ntlm_auth in it's 'basic' authentication
722 mode, as well as by pam_winbind to authenticate users where we are
723 given a plaintext password.
726 static void pam_auth_recv(struct composite_context *ctx);
728 NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
730 struct composite_context *ctx;
731 struct wbsrv_service *service =
732 s3call->wbconn->listen_socket->service;
733 struct cli_credentials *credentials;
734 char *user, *domain;
736 if (!wb_samba3_split_username(s3call, s3call->wbconn->lp_ctx,
737 s3call->request->data.auth.user,
738 &domain, &user)) {
739 return NT_STATUS_NO_SUCH_USER;
742 credentials = cli_credentials_init(s3call);
743 if (!credentials) {
744 return NT_STATUS_NO_MEMORY;
746 cli_credentials_set_conf(credentials, service->task->lp_ctx);
747 cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
748 cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
750 cli_credentials_set_password(credentials, s3call->request->data.auth.pass, CRED_SPECIFIED);
752 ctx = wb_cmd_pam_auth_send(s3call, service, credentials);
753 NT_STATUS_HAVE_NO_MEMORY(ctx);
755 ctx->async.fn = pam_auth_recv;
756 ctx->async.private_data = s3call;
757 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
758 return NT_STATUS_OK;
761 static void pam_auth_recv(struct composite_context *ctx)
763 struct wbsrv_samba3_call *s3call =
764 talloc_get_type(ctx->async.private_data,
765 struct wbsrv_samba3_call);
766 NTSTATUS status;
767 DATA_BLOB info3;
768 struct netr_UserSessionKey user_session_key;
769 struct netr_LMSessionKey lm_key;
770 char *unix_username;
772 status = wb_cmd_pam_auth_recv(ctx, s3call, &info3,
773 &user_session_key, &lm_key, &unix_username);
775 if (!NT_STATUS_IS_OK(status)) goto done;
777 if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
778 memcpy(s3call->response->data.auth.user_session_key,
779 &user_session_key.key,
780 sizeof(s3call->response->data.auth.user_session_key));
783 if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
784 status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
785 if (!NT_STATUS_IS_OK(status)) {
786 DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
787 nt_errstr(status)));
788 goto done;
792 if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
793 s3call->response->extra_data.data = info3.data;
794 s3call->response->length += info3.length;
797 if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
798 memcpy(s3call->response->data.auth.first_8_lm_hash,
799 lm_key.key,
800 sizeof(s3call->response->data.auth.first_8_lm_hash));
803 if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
804 WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
808 done:
809 wbsrv_samba3_async_auth_epilogue(status, s3call);
813 List trusted domains
816 static void list_trustdom_recv_doms(struct composite_context *ctx);
818 NTSTATUS wbsrv_samba3_list_trustdom(struct wbsrv_samba3_call *s3call)
820 struct composite_context *ctx;
821 struct wbsrv_service *service =
822 s3call->wbconn->listen_socket->service;
824 DEBUG(5, ("wbsrv_samba3_list_trustdom called\n"));
826 ctx = wb_cmd_list_trustdoms_send(s3call, service);
827 NT_STATUS_HAVE_NO_MEMORY(ctx);
829 ctx->async.fn = list_trustdom_recv_doms;
830 ctx->async.private_data = s3call;
831 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
832 return NT_STATUS_OK;
835 static void list_trustdom_recv_doms(struct composite_context *ctx)
837 struct wbsrv_samba3_call *s3call =
838 talloc_get_type(ctx->async.private_data,
839 struct wbsrv_samba3_call);
840 uint32_t i, num_domains;
841 struct wb_dom_info **domains;
842 NTSTATUS status;
843 char *result;
845 status = wb_cmd_list_trustdoms_recv(ctx, s3call, &num_domains,
846 &domains);
847 if (!NT_STATUS_IS_OK(status)) goto done;
849 result = talloc_strdup(s3call, "");
850 if (result == NULL) {
851 status = NT_STATUS_NO_MEMORY;
852 goto done;
855 for (i=0; i<num_domains; i++) {
856 result = talloc_asprintf_append_buffer(
857 result, "%s\\%s\\%s",
858 domains[i]->name, domains[i]->name,
859 dom_sid_string(s3call, domains[i]->sid));
862 if (result == NULL) {
863 status = NT_STATUS_NO_MEMORY;
864 goto done;
867 s3call->response->result = WINBINDD_OK;
868 if (num_domains > 0) {
869 s3call->response->extra_data.data = result;
870 s3call->response->length += strlen(result)+1;
871 s3call->response->data.num_entries = num_domains;
874 done:
875 wbsrv_samba3_async_epilogue(status, s3call);
878 /* list groups */
879 static void list_groups_recv(struct composite_context *ctx);
881 NTSTATUS wbsrv_samba3_list_groups(struct wbsrv_samba3_call *s3call)
883 struct composite_context *ctx;
884 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
886 DEBUG(5, ("wbsrv_samba4_list_groups called\n"));
888 ctx = wb_cmd_list_groups_send(s3call, service,
889 s3call->request->domain_name);
890 NT_STATUS_HAVE_NO_MEMORY(ctx);
892 ctx->async.fn = list_groups_recv;
893 ctx->async.private_data = s3call;
894 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
895 return NT_STATUS_OK;
898 static void list_groups_recv(struct composite_context *ctx)
900 struct wbsrv_samba3_call *s3call = talloc_get_type_abort(
901 ctx->async.private_data,
902 struct wbsrv_samba3_call);
903 uint32_t extra_data_len;
904 char *extra_data;
905 uint32_t num_groups;
906 NTSTATUS status;
908 DEBUG(5, ("list_groups_recv called\n"));
910 status = wb_cmd_list_groups_recv(ctx, s3call, &extra_data_len,
911 &extra_data, &num_groups);
913 if (NT_STATUS_IS_OK(status)) {
914 s3call->response->extra_data.data = extra_data;
915 s3call->response->length += extra_data_len;
916 if (extra_data) {
917 s3call->response->length += 1;
918 s3call->response->data.num_entries = num_groups;
922 wbsrv_samba3_async_epilogue(status, s3call);
925 /* List users */
927 static void list_users_recv(struct composite_context *ctx);
929 NTSTATUS wbsrv_samba3_list_users(struct wbsrv_samba3_call *s3call)
931 struct composite_context *ctx;
932 struct wbsrv_service *service =
933 s3call->wbconn->listen_socket->service;
935 DEBUG(5, ("wbsrv_samba3_list_users called\n"));
937 ctx = wb_cmd_list_users_send(s3call, service,
938 s3call->request->domain_name);
939 NT_STATUS_HAVE_NO_MEMORY(ctx);
941 ctx->async.fn = list_users_recv;
942 ctx->async.private_data = s3call;
943 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
944 return NT_STATUS_OK;
947 static void list_users_recv(struct composite_context *ctx)
949 struct wbsrv_samba3_call *s3call =
950 talloc_get_type(ctx->async.private_data,
951 struct wbsrv_samba3_call);
952 uint32_t extra_data_len;
953 char *extra_data;
954 uint32_t num_users;
955 NTSTATUS status;
957 DEBUG(5, ("list_users_recv called\n"));
959 status = wb_cmd_list_users_recv(ctx, s3call, &extra_data_len,
960 &extra_data, &num_users);
962 if (NT_STATUS_IS_OK(status)) {
963 s3call->response->extra_data.data = extra_data;
964 s3call->response->length += extra_data_len;
965 if (extra_data) {
966 s3call->response->length += 1;
967 s3call->response->data.num_entries = num_users;
971 wbsrv_samba3_async_epilogue(status, s3call);
974 /* NSS calls */
976 static void getpwnam_recv(struct composite_context *ctx);
978 NTSTATUS wbsrv_samba3_getpwnam(struct wbsrv_samba3_call *s3call)
980 struct composite_context *ctx;
981 struct wbsrv_service *service =
982 s3call->wbconn->listen_socket->service;
984 DEBUG(5, ("wbsrv_samba3_getpwnam called\n"));
986 ctx = wb_cmd_getpwnam_send(s3call, service,
987 s3call->request->data.username);
988 NT_STATUS_HAVE_NO_MEMORY(ctx);
990 ctx->async.fn = getpwnam_recv;
991 ctx->async.private_data = s3call;
992 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
993 return NT_STATUS_OK;
996 static void getpwnam_recv(struct composite_context *ctx)
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;
1004 DEBUG(5, ("getpwnam_recv called\n"));
1006 status = wb_cmd_getpwnam_recv(ctx, s3call, &pw);
1007 if(NT_STATUS_IS_OK(status))
1008 s3call->response->data.pw = *pw;
1010 wbsrv_samba3_async_epilogue(status, s3call);
1013 static void getpwuid_recv(struct composite_context *ctx);
1015 NTSTATUS wbsrv_samba3_getpwuid(struct wbsrv_samba3_call *s3call)
1017 struct composite_context *ctx;
1018 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1020 DEBUG(5, ("wbsrv_samba3_getpwuid called\n"));
1022 ctx = wb_cmd_getpwuid_send(s3call, service,
1023 s3call->request->data.uid);
1024 NT_STATUS_HAVE_NO_MEMORY(ctx);
1026 ctx->async.fn = getpwuid_recv;
1027 ctx->async.private_data = s3call;
1028 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1029 return NT_STATUS_OK;
1032 static void getpwuid_recv(struct composite_context *ctx)
1034 struct wbsrv_samba3_call *s3call =
1035 talloc_get_type(ctx->async.private_data,
1036 struct wbsrv_samba3_call);
1037 NTSTATUS status;
1038 struct winbindd_pw *pw;
1040 DEBUG(5, ("getpwuid_recv called\n"));
1042 status = wb_cmd_getpwuid_recv(ctx, s3call, &pw);
1043 if (NT_STATUS_IS_OK(status))
1044 s3call->response->data.pw = *pw;
1046 wbsrv_samba3_async_epilogue(status, s3call);
1049 static void setpwent_recv(struct composite_context *ctx);
1051 NTSTATUS wbsrv_samba3_setpwent(struct wbsrv_samba3_call *s3call)
1053 struct composite_context *ctx;
1054 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1056 DEBUG(5, ("wbsrv_samba3_setpwent called\n"));
1058 ctx = wb_cmd_setpwent_send(s3call, service);
1059 NT_STATUS_HAVE_NO_MEMORY(ctx);
1061 ctx->async.fn = setpwent_recv;
1062 ctx->async.private_data = s3call;
1063 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1064 return NT_STATUS_OK;
1067 static void setpwent_recv(struct composite_context *ctx)
1069 struct wbsrv_samba3_call *s3call =
1070 talloc_get_type(ctx->async.private_data,
1071 struct wbsrv_samba3_call);
1072 NTSTATUS status;
1073 struct wbsrv_pwent *pwent;
1075 DEBUG(5, ("setpwent_recv called\n"));
1077 status = wb_cmd_setpwent_recv(ctx, s3call->wbconn, &pwent);
1078 if (NT_STATUS_IS_OK(status)) {
1079 s3call->wbconn->protocol_private_data = pwent;
1082 wbsrv_samba3_async_epilogue(status, s3call);
1085 static void getpwent_recv(struct composite_context *ctx);
1087 NTSTATUS wbsrv_samba3_getpwent(struct wbsrv_samba3_call *s3call)
1089 struct composite_context *ctx;
1090 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1091 struct wbsrv_pwent *pwent;
1093 DEBUG(5, ("wbsrv_samba3_getpwent called\n"));
1095 NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
1097 pwent = talloc_get_type(s3call->wbconn->protocol_private_data,
1098 struct wbsrv_pwent);
1099 NT_STATUS_HAVE_NO_MEMORY(pwent);
1101 ctx = wb_cmd_getpwent_send(s3call, service, pwent,
1102 s3call->request->data.num_entries);
1103 NT_STATUS_HAVE_NO_MEMORY(ctx);
1105 ctx->async.fn = getpwent_recv;
1106 ctx->async.private_data = s3call;
1107 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1108 return NT_STATUS_OK;
1111 static void getpwent_recv(struct composite_context *ctx)
1113 struct wbsrv_samba3_call *s3call =
1114 talloc_get_type(ctx->async.private_data,
1115 struct wbsrv_samba3_call);
1116 NTSTATUS status;
1117 struct winbindd_pw *pw;
1118 uint32_t num_users;
1120 DEBUG(5, ("getpwent_recv called\n"));
1122 status = wb_cmd_getpwent_recv(ctx, s3call, &pw, &num_users);
1123 if (NT_STATUS_IS_OK(status)) {
1124 uint32_t extra_len = sizeof(struct winbindd_pw) * num_users;
1126 s3call->response->data.num_entries = num_users;
1127 s3call->response->extra_data.data = pw;
1128 s3call->response->length += extra_len;
1131 wbsrv_samba3_async_epilogue(status, s3call);
1134 NTSTATUS wbsrv_samba3_endpwent(struct wbsrv_samba3_call *s3call)
1136 struct wbsrv_pwent *pwent =
1137 talloc_get_type(s3call->wbconn->protocol_private_data,
1138 struct wbsrv_pwent);
1139 DEBUG(5, ("wbsrv_samba3_endpwent called\n"));
1141 talloc_free(pwent);
1143 s3call->wbconn->protocol_private_data = NULL;
1144 s3call->response->result = WINBINDD_OK;
1145 return NT_STATUS_OK;
1149 static void getgrnam_recv(struct composite_context *ctx);
1151 NTSTATUS wbsrv_samba3_getgrnam(struct wbsrv_samba3_call *s3call)
1153 struct composite_context *ctx;
1154 struct wbsrv_service *service =
1155 s3call->wbconn->listen_socket->service;
1157 DEBUG(5, ("wbsrv_samba3_getgrnam called\n"));
1159 ctx = wb_cmd_getgrnam_send(s3call, service,
1160 s3call->request->data.groupname);
1161 NT_STATUS_HAVE_NO_MEMORY(ctx);
1163 ctx->async.fn = getgrnam_recv;
1164 ctx->async.private_data = s3call;
1165 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1166 return NT_STATUS_OK;
1169 static void getgrnam_recv(struct composite_context *ctx)
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;
1177 DEBUG(5, ("getgrnam_recv called\n"));
1179 status = wb_cmd_getgrnam_recv(ctx, s3call, &gr);
1180 if(NT_STATUS_IS_OK(status))
1181 s3call->response->data.gr = *gr;
1183 wbsrv_samba3_async_epilogue(status, s3call);
1186 static void getgrgid_recv(struct composite_context *ctx);
1188 NTSTATUS wbsrv_samba3_getgrgid(struct wbsrv_samba3_call *s3call)
1190 struct composite_context *ctx;
1191 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1193 DEBUG(5, ("wbsrv_samba3_getgrgid called\n"));
1195 ctx = wb_cmd_getgrgid_send(s3call, service,
1196 s3call->request->data.gid);
1197 NT_STATUS_HAVE_NO_MEMORY(ctx);
1199 ctx->async.fn = getgrgid_recv;
1200 ctx->async.private_data = s3call;
1201 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1202 return NT_STATUS_OK;
1205 static void getgrgid_recv(struct composite_context *ctx)
1207 struct wbsrv_samba3_call *s3call =
1208 talloc_get_type(ctx->async.private_data,
1209 struct wbsrv_samba3_call);
1210 NTSTATUS status;
1211 struct winbindd_gr *gr;
1213 DEBUG(5, ("getgrgid_recv called\n"));
1215 status = wb_cmd_getgrgid_recv(ctx, s3call, &gr);
1216 if (NT_STATUS_IS_OK(status))
1217 s3call->response->data.gr = *gr;
1219 wbsrv_samba3_async_epilogue(status, s3call);
1222 static void getgroups_recv(struct composite_context *ctx);
1224 NTSTATUS wbsrv_samba3_getgroups(struct wbsrv_samba3_call *s3call)
1226 struct composite_context *ctx;
1227 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1229 DEBUG(5, ("wbsrv_samba3_getgroups called\n"));
1230 /* S3 code do the same so why not ... */
1231 s3call->request->data.username[sizeof(s3call->request->data.username)-1]='\0';
1232 ctx = wb_cmd_getgroups_send(s3call, service, s3call->request->data.username);
1233 NT_STATUS_HAVE_NO_MEMORY(ctx);
1235 ctx->async.fn = getgroups_recv;
1236 ctx->async.private_data = s3call;
1237 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1238 return NT_STATUS_OK;
1241 static void getgroups_recv(struct composite_context *ctx)
1243 struct wbsrv_samba3_call *s3call =
1244 talloc_get_type(ctx->async.private_data,
1245 struct wbsrv_samba3_call);
1246 gid_t *gids;
1247 uint32_t num_groups;
1248 NTSTATUS status;
1249 DEBUG(5, ("getgroups_recv called\n"));
1251 status = wb_cmd_getgroups_recv(ctx, s3call, &gids, &num_groups);
1252 if (NT_STATUS_IS_OK(status)) {
1253 uint32_t extra_len = sizeof(gid_t) * num_groups;
1255 s3call->response->data.num_entries = num_groups;
1256 s3call->response->extra_data.data = gids;
1257 s3call->response->length += extra_len;
1258 } else {
1259 s3call->response->result = WINBINDD_ERROR;
1262 wbsrv_samba3_async_epilogue(status, s3call);
1265 static void setgrent_recv(struct composite_context *ctx);
1267 NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
1269 struct composite_context *ctx;
1270 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1272 DEBUG(5, ("wbsrv_samba3_setgrent called\n"));
1274 ctx = wb_cmd_setgrent_send(s3call, service);
1275 NT_STATUS_HAVE_NO_MEMORY(ctx);
1277 ctx->async.fn = setgrent_recv;
1278 ctx->async.private_data = s3call;
1279 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1280 return NT_STATUS_OK;
1283 static void setgrent_recv(struct composite_context *ctx)
1285 struct wbsrv_samba3_call *s3call =
1286 talloc_get_type(ctx->async.private_data,
1287 struct wbsrv_samba3_call);
1288 NTSTATUS status;
1289 struct wbsrv_grent *grent;
1291 DEBUG(5, ("setpwent_recv called\n"));
1293 status = wb_cmd_setgrent_recv(ctx, s3call->wbconn, &grent);
1294 if (NT_STATUS_IS_OK(status)) {
1295 s3call->wbconn->protocol_private_data = grent;
1298 wbsrv_samba3_async_epilogue(status, s3call);
1301 static void getgrent_recv(struct composite_context *ctx);
1303 NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
1305 struct composite_context *ctx;
1306 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1307 struct wbsrv_grent *grent;
1309 DEBUG(5, ("wbsrv_samba3_getgrent called\n"));
1311 NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
1313 grent = talloc_get_type(s3call->wbconn->protocol_private_data,
1314 struct wbsrv_grent);
1315 NT_STATUS_HAVE_NO_MEMORY(grent);
1317 ctx = wb_cmd_getgrent_send(s3call, service, grent,
1318 s3call->request->data.num_entries);
1319 NT_STATUS_HAVE_NO_MEMORY(ctx);
1321 ctx->async.fn = getgrent_recv;
1322 ctx->async.private_data = s3call;
1323 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1324 return NT_STATUS_OK;
1327 static void getgrent_recv(struct composite_context *ctx)
1329 struct wbsrv_samba3_call *s3call =
1330 talloc_get_type(ctx->async.private_data,
1331 struct wbsrv_samba3_call);
1332 NTSTATUS status;
1333 struct winbindd_gr *gr;
1334 uint32_t num_groups;
1336 DEBUG(5, ("getgrent_recv called\n"));
1338 status = wb_cmd_getgrent_recv(ctx, s3call, &gr, &num_groups);
1339 if (NT_STATUS_IS_OK(status)) {
1340 uint32_t extra_len = sizeof(struct winbindd_gr) * num_groups;
1342 s3call->response->data.num_entries = num_groups;
1343 s3call->response->extra_data.data = gr;
1344 s3call->response->length += extra_len;
1347 wbsrv_samba3_async_epilogue(status, s3call);
1350 NTSTATUS wbsrv_samba3_endgrent(struct wbsrv_samba3_call *s3call)
1352 DEBUG(5, ("wbsrv_samba3_endgrent called\n"));
1353 s3call->response->result = WINBINDD_OK;
1354 return NT_STATUS_OK;
1357 static void sid2uid_recv(struct composite_context *ctx);
1359 NTSTATUS wbsrv_samba3_sid2uid(struct wbsrv_samba3_call *s3call)
1361 struct composite_context *ctx;
1362 struct wbsrv_service *service =
1363 s3call->wbconn->listen_socket->service;
1364 struct dom_sid *sid;
1366 DEBUG(5, ("wbsrv_samba3_sid2uid called\n"));
1368 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
1369 NT_STATUS_HAVE_NO_MEMORY(sid);
1371 ctx = wb_sid2uid_send(s3call, service, sid);
1372 NT_STATUS_HAVE_NO_MEMORY(ctx);
1374 ctx->async.fn = sid2uid_recv;
1375 ctx->async.private_data = s3call;
1376 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1377 return NT_STATUS_OK;
1381 static void sid2uid_recv(struct composite_context *ctx)
1383 struct wbsrv_samba3_call *s3call =
1384 talloc_get_type(ctx->async.private_data,
1385 struct wbsrv_samba3_call);
1386 NTSTATUS status;
1388 DEBUG(5, ("sid2uid_recv called\n"));
1390 status = wb_sid2uid_recv(ctx, &s3call->response->data.uid);
1392 wbsrv_samba3_async_epilogue(status, s3call);
1395 static void sid2gid_recv(struct composite_context *ctx);
1397 NTSTATUS wbsrv_samba3_sid2gid(struct wbsrv_samba3_call *s3call)
1399 struct composite_context *ctx;
1400 struct wbsrv_service *service =
1401 s3call->wbconn->listen_socket->service;
1402 struct dom_sid *sid;
1404 DEBUG(5, ("wbsrv_samba3_sid2gid called\n"));
1406 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
1407 NT_STATUS_HAVE_NO_MEMORY(sid);
1409 ctx = wb_sid2gid_send(s3call, service, sid);
1410 NT_STATUS_HAVE_NO_MEMORY(ctx);
1412 ctx->async.fn = sid2gid_recv;
1413 ctx->async.private_data = s3call;
1414 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1415 return NT_STATUS_OK;
1419 static void sid2gid_recv(struct composite_context *ctx)
1421 struct wbsrv_samba3_call *s3call =
1422 talloc_get_type(ctx->async.private_data,
1423 struct wbsrv_samba3_call);
1424 NTSTATUS status;
1426 DEBUG(5, ("sid2gid_recv called\n"));
1428 status = wb_sid2gid_recv(ctx, &s3call->response->data.gid);
1430 wbsrv_samba3_async_epilogue(status, s3call);
1433 static void uid2sid_recv(struct composite_context *ctx);
1435 NTSTATUS wbsrv_samba3_uid2sid(struct wbsrv_samba3_call *s3call)
1437 struct composite_context *ctx;
1438 struct wbsrv_service *service =
1439 s3call->wbconn->listen_socket->service;
1441 DEBUG(5, ("wbsrv_samba3_uid2sid called\n"));
1443 ctx = wb_uid2sid_send(s3call, service, s3call->request->data.uid);
1444 NT_STATUS_HAVE_NO_MEMORY(ctx);
1446 ctx->async.fn = uid2sid_recv;
1447 ctx->async.private_data = s3call;
1448 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1449 return NT_STATUS_OK;
1453 static void uid2sid_recv(struct composite_context *ctx)
1455 struct wbsrv_samba3_call *s3call =
1456 talloc_get_type(ctx->async.private_data,
1457 struct wbsrv_samba3_call);
1458 NTSTATUS status;
1459 struct dom_sid *sid;
1460 char *sid_str;
1462 DEBUG(5, ("uid2sid_recv called\n"));
1464 status = wb_uid2sid_recv(ctx, s3call, &sid);
1465 if(NT_STATUS_IS_OK(status)) {
1466 sid_str = dom_sid_string(s3call, sid);
1468 /* If the conversion failed, bail out with a failure. */
1469 if (sid_str == NULL)
1470 wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1472 /* But we assume this worked, so we'll set the string. Work
1473 * done. */
1474 WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
1475 s3call->response->data.sid.type = SID_NAME_USER;
1478 wbsrv_samba3_async_epilogue(status, s3call);
1481 static void gid2sid_recv(struct composite_context *ctx);
1483 NTSTATUS wbsrv_samba3_gid2sid(struct wbsrv_samba3_call *s3call)
1485 struct composite_context *ctx;
1486 struct wbsrv_service *service =
1487 s3call->wbconn->listen_socket->service;
1489 DEBUG(5, ("wbsrv_samba3_gid2sid called\n"));
1491 ctx = wb_gid2sid_send(s3call, service, s3call->request->data.gid);
1492 NT_STATUS_HAVE_NO_MEMORY(ctx);
1494 ctx->async.fn = gid2sid_recv;
1495 ctx->async.private_data = s3call;
1496 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1497 return NT_STATUS_OK;
1501 static void gid2sid_recv(struct composite_context *ctx)
1503 struct wbsrv_samba3_call *s3call =
1504 talloc_get_type(ctx->async.private_data,
1505 struct wbsrv_samba3_call);
1506 NTSTATUS status;
1507 struct dom_sid *sid;
1508 char *sid_str;
1510 DEBUG(5, ("gid2sid_recv called\n"));
1512 status = wb_gid2sid_recv(ctx, s3call, &sid);
1513 if(NT_STATUS_IS_OK(status)) {
1514 sid_str = dom_sid_string(s3call, sid);
1516 if (sid_str == NULL)
1517 wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1519 WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
1520 s3call->response->data.sid.type = SID_NAME_DOMAIN;
1523 wbsrv_samba3_async_epilogue(status, s3call);
1526 static void sids2xids_recv(struct composite_context *ctx)
1528 struct wbsrv_samba3_call *s3call =
1529 talloc_get_type(ctx->async.private_data,
1530 struct wbsrv_samba3_call);
1531 NTSTATUS status;
1532 struct id_map *ids;
1533 unsigned i, count;
1534 struct winbindd_response *resp = s3call->response;
1536 DEBUG(5, ("sids2xids_recv called\n"));
1538 status = wb_sids2xids_recv(ctx, &ids, &count);
1539 if (!NT_STATUS_IS_OK(status)) {
1540 goto done;
1543 /* fill in extra_data with the list of IDs. Each is prefixed
1544 * by 'U' or 'G' for user and group, and followed by a
1545 * newline */
1546 resp->extra_data.data = talloc_strdup(resp, "");
1547 if (resp->extra_data.data == NULL) {
1548 status = NT_STATUS_NO_MEMORY;
1549 goto done;
1552 for (i=0; i<count; i++) {
1553 char type_char = '*';
1554 if (ids[i].status != ID_MAPPED) {
1555 resp->extra_data.data = talloc_asprintf_append_buffer(resp->extra_data.data, "\n");
1556 if (resp->extra_data.data == NULL) {
1557 status = NT_STATUS_NO_MEMORY;
1558 goto done;
1560 continue;
1562 switch (ids[i].xid.type) {
1563 case ID_TYPE_UID:
1564 type_char = 'U';
1565 break;
1566 case ID_TYPE_GID:
1567 type_char = 'G';
1568 break;
1569 case ID_TYPE_BOTH:
1570 type_char = 'B';
1571 break;
1572 case ID_TYPE_NOT_SPECIFIED:
1573 type_char = 'N';
1574 break;
1576 resp->extra_data.data = talloc_asprintf_append_buffer(resp->extra_data.data, "%c%u\n",
1577 type_char, (unsigned)ids[i].xid.id);
1578 if (resp->extra_data.data == NULL) {
1579 status = NT_STATUS_NO_MEMORY;
1580 goto done;
1583 resp->length += strlen(resp->extra_data.data) + 1;
1585 done:
1586 wbsrv_samba3_async_epilogue(status, s3call);
1590 NTSTATUS wbsrv_samba3_sids2xids(struct wbsrv_samba3_call *s3call)
1592 struct composite_context *ctx;
1593 struct wbsrv_service *service =
1594 s3call->wbconn->listen_socket->service;
1595 struct id_map *ids = NULL;
1596 unsigned count = 0;
1597 char *saveptr = NULL;
1598 char *sidstr;
1600 DEBUG(5, ("wbsrv_samba3_sids2xids called\n"));
1602 for (sidstr = strtok_r(s3call->request->extra_data.data, "\n", &saveptr);
1603 sidstr;
1604 sidstr = strtok_r(NULL, "\n", &saveptr)) {
1605 count += 1;
1606 ids = talloc_realloc(s3call, ids, struct id_map, count);
1607 NT_STATUS_HAVE_NO_MEMORY(ids);
1608 ids[count-1].sid = dom_sid_parse_talloc(ids, sidstr);
1609 NT_STATUS_HAVE_NO_MEMORY(ids->sid);
1612 ctx = wb_sids2xids_send(s3call, service, count, ids);
1613 NT_STATUS_HAVE_NO_MEMORY(ctx);
1615 ctx->async.fn = sids2xids_recv;
1616 ctx->async.private_data = s3call;
1617 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1618 return NT_STATUS_OK;