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/>.
25 #include "winbind/wb_server.h"
26 #include "winbind/wb_async_helpers.h"
27 #include "param/param.h"
28 #include "winbind/wb_helper.h"
29 #include "libcli/composite/composite.h"
31 #include "librpc/gen_ndr/netlogon.h"
32 #include "librpc/gen_ndr/ndr_netlogon.h"
33 #include "libcli/security/security.h"
34 #include "auth/ntlm/pam_errors.h"
35 #include "auth/credentials/credentials.h"
36 #include "smbd/service_task.h"
39 support the old Samba3 TXT form of the info3
41 static NTSTATUS wb_samba3_append_info3_as_txt(TALLOC_CTX *mem_ctx,
42 struct wbsrv_samba3_call *s3call,
45 struct netr_SamInfo3 *info3;
48 enum ndr_err_code ndr_err;
50 info3 = talloc(mem_ctx, struct netr_SamInfo3);
51 NT_STATUS_HAVE_NO_MEMORY(info3);
53 /* The Samba3 protocol has a redundent 4 bytes at the start */
57 ndr_err = ndr_pull_struct_blob(&info3b,
59 lp_iconv_convenience(s3call->wbconn->lp_ctx),
61 (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3);
62 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
63 return ndr_map_error2ntstatus(ndr_err);
66 s3call->response.data.auth.info3.logon_time =
67 nt_time_to_unix(info3->base.last_logon);
68 s3call->response.data.auth.info3.logoff_time =
69 nt_time_to_unix(info3->base.last_logoff);
70 s3call->response.data.auth.info3.kickoff_time =
71 nt_time_to_unix(info3->base.acct_expiry);
72 s3call->response.data.auth.info3.pass_last_set_time =
73 nt_time_to_unix(info3->base.last_password_change);
74 s3call->response.data.auth.info3.pass_can_change_time =
75 nt_time_to_unix(info3->base.allow_password_change);
76 s3call->response.data.auth.info3.pass_must_change_time =
77 nt_time_to_unix(info3->base.force_password_change);
79 s3call->response.data.auth.info3.logon_count = info3->base.logon_count;
80 s3call->response.data.auth.info3.bad_pw_count = info3->base.bad_password_count;
82 s3call->response.data.auth.info3.user_rid = info3->base.rid;
83 s3call->response.data.auth.info3.group_rid = info3->base.primary_gid;
84 fstrcpy(s3call->response.data.auth.info3.dom_sid, dom_sid_string(mem_ctx, info3->base.domain_sid));
86 s3call->response.data.auth.info3.num_groups = info3->base.groups.count;
87 s3call->response.data.auth.info3.user_flgs = info3->base.user_flags;
89 s3call->response.data.auth.info3.acct_flags = info3->base.acct_flags;
90 s3call->response.data.auth.info3.num_other_sids = info3->sidcount;
92 fstrcpy(s3call->response.data.auth.info3.user_name,
93 info3->base.account_name.string);
94 fstrcpy(s3call->response.data.auth.info3.full_name,
95 info3->base.full_name.string);
96 fstrcpy(s3call->response.data.auth.info3.logon_script,
97 info3->base.logon_script.string);
98 fstrcpy(s3call->response.data.auth.info3.profile_path,
99 info3->base.profile_path.string);
100 fstrcpy(s3call->response.data.auth.info3.home_dir,
101 info3->base.home_directory.string);
102 fstrcpy(s3call->response.data.auth.info3.dir_drive,
103 info3->base.home_drive.string);
105 fstrcpy(s3call->response.data.auth.info3.logon_srv,
106 info3->base.logon_server.string);
107 fstrcpy(s3call->response.data.auth.info3.logon_dom,
108 info3->base.domain.string);
110 ex = talloc_strdup(mem_ctx, "");
111 NT_STATUS_HAVE_NO_MEMORY(ex);
113 for (i=0; i < info3->base.groups.count; i++) {
114 ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
115 info3->base.groups.rids[i].rid,
116 info3->base.groups.rids[i].attributes);
117 NT_STATUS_HAVE_NO_MEMORY(ex);
120 for (i=0; i < info3->sidcount; i++) {
123 sid = dom_sid_string(mem_ctx, info3->sids[i].sid);
124 NT_STATUS_HAVE_NO_MEMORY(sid);
126 ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n",
128 info3->sids[i].attributes);
129 NT_STATUS_HAVE_NO_MEMORY(ex);
134 s3call->response.extra_data.data = ex;
135 s3call->response.length += talloc_get_size(ex);
141 Send off the reply to an async Samba3 query, handling filling in the PAM, NTSTATUS and string errors.
144 static void wbsrv_samba3_async_auth_epilogue(NTSTATUS status,
145 struct wbsrv_samba3_call *s3call)
147 struct winbindd_response *resp = &s3call->response;
148 if (!NT_STATUS_IS_OK(status)) {
149 resp->result = WINBINDD_ERROR;
151 resp->result = WINBINDD_OK;
154 WBSRV_SAMBA3_SET_STRING(resp->data.auth.nt_status_string,
156 WBSRV_SAMBA3_SET_STRING(resp->data.auth.error_string,
157 get_friendly_nt_error_msg(status));
159 resp->data.auth.pam_error = nt_status_to_pam(status);
160 resp->data.auth.nt_status = NT_STATUS_V(status);
162 wbsrv_samba3_send_reply(s3call);
166 Send of a generic reply to a Samba3 query
169 static void wbsrv_samba3_async_epilogue(NTSTATUS status,
170 struct wbsrv_samba3_call *s3call)
172 struct winbindd_response *resp = &s3call->response;
173 if (NT_STATUS_IS_OK(status)) {
174 resp->result = WINBINDD_OK;
176 resp->result = WINBINDD_ERROR;
179 wbsrv_samba3_send_reply(s3call);
183 Boilerplate commands, simple queries without network traffic
186 NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call)
188 s3call->response.result = WINBINDD_OK;
189 s3call->response.data.interface_version = WINBIND_INTERFACE_VERSION;
193 NTSTATUS wbsrv_samba3_info(struct wbsrv_samba3_call *s3call)
195 s3call->response.result = WINBINDD_OK;
196 s3call->response.data.info.winbind_separator = *lp_winbind_separator(s3call->wbconn->lp_ctx);
197 WBSRV_SAMBA3_SET_STRING(s3call->response.data.info.samba_version,
198 SAMBA_VERSION_STRING);
202 NTSTATUS wbsrv_samba3_domain_name(struct wbsrv_samba3_call *s3call)
204 s3call->response.result = WINBINDD_OK;
205 WBSRV_SAMBA3_SET_STRING(s3call->response.data.domain_name,
206 lp_workgroup(s3call->wbconn->lp_ctx));
210 NTSTATUS wbsrv_samba3_netbios_name(struct wbsrv_samba3_call *s3call)
212 s3call->response.result = WINBINDD_OK;
213 WBSRV_SAMBA3_SET_STRING(s3call->response.data.netbios_name,
214 lp_netbios_name(s3call->wbconn->lp_ctx));
218 NTSTATUS wbsrv_samba3_priv_pipe_dir(struct wbsrv_samba3_call *s3call)
220 const char *path = s3call->wbconn->listen_socket->service->priv_socket_path;
221 s3call->response.result = WINBINDD_OK;
222 s3call->response.extra_data.data = discard_const(path);
224 s3call->response.length += strlen(path) + 1;
228 NTSTATUS wbsrv_samba3_ping(struct wbsrv_samba3_call *s3call)
230 s3call->response.result = WINBINDD_OK;
234 NTSTATUS wbsrv_samba3_domain_info(struct wbsrv_samba3_call *s3call)
236 DEBUG(5, ("wbsrv_samba3_domain_info called, stub\n"));
237 s3call->response.result = WINBINDD_OK;
238 fstrcpy(s3call->response.data.domain_info.name,
239 s3call->request.domain_name);
240 fstrcpy(s3call->response.data.domain_info.alt_name,
241 s3call->request.domain_name);
242 fstrcpy(s3call->response.data.domain_info.sid, "S-1-2-3-4");
243 s3call->response.data.domain_info.native_mode = false;
244 s3call->response.data.domain_info.active_directory = false;
245 s3call->response.data.domain_info.primary = false;
250 /* Plaintext authentication
252 This interface is used by ntlm_auth in it's 'basic' authentication
253 mode, as well as by pam_winbind to authenticate users where we are
254 given a plaintext password.
257 static void check_machacc_recv(struct composite_context *ctx);
259 NTSTATUS wbsrv_samba3_check_machacc(struct wbsrv_samba3_call *s3call)
262 struct cli_credentials *creds;
263 struct composite_context *ctx;
264 struct wbsrv_service *service =
265 s3call->wbconn->listen_socket->service;
267 /* Create a credentials structure */
268 creds = cli_credentials_init(s3call);
270 return NT_STATUS_NO_MEMORY;
273 cli_credentials_set_conf(creds, service->task->lp_ctx);
275 /* Connect the machine account to the credentials */
276 status = cli_credentials_set_machine_account(creds, service->task->lp_ctx);
277 if (!NT_STATUS_IS_OK(status)) {
282 ctx = wb_cmd_pam_auth_send(s3call, service, creds);
286 return NT_STATUS_NO_MEMORY;
289 ctx->async.fn = check_machacc_recv;
290 ctx->async.private_data = s3call;
291 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
295 static void check_machacc_recv(struct composite_context *ctx)
297 struct wbsrv_samba3_call *s3call =
298 talloc_get_type(ctx->async.private_data,
299 struct wbsrv_samba3_call);
302 status = wb_cmd_pam_auth_recv(ctx, s3call, NULL, NULL, NULL, NULL);
304 if (!NT_STATUS_IS_OK(status)) goto done;
307 wbsrv_samba3_async_auth_epilogue(status, s3call);
311 Find the name of a suitable domain controller, by query on the
312 netlogon pipe to the DC.
315 static void getdcname_recv_dc(struct composite_context *ctx);
317 NTSTATUS wbsrv_samba3_getdcname(struct wbsrv_samba3_call *s3call)
319 struct composite_context *ctx;
320 struct wbsrv_service *service =
321 s3call->wbconn->listen_socket->service;
323 DEBUG(5, ("wbsrv_samba3_getdcname called\n"));
325 ctx = wb_cmd_getdcname_send(s3call, service,
326 s3call->request.domain_name);
327 NT_STATUS_HAVE_NO_MEMORY(ctx);
329 ctx->async.fn = getdcname_recv_dc;
330 ctx->async.private_data = s3call;
331 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
335 static void getdcname_recv_dc(struct composite_context *ctx)
337 struct wbsrv_samba3_call *s3call =
338 talloc_get_type(ctx->async.private_data,
339 struct wbsrv_samba3_call);
343 status = wb_cmd_getdcname_recv(ctx, s3call, &dcname);
344 if (!NT_STATUS_IS_OK(status)) goto done;
346 s3call->response.result = WINBINDD_OK;
347 WBSRV_SAMBA3_SET_STRING(s3call->response.data.dc_name, dcname);
350 wbsrv_samba3_async_epilogue(status, s3call);
354 Lookup a user's domain groups
357 static void userdomgroups_recv_groups(struct composite_context *ctx);
359 NTSTATUS wbsrv_samba3_userdomgroups(struct wbsrv_samba3_call *s3call)
361 struct composite_context *ctx;
364 DEBUG(5, ("wbsrv_samba3_userdomgroups called\n"));
366 sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
368 DEBUG(5, ("Could not parse sid %s\n",
369 s3call->request.data.sid));
370 return NT_STATUS_NO_MEMORY;
373 ctx = wb_cmd_userdomgroups_send(
374 s3call, s3call->wbconn->listen_socket->service, sid);
375 NT_STATUS_HAVE_NO_MEMORY(ctx);
377 ctx->async.fn = userdomgroups_recv_groups;
378 ctx->async.private_data = s3call;
379 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
383 static void userdomgroups_recv_groups(struct composite_context *ctx)
385 struct wbsrv_samba3_call *s3call =
386 talloc_get_type(ctx->async.private_data,
387 struct wbsrv_samba3_call);
389 struct dom_sid **sids;
393 status = wb_cmd_userdomgroups_recv(ctx, s3call, &num_sids, &sids);
394 if (!NT_STATUS_IS_OK(status)) goto done;
396 sids_string = talloc_strdup(s3call, "");
397 if (sids_string == NULL) {
398 status = NT_STATUS_NO_MEMORY;
402 for (i=0; i<num_sids; i++) {
403 sids_string = talloc_asprintf_append_buffer(
404 sids_string, "%s\n", dom_sid_string(s3call, sids[i]));
407 if (sids_string == NULL) {
408 status = NT_STATUS_NO_MEMORY;
412 s3call->response.result = WINBINDD_OK;
413 s3call->response.extra_data.data = sids_string;
414 s3call->response.length += strlen(sids_string)+1;
415 s3call->response.data.num_entries = num_sids;
418 wbsrv_samba3_async_epilogue(status, s3call);
422 Lookup the list of SIDs for a user
424 static void usersids_recv_sids(struct composite_context *ctx);
426 NTSTATUS wbsrv_samba3_usersids(struct wbsrv_samba3_call *s3call)
428 struct composite_context *ctx;
431 DEBUG(5, ("wbsrv_samba3_usersids called\n"));
433 sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
435 DEBUG(5, ("Could not parse sid %s\n",
436 s3call->request.data.sid));
437 return NT_STATUS_NO_MEMORY;
440 ctx = wb_cmd_usersids_send(
441 s3call, s3call->wbconn->listen_socket->service, sid);
442 NT_STATUS_HAVE_NO_MEMORY(ctx);
444 ctx->async.fn = usersids_recv_sids;
445 ctx->async.private_data = s3call;
446 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
450 static void usersids_recv_sids(struct composite_context *ctx)
452 struct wbsrv_samba3_call *s3call =
453 talloc_get_type(ctx->async.private_data,
454 struct wbsrv_samba3_call);
456 struct dom_sid **sids;
460 status = wb_cmd_usersids_recv(ctx, s3call, &num_sids, &sids);
461 if (!NT_STATUS_IS_OK(status)) goto done;
463 sids_string = talloc_strdup(s3call, "");
464 if (sids_string == NULL) {
465 status = NT_STATUS_NO_MEMORY;
469 for (i=0; i<num_sids; i++) {
470 sids_string = talloc_asprintf_append_buffer(
471 sids_string, "%s\n", dom_sid_string(s3call, sids[i]));
472 if (sids_string == NULL) {
473 status = NT_STATUS_NO_MEMORY;
478 s3call->response.result = WINBINDD_OK;
479 s3call->response.extra_data.data = sids_string;
480 s3call->response.length += strlen(sids_string);
481 s3call->response.data.num_entries = num_sids;
483 /* Hmmmm. Nasty protocol -- who invented the zeros between the
484 * SIDs? Hmmm. Could have been me -- vl */
486 while (*sids_string != '\0') {
487 if ((*sids_string) == '\n') {
494 wbsrv_samba3_async_epilogue(status, s3call);
498 Lookup a DOMAIN\\user style name, and return a SID
501 static void lookupname_recv_sid(struct composite_context *ctx);
503 NTSTATUS wbsrv_samba3_lookupname(struct wbsrv_samba3_call *s3call)
505 struct composite_context *ctx;
506 struct wbsrv_service *service =
507 s3call->wbconn->listen_socket->service;
509 DEBUG(5, ("wbsrv_samba3_lookupname called\n"));
511 ctx = wb_cmd_lookupname_send(s3call, service,
512 s3call->request.data.name.dom_name,
513 s3call->request.data.name.name);
514 NT_STATUS_HAVE_NO_MEMORY(ctx);
516 /* setup the callbacks */
517 ctx->async.fn = lookupname_recv_sid;
518 ctx->async.private_data = s3call;
519 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
523 static void lookupname_recv_sid(struct composite_context *ctx)
525 struct wbsrv_samba3_call *s3call =
526 talloc_get_type(ctx->async.private_data,
527 struct wbsrv_samba3_call);
528 struct wb_sid_object *sid;
531 status = wb_cmd_lookupname_recv(ctx, s3call, &sid);
532 if (!NT_STATUS_IS_OK(status)) goto done;
534 s3call->response.result = WINBINDD_OK;
535 s3call->response.data.sid.type = sid->type;
536 WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid,
537 dom_sid_string(s3call, sid->sid));
540 wbsrv_samba3_async_epilogue(status, s3call);
544 Lookup a SID, and return a DOMAIN\\user style name
547 static void lookupsid_recv_name(struct composite_context *ctx);
549 NTSTATUS wbsrv_samba3_lookupsid(struct wbsrv_samba3_call *s3call)
551 struct composite_context *ctx;
552 struct wbsrv_service *service =
553 s3call->wbconn->listen_socket->service;
556 DEBUG(5, ("wbsrv_samba3_lookupsid called\n"));
558 sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
560 DEBUG(5, ("Could not parse sid %s\n",
561 s3call->request.data.sid));
562 return NT_STATUS_NO_MEMORY;
565 ctx = wb_cmd_lookupsid_send(s3call, service, sid);
566 NT_STATUS_HAVE_NO_MEMORY(ctx);
568 /* setup the callbacks */
569 ctx->async.fn = lookupsid_recv_name;
570 ctx->async.private_data = s3call;
571 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
575 static void lookupsid_recv_name(struct composite_context *ctx)
577 struct wbsrv_samba3_call *s3call =
578 talloc_get_type(ctx->async.private_data,
579 struct wbsrv_samba3_call);
580 struct wb_sid_object *sid;
583 status = wb_cmd_lookupsid_recv(ctx, s3call, &sid);
584 if (!NT_STATUS_IS_OK(status)) goto done;
586 s3call->response.result = WINBINDD_OK;
587 s3call->response.data.name.type = sid->type;
588 WBSRV_SAMBA3_SET_STRING(s3call->response.data.name.dom_name,
590 WBSRV_SAMBA3_SET_STRING(s3call->response.data.name.name, sid->name);
593 wbsrv_samba3_async_epilogue(status, s3call);
597 Challenge-response authentication. This interface is used by
598 ntlm_auth and the smbd auth subsystem to pass NTLM authentication
599 requests along a common pipe to the domain controller.
601 The return value (in the async reply) may include the 'info3'
602 (effectivly most things you would want to know about the user), or
603 the NT and LM session keys seperated.
606 static void pam_auth_crap_recv(struct composite_context *ctx);
608 NTSTATUS wbsrv_samba3_pam_auth_crap(struct wbsrv_samba3_call *s3call)
610 struct composite_context *ctx;
611 struct wbsrv_service *service =
612 s3call->wbconn->listen_socket->service;
613 DATA_BLOB chal, nt_resp, lm_resp;
615 DEBUG(5, ("wbsrv_samba3_pam_auth_crap called\n"));
617 chal.data = s3call->request.data.auth_crap.chal;
618 chal.length = sizeof(s3call->request.data.auth_crap.chal);
619 nt_resp.data = (uint8_t *)s3call->request.data.auth_crap.nt_resp;
620 nt_resp.length = s3call->request.data.auth_crap.nt_resp_len;
621 lm_resp.data = (uint8_t *)s3call->request.data.auth_crap.lm_resp;
622 lm_resp.length = s3call->request.data.auth_crap.lm_resp_len;
624 ctx = wb_cmd_pam_auth_crap_send(
626 s3call->request.data.auth_crap.logon_parameters,
627 s3call->request.data.auth_crap.domain,
628 s3call->request.data.auth_crap.user,
629 s3call->request.data.auth_crap.workstation,
630 chal, nt_resp, lm_resp);
631 NT_STATUS_HAVE_NO_MEMORY(ctx);
633 ctx->async.fn = pam_auth_crap_recv;
634 ctx->async.private_data = s3call;
635 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
639 static void pam_auth_crap_recv(struct composite_context *ctx)
641 struct wbsrv_samba3_call *s3call =
642 talloc_get_type(ctx->async.private_data,
643 struct wbsrv_samba3_call);
646 struct netr_UserSessionKey user_session_key;
647 struct netr_LMSessionKey lm_key;
650 status = wb_cmd_pam_auth_crap_recv(ctx, s3call, &info3,
651 &user_session_key, &lm_key, &unix_username);
652 if (!NT_STATUS_IS_OK(status)) goto done;
654 if (s3call->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
655 memcpy(s3call->response.data.auth.user_session_key,
656 &user_session_key.key,
657 sizeof(s3call->response.data.auth.user_session_key));
660 if (s3call->request.flags & WBFLAG_PAM_INFO3_TEXT) {
661 status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
662 if (!NT_STATUS_IS_OK(status)) {
663 DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
669 if (s3call->request.flags & WBFLAG_PAM_INFO3_NDR) {
670 s3call->response.extra_data.data = info3.data;
671 s3call->response.length += info3.length;
674 if (s3call->request.flags & WBFLAG_PAM_LMKEY) {
675 memcpy(s3call->response.data.auth.first_8_lm_hash,
677 sizeof(s3call->response.data.auth.first_8_lm_hash));
680 if (s3call->request.flags & WBFLAG_PAM_UNIX_NAME) {
681 s3call->response.extra_data.data = unix_username;
682 s3call->response.length += strlen(unix_username)+1;
686 wbsrv_samba3_async_auth_epilogue(status, s3call);
689 /* Plaintext authentication
691 This interface is used by ntlm_auth in it's 'basic' authentication
692 mode, as well as by pam_winbind to authenticate users where we are
693 given a plaintext password.
696 static void pam_auth_recv(struct composite_context *ctx);
698 NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call)
700 struct composite_context *ctx;
701 struct wbsrv_service *service =
702 s3call->wbconn->listen_socket->service;
703 struct cli_credentials *credentials;
706 if (!wb_samba3_split_username(s3call, s3call->wbconn->lp_ctx,
707 s3call->request.data.auth.user,
709 return NT_STATUS_NO_SUCH_USER;
712 credentials = cli_credentials_init(s3call);
714 return NT_STATUS_NO_MEMORY;
716 cli_credentials_set_conf(credentials, service->task->lp_ctx);
717 cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
718 cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
720 cli_credentials_set_password(credentials, s3call->request.data.auth.pass, CRED_SPECIFIED);
722 ctx = wb_cmd_pam_auth_send(s3call, service, credentials);
723 NT_STATUS_HAVE_NO_MEMORY(ctx);
725 ctx->async.fn = pam_auth_recv;
726 ctx->async.private_data = s3call;
727 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
731 static void pam_auth_recv(struct composite_context *ctx)
733 struct wbsrv_samba3_call *s3call =
734 talloc_get_type(ctx->async.private_data,
735 struct wbsrv_samba3_call);
738 struct netr_UserSessionKey user_session_key;
739 struct netr_LMSessionKey lm_key;
742 status = wb_cmd_pam_auth_recv(ctx, s3call, &info3,
743 &user_session_key, &lm_key, &unix_username);
745 if (!NT_STATUS_IS_OK(status)) goto done;
747 if (s3call->request.flags & WBFLAG_PAM_USER_SESSION_KEY) {
748 memcpy(s3call->response.data.auth.user_session_key,
749 &user_session_key.key,
750 sizeof(s3call->response.data.auth.user_session_key));
753 if (s3call->request.flags & WBFLAG_PAM_INFO3_TEXT) {
754 status = wb_samba3_append_info3_as_txt(ctx, s3call, info3);
755 if (!NT_STATUS_IS_OK(status)) {
756 DEBUG(10,("Failed to append INFO3 (TXT): %s\n",
762 if (s3call->request.flags & WBFLAG_PAM_INFO3_NDR) {
763 s3call->response.extra_data.data = info3.data;
764 s3call->response.length += info3.length;
767 if (s3call->request.flags & WBFLAG_PAM_LMKEY) {
768 memcpy(s3call->response.data.auth.first_8_lm_hash,
770 sizeof(s3call->response.data.auth.first_8_lm_hash));
773 if (s3call->request.flags & WBFLAG_PAM_UNIX_NAME) {
774 s3call->response.extra_data.data = unix_username;
775 s3call->response.length += strlen(unix_username)+1;
780 wbsrv_samba3_async_auth_epilogue(status, s3call);
787 static void list_trustdom_recv_doms(struct composite_context *ctx);
789 NTSTATUS wbsrv_samba3_list_trustdom(struct wbsrv_samba3_call *s3call)
791 struct composite_context *ctx;
792 struct wbsrv_service *service =
793 s3call->wbconn->listen_socket->service;
795 DEBUG(5, ("wbsrv_samba3_list_trustdom called\n"));
797 ctx = wb_cmd_list_trustdoms_send(s3call, service);
798 NT_STATUS_HAVE_NO_MEMORY(ctx);
800 ctx->async.fn = list_trustdom_recv_doms;
801 ctx->async.private_data = s3call;
802 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
806 static void list_trustdom_recv_doms(struct composite_context *ctx)
808 struct wbsrv_samba3_call *s3call =
809 talloc_get_type(ctx->async.private_data,
810 struct wbsrv_samba3_call);
812 struct wb_dom_info **domains;
816 status = wb_cmd_list_trustdoms_recv(ctx, s3call, &num_domains,
818 if (!NT_STATUS_IS_OK(status)) goto done;
820 result = talloc_strdup(s3call, "");
821 if (result == NULL) {
822 status = NT_STATUS_NO_MEMORY;
826 for (i=0; i<num_domains; i++) {
827 result = talloc_asprintf_append_buffer(
828 result, "%s\\%s\\%s",
829 domains[i]->name, domains[i]->name,
830 dom_sid_string(s3call, domains[i]->sid));
833 if (result == NULL) {
834 status = NT_STATUS_NO_MEMORY;
838 s3call->response.result = WINBINDD_OK;
839 if (num_domains > 0) {
840 s3call->response.extra_data.data = result;
841 s3call->response.length += strlen(result)+1;
845 wbsrv_samba3_async_epilogue(status, s3call);
849 static void list_groups_recv(struct composite_context *ctx);
851 NTSTATUS wbsrv_samba3_list_groups(struct wbsrv_samba3_call *s3call)
853 struct composite_context *ctx;
854 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
856 DEBUG(5, ("wbsrv_samba4_list_groups called\n"));
858 ctx = wb_cmd_list_groups_send(s3call, service,
859 s3call->request.domain_name);
860 NT_STATUS_HAVE_NO_MEMORY(ctx);
862 ctx->async.fn = list_groups_recv;
863 ctx->async.private_data = s3call;
864 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
868 static void list_groups_recv(struct composite_context *ctx)
870 struct wbsrv_samba3_call *s3call = talloc_get_type_abort(
871 ctx->async.private_data,
872 struct wbsrv_samba3_call);
873 uint32_t extra_data_len;
877 DEBUG(5, ("list_groups_recv called\n"));
879 status = wb_cmd_list_groups_recv(ctx, s3call, &extra_data_len,
882 if (NT_STATUS_IS_OK(status)) {
883 s3call->response.extra_data.data = extra_data;
884 s3call->response.length += extra_data_len;
886 s3call->response.length += 1;
890 wbsrv_samba3_async_epilogue(status, s3call);
895 static void list_users_recv(struct composite_context *ctx);
897 NTSTATUS wbsrv_samba3_list_users(struct wbsrv_samba3_call *s3call)
899 struct composite_context *ctx;
900 struct wbsrv_service *service =
901 s3call->wbconn->listen_socket->service;
903 DEBUG(5, ("wbsrv_samba3_list_users called\n"));
905 ctx = wb_cmd_list_users_send(s3call, service,
906 s3call->request.domain_name);
907 NT_STATUS_HAVE_NO_MEMORY(ctx);
909 ctx->async.fn = list_users_recv;
910 ctx->async.private_data = s3call;
911 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
915 static void list_users_recv(struct composite_context *ctx)
917 struct wbsrv_samba3_call *s3call =
918 talloc_get_type(ctx->async.private_data,
919 struct wbsrv_samba3_call);
920 uint32_t extra_data_len;
924 DEBUG(5, ("list_users_recv called\n"));
926 status = wb_cmd_list_users_recv(ctx, s3call, &extra_data_len,
929 if (NT_STATUS_IS_OK(status)) {
930 s3call->response.extra_data.data = extra_data;
931 s3call->response.length += extra_data_len;
933 s3call->response.length += 1;
937 wbsrv_samba3_async_epilogue(status, s3call);
942 static void getpwnam_recv(struct composite_context *ctx);
944 NTSTATUS wbsrv_samba3_getpwnam(struct wbsrv_samba3_call *s3call)
946 struct composite_context *ctx;
947 struct wbsrv_service *service =
948 s3call->wbconn->listen_socket->service;
950 DEBUG(5, ("wbsrv_samba3_getpwnam called\n"));
952 ctx = wb_cmd_getpwnam_send(s3call, service,
953 s3call->request.data.username);
954 NT_STATUS_HAVE_NO_MEMORY(ctx);
956 ctx->async.fn = getpwnam_recv;
957 ctx->async.private_data = s3call;
958 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
962 static void getpwnam_recv(struct composite_context *ctx)
964 struct wbsrv_samba3_call *s3call =
965 talloc_get_type(ctx->async.private_data,
966 struct wbsrv_samba3_call);
968 struct winbindd_pw *pw;
970 DEBUG(5, ("getpwnam_recv called\n"));
972 status = wb_cmd_getpwnam_recv(ctx, s3call, &pw);
973 if(NT_STATUS_IS_OK(status))
974 s3call->response.data.pw = *pw;
976 wbsrv_samba3_async_epilogue(status, s3call);
979 static void getpwuid_recv(struct composite_context *ctx);
981 NTSTATUS wbsrv_samba3_getpwuid(struct wbsrv_samba3_call *s3call)
983 struct composite_context *ctx;
984 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
986 DEBUG(5, ("wbsrv_samba3_getpwuid called\n"));
988 ctx = wb_cmd_getpwuid_send(s3call, service,
989 s3call->request.data.uid);
990 NT_STATUS_HAVE_NO_MEMORY(ctx);
992 ctx->async.fn = getpwuid_recv;
993 ctx->async.private_data = s3call;
994 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
998 static void getpwuid_recv(struct composite_context *ctx)
1000 struct wbsrv_samba3_call *s3call =
1001 talloc_get_type(ctx->async.private_data,
1002 struct wbsrv_samba3_call);
1004 struct winbindd_pw *pw;
1006 DEBUG(5, ("getpwuid_recv called\n"));
1008 status = wb_cmd_getpwuid_recv(ctx, s3call, &pw);
1009 if (NT_STATUS_IS_OK(status))
1010 s3call->response.data.pw = *pw;
1012 wbsrv_samba3_async_epilogue(status, s3call);
1015 static void setpwent_recv(struct composite_context *ctx);
1017 NTSTATUS wbsrv_samba3_setpwent(struct wbsrv_samba3_call *s3call)
1019 struct composite_context *ctx;
1020 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1022 DEBUG(5, ("wbsrv_samba3_setpwent called\n"));
1024 ctx = wb_cmd_setpwent_send(s3call, service);
1025 NT_STATUS_HAVE_NO_MEMORY(ctx);
1027 ctx->async.fn = setpwent_recv;
1028 ctx->async.private_data = s3call;
1029 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1030 return NT_STATUS_OK;
1033 static void setpwent_recv(struct composite_context *ctx)
1035 struct wbsrv_samba3_call *s3call =
1036 talloc_get_type(ctx->async.private_data,
1037 struct wbsrv_samba3_call);
1039 struct wbsrv_pwent *pwent;
1041 DEBUG(5, ("setpwent_recv called\n"));
1043 status = wb_cmd_setpwent_recv(ctx, s3call->wbconn, &pwent);
1044 if (NT_STATUS_IS_OK(status)) {
1045 s3call->wbconn->protocol_private_data = pwent;
1048 wbsrv_samba3_async_epilogue(status, s3call);
1051 static void getpwent_recv(struct composite_context *ctx);
1053 NTSTATUS wbsrv_samba3_getpwent(struct wbsrv_samba3_call *s3call)
1055 struct composite_context *ctx;
1056 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1057 struct wbsrv_pwent *pwent;
1059 DEBUG(5, ("wbsrv_samba3_getpwent called\n"));
1061 NT_STATUS_HAVE_NO_MEMORY(s3call->wbconn->protocol_private_data);
1063 pwent = talloc_get_type(s3call->wbconn->protocol_private_data,
1064 struct wbsrv_pwent);
1065 NT_STATUS_HAVE_NO_MEMORY(pwent);
1067 ctx = wb_cmd_getpwent_send(s3call, service, pwent,
1068 s3call->request.data.num_entries);
1069 NT_STATUS_HAVE_NO_MEMORY(ctx);
1071 ctx->async.fn = getpwent_recv;
1072 ctx->async.private_data = s3call;
1073 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1074 return NT_STATUS_OK;
1077 static void getpwent_recv(struct composite_context *ctx)
1079 struct wbsrv_samba3_call *s3call =
1080 talloc_get_type(ctx->async.private_data,
1081 struct wbsrv_samba3_call);
1083 struct winbindd_pw *pw;
1086 DEBUG(5, ("getpwent_recv called\n"));
1088 status = wb_cmd_getpwent_recv(ctx, s3call, &pw, &num_users);
1089 if (NT_STATUS_IS_OK(status)) {
1090 uint32_t extra_len = sizeof(struct winbindd_pw) * num_users;
1092 s3call->response.data.num_entries = num_users;
1093 s3call->response.extra_data.data = pw;
1094 s3call->response.length += extra_len;
1097 wbsrv_samba3_async_epilogue(status, s3call);
1100 NTSTATUS wbsrv_samba3_endpwent(struct wbsrv_samba3_call *s3call)
1102 struct wbsrv_pwent *pwent =
1103 talloc_get_type(s3call->wbconn->protocol_private_data,
1104 struct wbsrv_pwent);
1105 DEBUG(5, ("wbsrv_samba3_endpwent called\n"));
1109 s3call->wbconn->protocol_private_data = NULL;
1110 s3call->response.result = WINBINDD_OK;
1111 return NT_STATUS_OK;
1115 static void getgrnam_recv(struct composite_context *ctx);
1117 NTSTATUS wbsrv_samba3_getgrnam(struct wbsrv_samba3_call *s3call)
1119 struct composite_context *ctx;
1120 struct wbsrv_service *service =
1121 s3call->wbconn->listen_socket->service;
1123 DEBUG(5, ("wbsrv_samba3_getgrnam called\n"));
1125 ctx = wb_cmd_getgrnam_send(s3call, service,
1126 s3call->request.data.groupname);
1127 NT_STATUS_HAVE_NO_MEMORY(ctx);
1129 ctx->async.fn = getgrnam_recv;
1130 ctx->async.private_data = s3call;
1131 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1132 return NT_STATUS_OK;
1135 static void getgrnam_recv(struct composite_context *ctx)
1137 struct wbsrv_samba3_call *s3call =
1138 talloc_get_type(ctx->async.private_data,
1139 struct wbsrv_samba3_call);
1141 struct winbindd_gr *gr;
1143 DEBUG(5, ("getgrnam_recv called\n"));
1145 status = wb_cmd_getgrnam_recv(ctx, s3call, &gr);
1146 if(NT_STATUS_IS_OK(status))
1147 s3call->response.data.gr = *gr;
1149 wbsrv_samba3_async_epilogue(status, s3call);
1152 static void getgrgid_recv(struct composite_context *ctx);
1154 NTSTATUS wbsrv_samba3_getgrgid(struct wbsrv_samba3_call *s3call)
1156 struct composite_context *ctx;
1157 struct wbsrv_service *service = s3call->wbconn->listen_socket->service;
1159 DEBUG(5, ("wbsrv_samba3_getgrgid called\n"));
1161 ctx = wb_cmd_getgrgid_send(s3call, service,
1162 s3call->request.data.gid);
1163 NT_STATUS_HAVE_NO_MEMORY(ctx);
1165 ctx->async.fn = getgrgid_recv;
1166 ctx->async.private_data = s3call;
1167 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1168 return NT_STATUS_OK;
1171 static void getgrgid_recv(struct composite_context *ctx)
1173 struct wbsrv_samba3_call *s3call =
1174 talloc_get_type(ctx->async.private_data,
1175 struct wbsrv_samba3_call);
1177 struct winbindd_gr *gr;
1179 DEBUG(5, ("getgrgid_recv called\n"));
1181 status = wb_cmd_getgrgid_recv(ctx, s3call, &gr);
1182 if (NT_STATUS_IS_OK(status))
1183 s3call->response.data.gr = *gr;
1185 wbsrv_samba3_async_epilogue(status, s3call);
1188 NTSTATUS wbsrv_samba3_getgroups(struct wbsrv_samba3_call *s3call)
1190 DEBUG(5, ("wbsrv_samba3_getgroups called\n"));
1191 s3call->response.result = WINBINDD_ERROR;
1192 return NT_STATUS_OK;
1195 NTSTATUS wbsrv_samba3_setgrent(struct wbsrv_samba3_call *s3call)
1197 DEBUG(5, ("wbsrv_samba3_setgrent called\n"));
1198 s3call->response.result = WINBINDD_OK;
1199 return NT_STATUS_OK;
1202 NTSTATUS wbsrv_samba3_getgrent(struct wbsrv_samba3_call *s3call)
1204 DEBUG(5, ("wbsrv_samba3_getgrent called\n"));
1205 s3call->response.result = WINBINDD_ERROR;
1206 return NT_STATUS_OK;
1209 NTSTATUS wbsrv_samba3_endgrent(struct wbsrv_samba3_call *s3call)
1211 DEBUG(5, ("wbsrv_samba3_endgrent called\n"));
1212 s3call->response.result = WINBINDD_OK;
1213 return NT_STATUS_OK;
1216 static void sid2uid_recv(struct composite_context *ctx);
1218 NTSTATUS wbsrv_samba3_sid2uid(struct wbsrv_samba3_call *s3call)
1220 struct composite_context *ctx;
1221 struct wbsrv_service *service =
1222 s3call->wbconn->listen_socket->service;
1223 struct dom_sid *sid;
1225 DEBUG(5, ("wbsrv_samba3_sid2uid called\n"));
1227 sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
1228 NT_STATUS_HAVE_NO_MEMORY(sid);
1230 ctx = wb_sid2uid_send(s3call, service, sid);
1231 NT_STATUS_HAVE_NO_MEMORY(ctx);
1233 ctx->async.fn = sid2uid_recv;
1234 ctx->async.private_data = s3call;
1235 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1236 return NT_STATUS_OK;
1240 static void sid2uid_recv(struct composite_context *ctx)
1242 struct wbsrv_samba3_call *s3call =
1243 talloc_get_type(ctx->async.private_data,
1244 struct wbsrv_samba3_call);
1247 DEBUG(5, ("sid2uid_recv called\n"));
1249 status = wb_sid2uid_recv(ctx, &s3call->response.data.uid);
1251 wbsrv_samba3_async_epilogue(status, s3call);
1254 static void sid2gid_recv(struct composite_context *ctx);
1256 NTSTATUS wbsrv_samba3_sid2gid(struct wbsrv_samba3_call *s3call)
1258 struct composite_context *ctx;
1259 struct wbsrv_service *service =
1260 s3call->wbconn->listen_socket->service;
1261 struct dom_sid *sid;
1263 DEBUG(5, ("wbsrv_samba3_sid2gid called\n"));
1265 sid = dom_sid_parse_talloc(s3call, s3call->request.data.sid);
1266 NT_STATUS_HAVE_NO_MEMORY(sid);
1268 ctx = wb_sid2gid_send(s3call, service, sid);
1269 NT_STATUS_HAVE_NO_MEMORY(ctx);
1271 ctx->async.fn = sid2gid_recv;
1272 ctx->async.private_data = s3call;
1273 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1274 return NT_STATUS_OK;
1278 static void sid2gid_recv(struct composite_context *ctx)
1280 struct wbsrv_samba3_call *s3call =
1281 talloc_get_type(ctx->async.private_data,
1282 struct wbsrv_samba3_call);
1285 DEBUG(5, ("sid2gid_recv called\n"));
1287 status = wb_sid2gid_recv(ctx, &s3call->response.data.gid);
1289 wbsrv_samba3_async_epilogue(status, s3call);
1292 static void uid2sid_recv(struct composite_context *ctx);
1294 NTSTATUS wbsrv_samba3_uid2sid(struct wbsrv_samba3_call *s3call)
1296 struct composite_context *ctx;
1297 struct wbsrv_service *service =
1298 s3call->wbconn->listen_socket->service;
1300 DEBUG(5, ("wbsrv_samba3_uid2sid called\n"));
1302 ctx = wb_uid2sid_send(s3call, service, s3call->request.data.uid);
1303 NT_STATUS_HAVE_NO_MEMORY(ctx);
1305 ctx->async.fn = uid2sid_recv;
1306 ctx->async.private_data = s3call;
1307 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1308 return NT_STATUS_OK;
1312 static void uid2sid_recv(struct composite_context *ctx)
1314 struct wbsrv_samba3_call *s3call =
1315 talloc_get_type(ctx->async.private_data,
1316 struct wbsrv_samba3_call);
1318 struct dom_sid *sid;
1321 DEBUG(5, ("uid2sid_recv called\n"));
1323 status = wb_uid2sid_recv(ctx, s3call, &sid);
1324 if(NT_STATUS_IS_OK(status)) {
1325 sid_str = dom_sid_string(s3call, sid);
1327 /* If the conversion failed, bail out with a failure. */
1328 if (sid_str == NULL)
1329 wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1331 /* But we assume this worked, so we'll set the string. Work
1333 WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid, sid_str);
1334 s3call->response.data.sid.type = SID_NAME_USER;
1337 wbsrv_samba3_async_epilogue(status, s3call);
1340 static void gid2sid_recv(struct composite_context *ctx);
1342 NTSTATUS wbsrv_samba3_gid2sid(struct wbsrv_samba3_call *s3call)
1344 struct composite_context *ctx;
1345 struct wbsrv_service *service =
1346 s3call->wbconn->listen_socket->service;
1348 DEBUG(5, ("wbsrv_samba3_gid2sid called\n"));
1350 ctx = wb_gid2sid_send(s3call, service, s3call->request.data.gid);
1351 NT_STATUS_HAVE_NO_MEMORY(ctx);
1353 ctx->async.fn = gid2sid_recv;
1354 ctx->async.private_data = s3call;
1355 s3call->flags |= WBSRV_CALL_FLAGS_REPLY_ASYNC;
1356 return NT_STATUS_OK;
1360 static void gid2sid_recv(struct composite_context *ctx)
1362 struct wbsrv_samba3_call *s3call =
1363 talloc_get_type(ctx->async.private_data,
1364 struct wbsrv_samba3_call);
1366 struct dom_sid *sid;
1369 DEBUG(5, ("gid2sid_recv called\n"));
1371 status = wb_gid2sid_recv(ctx, s3call, &sid);
1372 if(NT_STATUS_IS_OK(status)) {
1373 sid_str = dom_sid_string(s3call, sid);
1375 if (sid_str == NULL)
1376 wbsrv_samba3_async_epilogue(NT_STATUS_NO_MEMORY,s3call);
1378 WBSRV_SAMBA3_SET_STRING(s3call->response.data.sid.sid, sid_str);
1379 s3call->response.data.sid.type = SID_NAME_DOMAIN;
1382 wbsrv_samba3_async_epilogue(status, s3call);