s4:librpc/rpc: use dcerpc_binding_get_string_option("target_principal")
[Samba.git] / source4 / winbind / wb_samba3_cmd.c
blob9ec3c4b0ccdd6c058a545316b1fd7431d2309458
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"));
644 chal.data = s3call->request->data.auth_crap.chal;
645 chal.length = sizeof(s3call->request->data.auth_crap.chal);
646 nt_resp.data = (uint8_t *)s3call->request->data.auth_crap.nt_resp;
647 nt_resp.length = s3call->request->data.auth_crap.nt_resp_len;
648 lm_resp.data = (uint8_t *)s3call->request->data.auth_crap.lm_resp;
649 lm_resp.length = s3call->request->data.auth_crap.lm_resp_len;
651 ctx = wb_cmd_pam_auth_crap_send(
652 s3call, service,
653 s3call->request->data.auth_crap.logon_parameters,
654 s3call->request->data.auth_crap.domain,
655 s3call->request->data.auth_crap.user,
656 s3call->request->data.auth_crap.workstation,
657 chal, nt_resp, lm_resp);
658 NT_STATUS_HAVE_NO_MEMORY(ctx);
660 ctx->async.fn = pam_auth_crap_recv;
661 ctx->async.private_data = s3call;
662 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
663 return NT_STATUS_OK;
666 static void pam_auth_crap_recv(struct composite_context *ctx)
668 struct wbsrv_samba3_call *s3call =
669 talloc_get_type(ctx->async.private_data,
670 struct wbsrv_samba3_call);
671 NTSTATUS status;
672 DATA_BLOB info3;
673 struct netr_UserSessionKey user_session_key;
674 struct netr_LMSessionKey lm_key;
675 char *unix_username;
677 status = wb_cmd_pam_auth_crap_recv(ctx, s3call, &info3,
678 &user_session_key, &lm_key, &unix_username);
679 if (!NT_STATUS_IS_OK(status)) goto done;
681 if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
682 memcpy(s3call->response->data.auth.user_session_key,
683 &user_session_key.key,
684 sizeof(s3call->response->data.auth.user_session_key));
687 if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
688 status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
689 if (!NT_STATUS_IS_OK(status)) {
690 DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
691 nt_errstr(status)));
692 goto done;
696 if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
697 s3call->response->extra_data.data = info3.data;
698 s3call->response->length += info3.length;
701 if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
702 memcpy(s3call->response->data.auth.first_8_lm_hash,
703 lm_key.key,
704 sizeof(s3call->response->data.auth.first_8_lm_hash));
707 if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
708 WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
711 done:
712 wbsrv_samba3_async_auth_epilogue(status, s3call);
715 /* Plaintext authentication
717 This interface is used by ntlm_auth in it's 'basic' authentication
718 mode, as well as by pam_winbind to authenticate users where we are
719 given a plaintext password.
722 static void pam_auth_recv(struct composite_context *ctx);
724 NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
726 struct composite_context *ctx;
727 struct wbsrv_service *service =
728 s3call->wbconn->listen_socket->service;
729 struct cli_credentials *credentials;
730 char *user, *domain;
732 if (!wb_samba3_split_username(s3call, s3call->wbconn->lp_ctx,
733 s3call->request->data.auth.user,
734 &domain, &user)) {
735 return NT_STATUS_NO_SUCH_USER;
738 credentials = cli_credentials_init(s3call);
739 if (!credentials) {
740 return NT_STATUS_NO_MEMORY;
742 cli_credentials_set_conf(credentials, service->task->lp_ctx);
743 cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
744 cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
746 cli_credentials_set_password(credentials, s3call->request->data.auth.pass, CRED_SPECIFIED);
748 ctx = wb_cmd_pam_auth_send(s3call, service, credentials);
749 NT_STATUS_HAVE_NO_MEMORY(ctx);
751 ctx->async.fn = pam_auth_recv;
752 ctx->async.private_data = s3call;
753 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
754 return NT_STATUS_OK;
757 static void pam_auth_recv(struct composite_context *ctx)
759 struct wbsrv_samba3_call *s3call =
760 talloc_get_type(ctx->async.private_data,
761 struct wbsrv_samba3_call);
762 NTSTATUS status;
763 DATA_BLOB info3;
764 struct netr_UserSessionKey user_session_key;
765 struct netr_LMSessionKey lm_key;
766 char *unix_username;
768 status = wb_cmd_pam_auth_recv(ctx, s3call, &info3,
769 &user_session_key, &lm_key, &unix_username);
771 if (!NT_STATUS_IS_OK(status)) goto done;
773 if (s3call->request->flags & WBFLAG_PAM_USER_SESSION_KEY) {
774 memcpy(s3call->response->data.auth.user_session_key,
775 &user_session_key.key,
776 sizeof(s3call->response->data.auth.user_session_key));
779 if (s3call->request->flags & WBFLAG_PAM_INFO3_TEXT) {
780 status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
781 if (!NT_STATUS_IS_OK(status)) {
782 DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
783 nt_errstr(status)));
784 goto done;
788 if (s3call->request->flags & WBFLAG_PAM_INFO3_NDR) {
789 s3call->response->extra_data.data = info3.data;
790 s3call->response->length += info3.length;
793 if (s3call->request->flags & WBFLAG_PAM_LMKEY) {
794 memcpy(s3call->response->data.auth.first_8_lm_hash,
795 lm_key.key,
796 sizeof(s3call->response->data.auth.first_8_lm_hash));
799 if (s3call->request->flags & WBFLAG_PAM_UNIX_NAME) {
800 WBSRV_SAMBA3_SET_STRING(s3call->response->data.auth.unix_username,unix_username);
804 done:
805 wbsrv_samba3_async_auth_epilogue(status, s3call);
809 List trusted domains
812 static void list_trustdom_recv_doms(struct composite_context *ctx);
814 NTSTATUS wbsrv_samba3_list_trustdom(struct wbsrv_samba3_call *s3call)
816 struct composite_context *ctx;
817 struct wbsrv_service *service =
818 s3call->wbconn->listen_socket->service;
820 DEBUG(5, ("wbsrv_samba3_list_trustdom called\n"));
822 ctx = wb_cmd_list_trustdoms_send(s3call, service);
823 NT_STATUS_HAVE_NO_MEMORY(ctx);
825 ctx->async.fn = list_trustdom_recv_doms;
826 ctx->async.private_data = s3call;
827 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
828 return NT_STATUS_OK;
831 static void list_trustdom_recv_doms(struct composite_context *ctx)
833 struct wbsrv_samba3_call *s3call =
834 talloc_get_type(ctx->async.private_data,
835 struct wbsrv_samba3_call);
836 uint32_t i, num_domains;
837 struct wb_dom_info **domains;
838 NTSTATUS status;
839 char *result;
841 status = wb_cmd_list_trustdoms_recv(ctx, s3call, &num_domains,
842 &domains);
843 if (!NT_STATUS_IS_OK(status)) goto done;
845 result = talloc_strdup(s3call, "");
846 if (result == NULL) {
847 status = NT_STATUS_NO_MEMORY;
848 goto done;
851 for (i=0; i<num_domains; i++) {
852 result = talloc_asprintf_append_buffer(
853 result, "%s\\%s\\%s",
854 domains[i]->name, domains[i]->name,
855 dom_sid_string(s3call, domains[i]->sid));
858 if (result == NULL) {
859 status = NT_STATUS_NO_MEMORY;
860 goto done;
863 s3call->response->result = WINBINDD_OK;
864 if (num_domains > 0) {
865 s3call->response->extra_data.data = result;
866 s3call->response->length += strlen(result)+1;
867 s3call->response->data.num_entries = num_domains;
870 done:
871 wbsrv_samba3_async_epilogue(status, s3call);
874 /* list groups */
875 static void list_groups_recv(struct composite_context *ctx);
877 NTSTATUS wbsrv_samba3_list_groups(struct wbsrv_samba3_call *s3call)
879 struct composite_context *ctx;
880 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
882 DEBUG(5, ("wbsrv_samba4_list_groups called\n"));
884 ctx = wb_cmd_list_groups_send(s3call, service,
885 s3call->request->domain_name);
886 NT_STATUS_HAVE_NO_MEMORY(ctx);
888 ctx->async.fn = list_groups_recv;
889 ctx->async.private_data = s3call;
890 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
891 return NT_STATUS_OK;
894 static void list_groups_recv(struct composite_context *ctx)
896 struct wbsrv_samba3_call *s3call = talloc_get_type_abort(
897 ctx->async.private_data,
898 struct wbsrv_samba3_call);
899 uint32_t extra_data_len;
900 char *extra_data;
901 uint32_t num_groups;
902 NTSTATUS status;
904 DEBUG(5, ("list_groups_recv called\n"));
906 status = wb_cmd_list_groups_recv(ctx, s3call, &extra_data_len,
907 &extra_data, &num_groups);
909 if (NT_STATUS_IS_OK(status)) {
910 s3call->response->extra_data.data = extra_data;
911 s3call->response->length += extra_data_len;
912 if (extra_data) {
913 s3call->response->length += 1;
914 s3call->response->data.num_entries = num_groups;
918 wbsrv_samba3_async_epilogue(status, s3call);
921 /* List users */
923 static void list_users_recv(struct composite_context *ctx);
925 NTSTATUS wbsrv_samba3_list_users(struct wbsrv_samba3_call *s3call)
927 struct composite_context *ctx;
928 struct wbsrv_service *service =
929 s3call->wbconn->listen_socket->service;
931 DEBUG(5, ("wbsrv_samba3_list_users called\n"));
933 ctx = wb_cmd_list_users_send(s3call, service,
934 s3call->request->domain_name);
935 NT_STATUS_HAVE_NO_MEMORY(ctx);
937 ctx->async.fn = list_users_recv;
938 ctx->async.private_data = s3call;
939 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
940 return NT_STATUS_OK;
943 static void list_users_recv(struct composite_context *ctx)
945 struct wbsrv_samba3_call *s3call =
946 talloc_get_type(ctx->async.private_data,
947 struct wbsrv_samba3_call);
948 uint32_t extra_data_len;
949 char *extra_data;
950 uint32_t num_users;
951 NTSTATUS status;
953 DEBUG(5, ("list_users_recv called\n"));
955 status = wb_cmd_list_users_recv(ctx, s3call, &extra_data_len,
956 &extra_data, &num_users);
958 if (NT_STATUS_IS_OK(status)) {
959 s3call->response->extra_data.data = extra_data;
960 s3call->response->length += extra_data_len;
961 if (extra_data) {
962 s3call->response->length += 1;
963 s3call->response->data.num_entries = num_users;
967 wbsrv_samba3_async_epilogue(status, s3call);
970 /* NSS calls */
972 static void getpwnam_recv(struct composite_context *ctx);
974 NTSTATUS wbsrv_samba3_getpwnam(struct wbsrv_samba3_call *s3call)
976 struct composite_context *ctx;
977 struct wbsrv_service *service =
978 s3call->wbconn->listen_socket->service;
980 DEBUG(5, ("wbsrv_samba3_getpwnam called\n"));
982 ctx = wb_cmd_getpwnam_send(s3call, service,
983 s3call->request->data.username);
984 NT_STATUS_HAVE_NO_MEMORY(ctx);
986 ctx->async.fn = getpwnam_recv;
987 ctx->async.private_data = s3call;
988 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
989 return NT_STATUS_OK;
992 static void getpwnam_recv(struct composite_context *ctx)
994 struct wbsrv_samba3_call *s3call =
995 talloc_get_type(ctx->async.private_data,
996 struct wbsrv_samba3_call);
997 NTSTATUS status;
998 struct winbindd_pw *pw;
1000 DEBUG(5, ("getpwnam_recv called\n"));
1002 status = wb_cmd_getpwnam_recv(ctx, s3call, &pw);
1003 if(NT_STATUS_IS_OK(status))
1004 s3call->response->data.pw = *pw;
1006 wbsrv_samba3_async_epilogue(status, s3call);
1009 static void getpwuid_recv(struct composite_context *ctx);
1011 NTSTATUS wbsrv_samba3_getpwuid(struct wbsrv_samba3_call *s3call)
1013 struct composite_context *ctx;
1014 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1016 DEBUG(5, ("wbsrv_samba3_getpwuid called\n"));
1018 ctx = wb_cmd_getpwuid_send(s3call, service,
1019 s3call->request->data.uid);
1020 NT_STATUS_HAVE_NO_MEMORY(ctx);
1022 ctx->async.fn = getpwuid_recv;
1023 ctx->async.private_data = s3call;
1024 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1025 return NT_STATUS_OK;
1028 static void getpwuid_recv(struct composite_context *ctx)
1030 struct wbsrv_samba3_call *s3call =
1031 talloc_get_type(ctx->async.private_data,
1032 struct wbsrv_samba3_call);
1033 NTSTATUS status;
1034 struct winbindd_pw *pw;
1036 DEBUG(5, ("getpwuid_recv called\n"));
1038 status = wb_cmd_getpwuid_recv(ctx, s3call, &pw);
1039 if (NT_STATUS_IS_OK(status))
1040 s3call->response->data.pw = *pw;
1042 wbsrv_samba3_async_epilogue(status, s3call);
1045 static void setpwent_recv(struct composite_context *ctx);
1047 NTSTATUS wbsrv_samba3_setpwent(struct wbsrv_samba3_call *s3call)
1049 struct composite_context *ctx;
1050 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1052 DEBUG(5, ("wbsrv_samba3_setpwent called\n"));
1054 ctx = wb_cmd_setpwent_send(s3call, service);
1055 NT_STATUS_HAVE_NO_MEMORY(ctx);
1057 ctx->async.fn = setpwent_recv;
1058 ctx->async.private_data = s3call;
1059 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1060 return NT_STATUS_OK;
1063 static void setpwent_recv(struct composite_context *ctx)
1065 struct wbsrv_samba3_call *s3call =
1066 talloc_get_type(ctx->async.private_data,
1067 struct wbsrv_samba3_call);
1068 NTSTATUS status;
1069 struct wbsrv_pwent *pwent;
1071 DEBUG(5, ("setpwent_recv called\n"));
1073 status = wb_cmd_setpwent_recv(ctx, s3call->wbconn, &pwent);
1074 if (NT_STATUS_IS_OK(status)) {
1075 s3call->wbconn->protocol_private_data = pwent;
1078 wbsrv_samba3_async_epilogue(status, s3call);
1081 static void getpwent_recv(struct composite_context *ctx);
1083 NTSTATUS wbsrv_samba3_getpwent(struct wbsrv_samba3_call *s3call)
1085 struct composite_context *ctx;
1086 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1087 struct wbsrv_pwent *pwent;
1089 DEBUG(5, ("wbsrv_samba3_getpwent called\n"));
1091 NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
1093 pwent = talloc_get_type(s3call->wbconn->protocol_private_data,
1094 struct wbsrv_pwent);
1095 NT_STATUS_HAVE_NO_MEMORY(pwent);
1097 ctx = wb_cmd_getpwent_send(s3call, service, pwent,
1098 s3call->request->data.num_entries);
1099 NT_STATUS_HAVE_NO_MEMORY(ctx);
1101 ctx->async.fn = getpwent_recv;
1102 ctx->async.private_data = s3call;
1103 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1104 return NT_STATUS_OK;
1107 static void getpwent_recv(struct composite_context *ctx)
1109 struct wbsrv_samba3_call *s3call =
1110 talloc_get_type(ctx->async.private_data,
1111 struct wbsrv_samba3_call);
1112 NTSTATUS status;
1113 struct winbindd_pw *pw;
1114 uint32_t num_users;
1116 DEBUG(5, ("getpwent_recv called\n"));
1118 status = wb_cmd_getpwent_recv(ctx, s3call, &pw, &num_users);
1119 if (NT_STATUS_IS_OK(status)) {
1120 uint32_t extra_len = sizeof(struct winbindd_pw) * num_users;
1122 s3call->response->data.num_entries = num_users;
1123 s3call->response->extra_data.data = pw;
1124 s3call->response->length += extra_len;
1127 wbsrv_samba3_async_epilogue(status, s3call);
1130 NTSTATUS wbsrv_samba3_endpwent(struct wbsrv_samba3_call *s3call)
1132 struct wbsrv_pwent *pwent =
1133 talloc_get_type(s3call->wbconn->protocol_private_data,
1134 struct wbsrv_pwent);
1135 DEBUG(5, ("wbsrv_samba3_endpwent called\n"));
1137 talloc_free(pwent);
1139 s3call->wbconn->protocol_private_data = NULL;
1140 s3call->response->result = WINBINDD_OK;
1141 return NT_STATUS_OK;
1145 static void getgrnam_recv(struct composite_context *ctx);
1147 NTSTATUS wbsrv_samba3_getgrnam(struct wbsrv_samba3_call *s3call)
1149 struct composite_context *ctx;
1150 struct wbsrv_service *service =
1151 s3call->wbconn->listen_socket->service;
1153 DEBUG(5, ("wbsrv_samba3_getgrnam called\n"));
1155 ctx = wb_cmd_getgrnam_send(s3call, service,
1156 s3call->request->data.groupname);
1157 NT_STATUS_HAVE_NO_MEMORY(ctx);
1159 ctx->async.fn = getgrnam_recv;
1160 ctx->async.private_data = s3call;
1161 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1162 return NT_STATUS_OK;
1165 static void getgrnam_recv(struct composite_context *ctx)
1167 struct wbsrv_samba3_call *s3call =
1168 talloc_get_type(ctx->async.private_data,
1169 struct wbsrv_samba3_call);
1170 NTSTATUS status;
1171 struct winbindd_gr *gr;
1173 DEBUG(5, ("getgrnam_recv called\n"));
1175 status = wb_cmd_getgrnam_recv(ctx, s3call, &gr);
1176 if(NT_STATUS_IS_OK(status))
1177 s3call->response->data.gr = *gr;
1179 wbsrv_samba3_async_epilogue(status, s3call);
1182 static void getgrgid_recv(struct composite_context *ctx);
1184 NTSTATUS wbsrv_samba3_getgrgid(struct wbsrv_samba3_call *s3call)
1186 struct composite_context *ctx;
1187 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1189 DEBUG(5, ("wbsrv_samba3_getgrgid called\n"));
1191 ctx = wb_cmd_getgrgid_send(s3call, service,
1192 s3call->request->data.gid);
1193 NT_STATUS_HAVE_NO_MEMORY(ctx);
1195 ctx->async.fn = getgrgid_recv;
1196 ctx->async.private_data = s3call;
1197 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1198 return NT_STATUS_OK;
1201 static void getgrgid_recv(struct composite_context *ctx)
1203 struct wbsrv_samba3_call *s3call =
1204 talloc_get_type(ctx->async.private_data,
1205 struct wbsrv_samba3_call);
1206 NTSTATUS status;
1207 struct winbindd_gr *gr;
1209 DEBUG(5, ("getgrgid_recv called\n"));
1211 status = wb_cmd_getgrgid_recv(ctx, s3call, &gr);
1212 if (NT_STATUS_IS_OK(status))
1213 s3call->response->data.gr = *gr;
1215 wbsrv_samba3_async_epilogue(status, s3call);
1218 static void getgroups_recv(struct composite_context *ctx);
1220 NTSTATUS wbsrv_samba3_getgroups(struct wbsrv_samba3_call *s3call)
1222 struct composite_context *ctx;
1223 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1225 DEBUG(5, ("wbsrv_samba3_getgroups called\n"));
1226 /* S3 code do the same so why not ... */
1227 s3call->request->data.username[sizeof(s3call->request->data.username)-1]='\0';
1228 ctx = wb_cmd_getgroups_send(s3call, service, s3call->request->data.username);
1229 NT_STATUS_HAVE_NO_MEMORY(ctx);
1231 ctx->async.fn = getgroups_recv;
1232 ctx->async.private_data = s3call;
1233 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1234 return NT_STATUS_OK;
1237 static void getgroups_recv(struct composite_context *ctx)
1239 struct wbsrv_samba3_call *s3call =
1240 talloc_get_type(ctx->async.private_data,
1241 struct wbsrv_samba3_call);
1242 gid_t *gids;
1243 uint32_t num_groups;
1244 NTSTATUS status;
1245 DEBUG(5, ("getgroups_recv called\n"));
1247 status = wb_cmd_getgroups_recv(ctx, s3call, &gids, &num_groups);
1248 if (NT_STATUS_IS_OK(status)) {
1249 uint32_t extra_len = sizeof(gid_t) * num_groups;
1251 s3call->response->data.num_entries = num_groups;
1252 s3call->response->extra_data.data = gids;
1253 s3call->response->length += extra_len;
1254 } else {
1255 s3call->response->result = WINBINDD_ERROR;
1258 wbsrv_samba3_async_epilogue(status, s3call);
1261 static void setgrent_recv(struct composite_context *ctx);
1263 NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
1265 struct composite_context *ctx;
1266 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1268 DEBUG(5, ("wbsrv_samba3_setgrent called\n"));
1270 ctx = wb_cmd_setgrent_send(s3call, service);
1271 NT_STATUS_HAVE_NO_MEMORY(ctx);
1273 ctx->async.fn = setgrent_recv;
1274 ctx->async.private_data = s3call;
1275 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1276 return NT_STATUS_OK;
1279 static void setgrent_recv(struct composite_context *ctx)
1281 struct wbsrv_samba3_call *s3call =
1282 talloc_get_type(ctx->async.private_data,
1283 struct wbsrv_samba3_call);
1284 NTSTATUS status;
1285 struct wbsrv_grent *grent;
1287 DEBUG(5, ("setpwent_recv called\n"));
1289 status = wb_cmd_setgrent_recv(ctx, s3call->wbconn, &grent);
1290 if (NT_STATUS_IS_OK(status)) {
1291 s3call->wbconn->protocol_private_data = grent;
1294 wbsrv_samba3_async_epilogue(status, s3call);
1297 static void getgrent_recv(struct composite_context *ctx);
1299 NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
1301 struct composite_context *ctx;
1302 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1303 struct wbsrv_grent *grent;
1305 DEBUG(5, ("wbsrv_samba3_getgrent called\n"));
1307 NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
1309 grent = talloc_get_type(s3call->wbconn->protocol_private_data,
1310 struct wbsrv_grent);
1311 NT_STATUS_HAVE_NO_MEMORY(grent);
1313 ctx = wb_cmd_getgrent_send(s3call, service, grent,
1314 s3call->request->data.num_entries);
1315 NT_STATUS_HAVE_NO_MEMORY(ctx);
1317 ctx->async.fn = getgrent_recv;
1318 ctx->async.private_data = s3call;
1319 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1320 return NT_STATUS_OK;
1323 static void getgrent_recv(struct composite_context *ctx)
1325 struct wbsrv_samba3_call *s3call =
1326 talloc_get_type(ctx->async.private_data,
1327 struct wbsrv_samba3_call);
1328 NTSTATUS status;
1329 struct winbindd_gr *gr;
1330 uint32_t num_groups;
1332 DEBUG(5, ("getgrent_recv called\n"));
1334 status = wb_cmd_getgrent_recv(ctx, s3call, &gr, &num_groups);
1335 if (NT_STATUS_IS_OK(status)) {
1336 uint32_t extra_len = sizeof(struct winbindd_gr) * num_groups;
1338 s3call->response->data.num_entries = num_groups;
1339 s3call->response->extra_data.data = gr;
1340 s3call->response->length += extra_len;
1343 wbsrv_samba3_async_epilogue(status, s3call);
1346 NTSTATUS wbsrv_samba3_endgrent(struct wbsrv_samba3_call *s3call)
1348 DEBUG(5, ("wbsrv_samba3_endgrent called\n"));
1349 s3call->response->result = WINBINDD_OK;
1350 return NT_STATUS_OK;
1353 static void sid2uid_recv(struct composite_context *ctx);
1355 NTSTATUS wbsrv_samba3_sid2uid(struct wbsrv_samba3_call *s3call)
1357 struct composite_context *ctx;
1358 struct wbsrv_service *service =
1359 s3call->wbconn->listen_socket->service;
1360 struct dom_sid *sid;
1362 DEBUG(5, ("wbsrv_samba3_sid2uid called\n"));
1364 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
1365 NT_STATUS_HAVE_NO_MEMORY(sid);
1367 ctx = wb_sid2uid_send(s3call, service, sid);
1368 NT_STATUS_HAVE_NO_MEMORY(ctx);
1370 ctx->async.fn = sid2uid_recv;
1371 ctx->async.private_data = s3call;
1372 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1373 return NT_STATUS_OK;
1377 static void sid2uid_recv(struct composite_context *ctx)
1379 struct wbsrv_samba3_call *s3call =
1380 talloc_get_type(ctx->async.private_data,
1381 struct wbsrv_samba3_call);
1382 NTSTATUS status;
1384 DEBUG(5, ("sid2uid_recv called\n"));
1386 status = wb_sid2uid_recv(ctx, &s3call->response->data.uid);
1388 wbsrv_samba3_async_epilogue(status, s3call);
1391 static void sid2gid_recv(struct composite_context *ctx);
1393 NTSTATUS wbsrv_samba3_sid2gid(struct wbsrv_samba3_call *s3call)
1395 struct composite_context *ctx;
1396 struct wbsrv_service *service =
1397 s3call->wbconn->listen_socket->service;
1398 struct dom_sid *sid;
1400 DEBUG(5, ("wbsrv_samba3_sid2gid called\n"));
1402 sid = dom_sid_parse_talloc(s3call, s3call->request->data.sid);
1403 NT_STATUS_HAVE_NO_MEMORY(sid);
1405 ctx = wb_sid2gid_send(s3call, service, sid);
1406 NT_STATUS_HAVE_NO_MEMORY(ctx);
1408 ctx->async.fn = sid2gid_recv;
1409 ctx->async.private_data = s3call;
1410 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1411 return NT_STATUS_OK;
1415 static void sid2gid_recv(struct composite_context *ctx)
1417 struct wbsrv_samba3_call *s3call =
1418 talloc_get_type(ctx->async.private_data,
1419 struct wbsrv_samba3_call);
1420 NTSTATUS status;
1422 DEBUG(5, ("sid2gid_recv called\n"));
1424 status = wb_sid2gid_recv(ctx, &s3call->response->data.gid);
1426 wbsrv_samba3_async_epilogue(status, s3call);
1429 static void uid2sid_recv(struct composite_context *ctx);
1431 NTSTATUS wbsrv_samba3_uid2sid(struct wbsrv_samba3_call *s3call)
1433 struct composite_context *ctx;
1434 struct wbsrv_service *service =
1435 s3call->wbconn->listen_socket->service;
1437 DEBUG(5, ("wbsrv_samba3_uid2sid called\n"));
1439 ctx = wb_uid2sid_send(s3call, service, s3call->request->data.uid);
1440 NT_STATUS_HAVE_NO_MEMORY(ctx);
1442 ctx->async.fn = uid2sid_recv;
1443 ctx->async.private_data = s3call;
1444 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1445 return NT_STATUS_OK;
1449 static void uid2sid_recv(struct composite_context *ctx)
1451 struct wbsrv_samba3_call *s3call =
1452 talloc_get_type(ctx->async.private_data,
1453 struct wbsrv_samba3_call);
1454 NTSTATUS status;
1455 struct dom_sid *sid;
1456 char *sid_str;
1458 DEBUG(5, ("uid2sid_recv called\n"));
1460 status = wb_uid2sid_recv(ctx, s3call, &sid);
1461 if(NT_STATUS_IS_OK(status)) {
1462 sid_str = dom_sid_string(s3call, sid);
1464 /* If the conversion failed, bail out with a failure. */
1465 if (sid_str == NULL)
1466 wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1468 /* But we assume this worked, so we'll set the string. Work
1469 * done. */
1470 WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
1471 s3call->response->data.sid.type = SID_NAME_USER;
1474 wbsrv_samba3_async_epilogue(status, s3call);
1477 static void gid2sid_recv(struct composite_context *ctx);
1479 NTSTATUS wbsrv_samba3_gid2sid(struct wbsrv_samba3_call *s3call)
1481 struct composite_context *ctx;
1482 struct wbsrv_service *service =
1483 s3call->wbconn->listen_socket->service;
1485 DEBUG(5, ("wbsrv_samba3_gid2sid called\n"));
1487 ctx = wb_gid2sid_send(s3call, service, s3call->request->data.gid);
1488 NT_STATUS_HAVE_NO_MEMORY(ctx);
1490 ctx->async.fn = gid2sid_recv;
1491 ctx->async.private_data = s3call;
1492 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1493 return NT_STATUS_OK;
1497 static void gid2sid_recv(struct composite_context *ctx)
1499 struct wbsrv_samba3_call *s3call =
1500 talloc_get_type(ctx->async.private_data,
1501 struct wbsrv_samba3_call);
1502 NTSTATUS status;
1503 struct dom_sid *sid;
1504 char *sid_str;
1506 DEBUG(5, ("gid2sid_recv called\n"));
1508 status = wb_gid2sid_recv(ctx, s3call, &sid);
1509 if(NT_STATUS_IS_OK(status)) {
1510 sid_str = dom_sid_string(s3call, sid);
1512 if (sid_str == NULL)
1513 wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1515 WBSRV_SAMBA3_SET_STRING(s3call->response->data.sid.sid, sid_str);
1516 s3call->response->data.sid.type = SID_NAME_DOMAIN;
1519 wbsrv_samba3_async_epilogue(status, s3call);
1522 static void sids2xids_recv(struct composite_context *ctx)
1524 struct wbsrv_samba3_call *s3call =
1525 talloc_get_type(ctx->async.private_data,
1526 struct wbsrv_samba3_call);
1527 NTSTATUS status;
1528 struct id_map *ids;
1529 unsigned i, count;
1530 struct winbindd_response *resp = s3call->response;
1532 DEBUG(5, ("sids2xids_recv called\n"));
1534 status = wb_sids2xids_recv(ctx, &ids, &count);
1535 if (!NT_STATUS_IS_OK(status)) {
1536 goto done;
1539 /* fill in extra_data with the list of IDs. Each is prefixed
1540 * by 'U' or 'G' for user and group, and followed by a
1541 * newline */
1542 resp->extra_data.data = talloc_strdup(resp, "");
1543 if (resp->extra_data.data == NULL) {
1544 status = NT_STATUS_NO_MEMORY;
1545 goto done;
1548 for (i=0; i<count; i++) {
1549 char type_char = '*';
1550 if (ids[i].status != ID_MAPPED) {
1551 resp->extra_data.data = talloc_asprintf_append_buffer(resp->extra_data.data, "\n");
1552 if (resp->extra_data.data == NULL) {
1553 status = NT_STATUS_NO_MEMORY;
1554 goto done;
1556 continue;
1558 switch (ids[i].xid.type) {
1559 case ID_TYPE_UID:
1560 type_char = 'U';
1561 break;
1562 case ID_TYPE_GID:
1563 type_char = 'G';
1564 break;
1565 case ID_TYPE_BOTH:
1566 type_char = 'B';
1567 break;
1568 case ID_TYPE_NOT_SPECIFIED:
1569 type_char = 'N';
1570 break;
1572 resp->extra_data.data = talloc_asprintf_append_buffer(resp->extra_data.data, "%c%u\n",
1573 type_char, (unsigned)ids[i].xid.id);
1574 if (resp->extra_data.data == NULL) {
1575 status = NT_STATUS_NO_MEMORY;
1576 goto done;
1579 resp->length += strlen(resp->extra_data.data) + 1;
1581 done:
1582 wbsrv_samba3_async_epilogue(status, s3call);
1586 NTSTATUS wbsrv_samba3_sids2xids(struct wbsrv_samba3_call *s3call)
1588 struct composite_context *ctx;
1589 struct wbsrv_service *service =
1590 s3call->wbconn->listen_socket->service;
1591 struct id_map *ids = NULL;
1592 unsigned count = 0;
1593 char *saveptr = NULL;
1594 char *sidstr;
1596 DEBUG(5, ("wbsrv_samba3_sids2xids called\n"));
1598 for (sidstr = strtok_r(s3call->request->extra_data.data, "\n", &saveptr);
1599 sidstr;
1600 sidstr = strtok_r(NULL, "\n", &saveptr)) {
1601 count += 1;
1602 ids = talloc_realloc(s3call, ids, struct id_map, count);
1603 NT_STATUS_HAVE_NO_MEMORY(ids);
1604 ids[count-1].sid = dom_sid_parse_talloc(ids, sidstr);
1605 NT_STATUS_HAVE_NO_MEMORY(ids->sid);
1608 ctx = wb_sids2xids_send(s3call, service, count, ids);
1609 NT_STATUS_HAVE_NO_MEMORY(ctx);
1611 ctx->async.fn = sids2xids_recv;
1612 ctx->async.private_data = s3call;
1613 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1614 return NT_STATUS_OK;