nfs4acls: Introduce a helper variable
[Samba.git] / source3 / winbindd / winbindd_samr.c
blob3d0914a3d7c7d0cc6bfdb4a48bbc3aa70580636d
1 /*
2 * Unix SMB/CIFS implementation.
4 * Winbind rpc backend functions
6 * Copyright (c) 2000-2003 Tim Potter
7 * Copyright (c) 2001 Andrew Tridgell
8 * Copyright (c) 2005 Volker Lendecke
9 * Copyright (c) 2008 Guenther Deschner (pidl conversion)
10 * Copyright (c) 2010 Andreas Schneider <asn@samba.org>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "winbindd.h"
28 #include "winbindd_rpc.h"
29 #include "rpc_client/rpc_client.h"
30 #include "../librpc/gen_ndr/ndr_samr_c.h"
31 #include "rpc_client/cli_samr.h"
32 #include "../librpc/gen_ndr/ndr_lsa_c.h"
33 #include "rpc_client/cli_lsarpc.h"
34 #include "rpc_server/rpc_ncacn_np.h"
35 #include "../libcli/security/security.h"
36 #include "passdb/machine_sid.h"
37 #include "auth.h"
39 #undef DBGC_CLASS
40 #define DBGC_CLASS DBGC_WINBIND
42 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
43 struct winbindd_domain *domain,
44 struct rpc_pipe_client **samr_pipe,
45 struct policy_handle *samr_domain_hnd)
47 NTSTATUS status, result;
48 struct policy_handle samr_connect_hnd;
49 struct dcerpc_binding_handle *b;
51 status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
52 if (!NT_STATUS_IS_OK(status)) {
53 return status;
56 b = (*samr_pipe)->binding_handle;
58 status = dcerpc_samr_Connect2(b, mem_ctx,
59 (*samr_pipe)->desthost,
60 SEC_FLAG_MAXIMUM_ALLOWED,
61 &samr_connect_hnd,
62 &result);
63 if (!NT_STATUS_IS_OK(status)) {
64 return status;
66 if (!NT_STATUS_IS_OK(result)) {
67 return result;
70 status = dcerpc_samr_OpenDomain(b, mem_ctx,
71 &samr_connect_hnd,
72 SEC_FLAG_MAXIMUM_ALLOWED,
73 &domain->sid,
74 samr_domain_hnd,
75 &result);
76 if (!NT_STATUS_IS_OK(status)) {
77 return status;
80 return result;
83 NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
84 struct rpc_pipe_client **lsa_pipe,
85 struct policy_handle *lsa_hnd)
87 NTSTATUS status;
89 status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
90 if (!NT_STATUS_IS_OK(status)) {
91 return status;
94 status = rpccli_lsa_open_policy((*lsa_pipe),
95 mem_ctx,
96 true,
97 SEC_FLAG_MAXIMUM_ALLOWED,
98 lsa_hnd);
100 return status;
103 /*********************************************************************
104 SAM specific functions.
105 *********************************************************************/
107 /* List all domain groups */
108 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
109 TALLOC_CTX *mem_ctx,
110 uint32_t *pnum_info,
111 struct wb_acct_info **pinfo)
113 struct rpc_pipe_client *samr_pipe;
114 struct policy_handle dom_pol;
115 struct wb_acct_info *info = NULL;
116 uint32_t num_info = 0;
117 TALLOC_CTX *tmp_ctx;
118 NTSTATUS status, result;
119 struct dcerpc_binding_handle *b = NULL;
121 DEBUG(3,("sam_enum_dom_groups\n"));
123 ZERO_STRUCT(dom_pol);
125 if (pnum_info) {
126 *pnum_info = 0;
129 tmp_ctx = talloc_stackframe();
130 if (tmp_ctx == NULL) {
131 return NT_STATUS_NO_MEMORY;
134 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
135 if (!NT_STATUS_IS_OK(status)) {
136 goto error;
139 b = samr_pipe->binding_handle;
141 status = rpc_enum_dom_groups(tmp_ctx,
142 samr_pipe,
143 &dom_pol,
144 &num_info,
145 &info);
146 if (!NT_STATUS_IS_OK(status)) {
147 goto error;
150 if (pnum_info) {
151 *pnum_info = num_info;
154 if (pinfo) {
155 *pinfo = talloc_move(mem_ctx, &info);
158 error:
159 if (b && is_valid_policy_hnd(&dom_pol)) {
160 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
162 TALLOC_FREE(tmp_ctx);
163 return status;
166 /* Query display info for a domain */
167 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
168 TALLOC_CTX *mem_ctx,
169 uint32_t *pnum_info,
170 struct wbint_userinfo **pinfo)
172 struct rpc_pipe_client *samr_pipe = NULL;
173 struct policy_handle dom_pol;
174 struct wbint_userinfo *info = NULL;
175 uint32_t num_info = 0;
176 TALLOC_CTX *tmp_ctx;
177 NTSTATUS status, result;
178 struct dcerpc_binding_handle *b = NULL;
180 DEBUG(3,("samr_query_user_list\n"));
182 ZERO_STRUCT(dom_pol);
184 if (pnum_info) {
185 *pnum_info = 0;
188 tmp_ctx = talloc_stackframe();
189 if (tmp_ctx == NULL) {
190 return NT_STATUS_NO_MEMORY;
193 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
194 if (!NT_STATUS_IS_OK(status)) {
195 goto done;
198 b = samr_pipe->binding_handle;
200 status = rpc_query_user_list(tmp_ctx,
201 samr_pipe,
202 &dom_pol,
203 &domain->sid,
204 &num_info,
205 &info);
206 if (!NT_STATUS_IS_OK(status)) {
207 goto done;
210 if (pnum_info) {
211 *pnum_info = num_info;
214 if (pinfo) {
215 *pinfo = talloc_move(mem_ctx, &info);
218 done:
219 if (b && is_valid_policy_hnd(&dom_pol)) {
220 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
223 TALLOC_FREE(tmp_ctx);
224 return status;
227 /* Lookup user information from a rid or username. */
228 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
229 TALLOC_CTX *mem_ctx,
230 const struct dom_sid *user_sid,
231 struct wbint_userinfo *user_info)
233 struct rpc_pipe_client *samr_pipe;
234 struct policy_handle dom_pol;
235 TALLOC_CTX *tmp_ctx;
236 NTSTATUS status, result;
237 struct dcerpc_binding_handle *b = NULL;
239 DEBUG(3,("sam_query_user\n"));
241 ZERO_STRUCT(dom_pol);
243 /* Paranoia check */
244 if (!sid_check_is_in_our_sam(user_sid)) {
245 return NT_STATUS_NO_SUCH_USER;
248 user_info->homedir = NULL;
249 user_info->shell = NULL;
250 user_info->primary_gid = (gid_t) -1;
252 tmp_ctx = talloc_stackframe();
253 if (tmp_ctx == NULL) {
254 return NT_STATUS_NO_MEMORY;
257 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
258 if (!NT_STATUS_IS_OK(status)) {
259 goto done;
262 b = samr_pipe->binding_handle;
264 status = rpc_query_user(tmp_ctx,
265 samr_pipe,
266 &dom_pol,
267 &domain->sid,
268 user_sid,
269 user_info);
271 done:
272 if (b && is_valid_policy_hnd(&dom_pol)) {
273 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
276 TALLOC_FREE(tmp_ctx);
277 return status;
280 /* get a list of trusted domains - builtin domain */
281 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
282 TALLOC_CTX *mem_ctx,
283 struct netr_DomainTrustList *ptrust_list)
285 struct rpc_pipe_client *lsa_pipe;
286 struct policy_handle lsa_policy;
287 struct netr_DomainTrust *trusts = NULL;
288 uint32_t num_trusts = 0;
289 TALLOC_CTX *tmp_ctx;
290 NTSTATUS status, result;
291 struct dcerpc_binding_handle *b = NULL;
293 DEBUG(3,("samr: trusted domains\n"));
295 ZERO_STRUCT(lsa_policy);
297 if (ptrust_list) {
298 ZERO_STRUCTP(ptrust_list);
301 tmp_ctx = talloc_stackframe();
302 if (tmp_ctx == NULL) {
303 return NT_STATUS_NO_MEMORY;
306 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
307 if (!NT_STATUS_IS_OK(status)) {
308 goto done;
311 b = lsa_pipe->binding_handle;
313 status = rpc_trusted_domains(tmp_ctx,
314 lsa_pipe,
315 &lsa_policy,
316 &num_trusts,
317 &trusts);
318 if (!NT_STATUS_IS_OK(status)) {
319 goto done;
322 if (ptrust_list) {
323 ptrust_list->count = num_trusts;
324 ptrust_list->array = talloc_move(mem_ctx, &trusts);
327 done:
328 if (b && is_valid_policy_hnd(&lsa_policy)) {
329 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
332 TALLOC_FREE(tmp_ctx);
333 return status;
336 /* Lookup group membership given a rid. */
337 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
338 TALLOC_CTX *mem_ctx,
339 const struct dom_sid *group_sid,
340 enum lsa_SidType type,
341 uint32_t *pnum_names,
342 struct dom_sid **psid_mem,
343 char ***pnames,
344 uint32_t **pname_types)
346 struct rpc_pipe_client *samr_pipe;
347 struct policy_handle dom_pol;
349 uint32_t num_names = 0;
350 struct dom_sid *sid_mem = NULL;
351 char **names = NULL;
352 uint32_t *name_types = NULL;
354 TALLOC_CTX *tmp_ctx;
355 NTSTATUS status, result;
356 struct dcerpc_binding_handle *b = NULL;
358 DEBUG(3,("sam_lookup_groupmem\n"));
360 ZERO_STRUCT(dom_pol);
362 /* Paranoia check */
363 if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
364 /* There's no groups, only aliases in BUILTIN */
365 return NT_STATUS_NO_SUCH_GROUP;
368 if (pnum_names) {
369 *pnum_names = 0;
372 tmp_ctx = talloc_stackframe();
373 if (tmp_ctx == NULL) {
374 return NT_STATUS_NO_MEMORY;
377 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
378 if (!NT_STATUS_IS_OK(status)) {
379 goto done;
382 b = samr_pipe->binding_handle;
384 status = rpc_lookup_groupmem(tmp_ctx,
385 samr_pipe,
386 &dom_pol,
387 domain->name,
388 &domain->sid,
389 group_sid,
390 type,
391 &num_names,
392 &sid_mem,
393 &names,
394 &name_types);
396 if (pnum_names) {
397 *pnum_names = num_names;
400 if (pnames) {
401 *pnames = talloc_move(mem_ctx, &names);
404 if (pname_types) {
405 *pname_types = talloc_move(mem_ctx, &name_types);
408 if (psid_mem) {
409 *psid_mem = talloc_move(mem_ctx, &sid_mem);
412 done:
413 if (b && is_valid_policy_hnd(&dom_pol)) {
414 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
417 TALLOC_FREE(tmp_ctx);
418 return status;
421 /*********************************************************************
422 BUILTIN specific functions.
423 *********************************************************************/
425 /* List all domain groups */
426 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
427 TALLOC_CTX *mem_ctx,
428 uint32_t *num_entries,
429 struct wb_acct_info **info)
431 /* BUILTIN doesn't have domain groups */
432 *num_entries = 0;
433 *info = NULL;
434 return NT_STATUS_OK;
437 /* Query display info for a domain */
438 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
439 TALLOC_CTX *mem_ctx,
440 uint32_t *num_entries,
441 struct wbint_userinfo **info)
443 /* We don't have users */
444 *num_entries = 0;
445 *info = NULL;
446 return NT_STATUS_OK;
449 /* Lookup user information from a rid or username. */
450 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
451 TALLOC_CTX *mem_ctx,
452 const struct dom_sid *user_sid,
453 struct wbint_userinfo *user_info)
455 return NT_STATUS_NO_SUCH_USER;
458 /* get a list of trusted domains - builtin domain */
459 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
460 TALLOC_CTX *mem_ctx,
461 struct netr_DomainTrustList *trusts)
463 ZERO_STRUCTP(trusts);
464 return NT_STATUS_OK;
467 /*********************************************************************
468 COMMON functions.
469 *********************************************************************/
471 /* List all local groups (aliases) */
472 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
473 TALLOC_CTX *mem_ctx,
474 uint32_t *pnum_info,
475 struct wb_acct_info **pinfo)
477 struct rpc_pipe_client *samr_pipe;
478 struct policy_handle dom_pol;
479 struct wb_acct_info *info = NULL;
480 uint32_t num_info = 0;
481 TALLOC_CTX *tmp_ctx;
482 NTSTATUS status, result;
483 struct dcerpc_binding_handle *b = NULL;
485 DEBUG(3,("samr: enum local groups\n"));
487 ZERO_STRUCT(dom_pol);
489 if (pnum_info) {
490 *pnum_info = 0;
493 tmp_ctx = talloc_stackframe();
494 if (tmp_ctx == NULL) {
495 return NT_STATUS_NO_MEMORY;
498 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
499 if (!NT_STATUS_IS_OK(status)) {
500 goto done;
503 b = samr_pipe->binding_handle;
505 status = rpc_enum_local_groups(mem_ctx,
506 samr_pipe,
507 &dom_pol,
508 &num_info,
509 &info);
510 if (!NT_STATUS_IS_OK(status)) {
511 goto done;
514 if (pnum_info) {
515 *pnum_info = num_info;
518 if (pinfo) {
519 *pinfo = talloc_move(mem_ctx, &info);
522 done:
523 if (b && is_valid_policy_hnd(&dom_pol)) {
524 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
527 TALLOC_FREE(tmp_ctx);
528 return status;
531 /* convert a single name to a sid in a domain */
532 static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
533 TALLOC_CTX *mem_ctx,
534 const char *domain_name,
535 const char *name,
536 uint32_t flags,
537 struct dom_sid *psid,
538 enum lsa_SidType *ptype)
540 struct rpc_pipe_client *lsa_pipe;
541 struct policy_handle lsa_policy;
542 struct dom_sid sid;
543 enum lsa_SidType type;
544 TALLOC_CTX *tmp_ctx;
545 NTSTATUS status, result;
546 struct dcerpc_binding_handle *b = NULL;
548 DEBUG(3,("sam_name_to_sid\n"));
550 ZERO_STRUCT(lsa_policy);
552 tmp_ctx = talloc_stackframe();
553 if (tmp_ctx == NULL) {
554 return NT_STATUS_NO_MEMORY;
557 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
558 if (!NT_STATUS_IS_OK(status)) {
559 goto done;
562 b = lsa_pipe->binding_handle;
564 status = rpc_name_to_sid(tmp_ctx,
565 lsa_pipe,
566 &lsa_policy,
567 domain_name,
568 name,
569 flags,
570 &sid,
571 &type);
572 if (!NT_STATUS_IS_OK(status)) {
573 goto done;
576 if (psid) {
577 sid_copy(psid, &sid);
579 if (ptype) {
580 *ptype = type;
583 done:
584 if (b && is_valid_policy_hnd(&lsa_policy)) {
585 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
588 TALLOC_FREE(tmp_ctx);
589 return status;
592 /* convert a domain SID to a user or group name */
593 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
594 TALLOC_CTX *mem_ctx,
595 const struct dom_sid *sid,
596 char **pdomain_name,
597 char **pname,
598 enum lsa_SidType *ptype)
600 struct rpc_pipe_client *lsa_pipe;
601 struct policy_handle lsa_policy;
602 char *domain_name = NULL;
603 char *name = NULL;
604 enum lsa_SidType type;
605 TALLOC_CTX *tmp_ctx;
606 NTSTATUS status, result;
607 struct dcerpc_binding_handle *b = NULL;
609 DEBUG(3,("sam_sid_to_name\n"));
611 ZERO_STRUCT(lsa_policy);
613 /* Paranoia check */
614 if (!sid_check_is_in_builtin(sid) &&
615 !sid_check_is_builtin(sid) &&
616 !sid_check_is_in_our_sam(sid) &&
617 !sid_check_is_our_sam(sid) &&
618 !sid_check_is_in_unix_users(sid) &&
619 !sid_check_is_unix_users(sid) &&
620 !sid_check_is_in_unix_groups(sid) &&
621 !sid_check_is_unix_groups(sid) &&
622 !sid_check_is_in_wellknown_domain(sid)) {
623 DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to "
624 "lookup SID %s\n", sid_string_dbg(sid)));
625 return NT_STATUS_NONE_MAPPED;
628 tmp_ctx = talloc_stackframe();
629 if (tmp_ctx == NULL) {
630 return NT_STATUS_NO_MEMORY;
633 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
634 if (!NT_STATUS_IS_OK(status)) {
635 goto done;
638 b = lsa_pipe->binding_handle;
640 status = rpc_sid_to_name(tmp_ctx,
641 lsa_pipe,
642 &lsa_policy,
643 domain,
644 sid,
645 &domain_name,
646 &name,
647 &type);
649 if (ptype) {
650 *ptype = type;
653 if (pname) {
654 *pname = talloc_move(mem_ctx, &name);
657 if (pdomain_name) {
658 *pdomain_name = talloc_move(mem_ctx, &domain_name);
661 done:
662 if (b && is_valid_policy_hnd(&lsa_policy)) {
663 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
666 TALLOC_FREE(tmp_ctx);
667 return status;
670 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
671 TALLOC_CTX *mem_ctx,
672 const struct dom_sid *domain_sid,
673 uint32_t *rids,
674 size_t num_rids,
675 char **pdomain_name,
676 char ***pnames,
677 enum lsa_SidType **ptypes)
679 struct rpc_pipe_client *lsa_pipe;
680 struct policy_handle lsa_policy;
681 enum lsa_SidType *types = NULL;
682 char *domain_name = NULL;
683 char **names = NULL;
684 TALLOC_CTX *tmp_ctx;
685 NTSTATUS status, result;
686 struct dcerpc_binding_handle *b = NULL;
688 DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
690 ZERO_STRUCT(lsa_policy);
692 /* Paranoia check */
693 if (!sid_check_is_builtin(domain_sid) &&
694 !sid_check_is_our_sam(domain_sid) &&
695 !sid_check_is_unix_users(domain_sid) &&
696 !sid_check_is_unix_groups(domain_sid) &&
697 !sid_check_is_in_wellknown_domain(domain_sid)) {
698 DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to "
699 "lookup SID %s\n", sid_string_dbg(domain_sid)));
700 return NT_STATUS_NONE_MAPPED;
703 tmp_ctx = talloc_stackframe();
704 if (tmp_ctx == NULL) {
705 return NT_STATUS_NO_MEMORY;
708 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
709 if (!NT_STATUS_IS_OK(status)) {
710 goto done;
713 b = lsa_pipe->binding_handle;
715 status = rpc_rids_to_names(tmp_ctx,
716 lsa_pipe,
717 &lsa_policy,
718 domain,
719 domain_sid,
720 rids,
721 num_rids,
722 &domain_name,
723 &names,
724 &types);
725 if (!NT_STATUS_IS_OK(status)) {
726 goto done;
729 if (pdomain_name) {
730 *pdomain_name = talloc_move(mem_ctx, &domain_name);
733 if (ptypes) {
734 *ptypes = talloc_move(mem_ctx, &types);
737 if (pnames) {
738 *pnames = talloc_move(mem_ctx, &names);
741 done:
742 if (b && is_valid_policy_hnd(&lsa_policy)) {
743 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
746 TALLOC_FREE(tmp_ctx);
747 return status;
750 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
751 TALLOC_CTX *mem_ctx,
752 struct samr_DomInfo12 *lockout_policy)
754 struct rpc_pipe_client *samr_pipe;
755 struct policy_handle dom_pol;
756 union samr_DomainInfo *info = NULL;
757 TALLOC_CTX *tmp_ctx;
758 NTSTATUS status, result;
759 struct dcerpc_binding_handle *b = NULL;
761 DEBUG(3,("sam_lockout_policy\n"));
763 ZERO_STRUCT(dom_pol);
765 tmp_ctx = talloc_stackframe();
766 if (tmp_ctx == NULL) {
767 return NT_STATUS_NO_MEMORY;
770 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
771 if (!NT_STATUS_IS_OK(status)) {
772 goto error;
775 b = samr_pipe->binding_handle;
777 status = dcerpc_samr_QueryDomainInfo(b,
778 mem_ctx,
779 &dom_pol,
780 DomainLockoutInformation,
781 &info,
782 &result);
783 if (!NT_STATUS_IS_OK(status)) {
784 goto error;
786 if (!NT_STATUS_IS_OK(result)) {
787 status = result;
788 goto error;
791 *lockout_policy = info->info12;
793 error:
794 if (b && is_valid_policy_hnd(&dom_pol)) {
795 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
798 TALLOC_FREE(tmp_ctx);
799 return status;
802 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
803 TALLOC_CTX *mem_ctx,
804 struct samr_DomInfo1 *passwd_policy)
806 struct rpc_pipe_client *samr_pipe;
807 struct policy_handle dom_pol;
808 union samr_DomainInfo *info = NULL;
809 TALLOC_CTX *tmp_ctx;
810 NTSTATUS status, result;
811 struct dcerpc_binding_handle *b = NULL;
813 DEBUG(3,("sam_password_policy\n"));
815 ZERO_STRUCT(dom_pol);
817 tmp_ctx = talloc_stackframe();
818 if (tmp_ctx == NULL) {
819 return NT_STATUS_NO_MEMORY;
822 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
823 if (!NT_STATUS_IS_OK(status)) {
824 goto error;
827 b = samr_pipe->binding_handle;
829 status = dcerpc_samr_QueryDomainInfo(b,
830 mem_ctx,
831 &dom_pol,
832 DomainPasswordInformation,
833 &info,
834 &result);
835 if (!NT_STATUS_IS_OK(status)) {
836 goto error;
838 if (!NT_STATUS_IS_OK(result)) {
839 status = result;
840 goto error;
843 *passwd_policy = info->info1;
845 error:
846 if (b && is_valid_policy_hnd(&dom_pol)) {
847 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
850 TALLOC_FREE(tmp_ctx);
851 return status;
854 /* Lookup groups a user is a member of. */
855 static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
856 TALLOC_CTX *mem_ctx,
857 const struct dom_sid *user_sid,
858 uint32_t *pnum_groups,
859 struct dom_sid **puser_grpsids)
861 struct rpc_pipe_client *samr_pipe;
862 struct policy_handle dom_pol;
863 struct dom_sid *user_grpsids = NULL;
864 uint32_t num_groups = 0;
865 TALLOC_CTX *tmp_ctx;
866 NTSTATUS status, result;
867 struct dcerpc_binding_handle *b = NULL;
869 DEBUG(3,("sam_lookup_usergroups\n"));
871 ZERO_STRUCT(dom_pol);
873 if (pnum_groups) {
874 *pnum_groups = 0;
877 tmp_ctx = talloc_stackframe();
878 if (tmp_ctx == NULL) {
879 return NT_STATUS_NO_MEMORY;
882 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
883 if (!NT_STATUS_IS_OK(status)) {
884 goto done;
887 b = samr_pipe->binding_handle;
889 status = rpc_lookup_usergroups(tmp_ctx,
890 samr_pipe,
891 &dom_pol,
892 &domain->sid,
893 user_sid,
894 &num_groups,
895 &user_grpsids);
896 if (!NT_STATUS_IS_OK(status)) {
897 goto done;
900 if (pnum_groups) {
901 *pnum_groups = num_groups;
904 if (puser_grpsids) {
905 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
908 done:
909 if (b && is_valid_policy_hnd(&dom_pol)) {
910 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
913 TALLOC_FREE(tmp_ctx);
914 return status;
917 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
918 TALLOC_CTX *mem_ctx,
919 uint32_t num_sids,
920 const struct dom_sid *sids,
921 uint32_t *pnum_aliases,
922 uint32_t **palias_rids)
924 struct rpc_pipe_client *samr_pipe;
925 struct policy_handle dom_pol;
926 uint32_t num_aliases = 0;
927 uint32_t *alias_rids = NULL;
928 TALLOC_CTX *tmp_ctx;
929 NTSTATUS status, result;
930 struct dcerpc_binding_handle *b = NULL;
932 DEBUG(3,("sam_lookup_useraliases\n"));
934 ZERO_STRUCT(dom_pol);
936 if (pnum_aliases) {
937 *pnum_aliases = 0;
940 tmp_ctx = talloc_stackframe();
941 if (tmp_ctx == NULL) {
942 return NT_STATUS_NO_MEMORY;
945 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
946 if (!NT_STATUS_IS_OK(status)) {
947 goto done;
950 b = samr_pipe->binding_handle;
952 status = rpc_lookup_useraliases(tmp_ctx,
953 samr_pipe,
954 &dom_pol,
955 num_sids,
956 sids,
957 &num_aliases,
958 &alias_rids);
959 if (!NT_STATUS_IS_OK(status)) {
960 goto done;
963 if (pnum_aliases) {
964 *pnum_aliases = num_aliases;
967 if (palias_rids) {
968 *palias_rids = talloc_move(mem_ctx, &alias_rids);
971 done:
972 if (b && is_valid_policy_hnd(&dom_pol)) {
973 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
976 TALLOC_FREE(tmp_ctx);
977 return status;
980 /* find the sequence number for a domain */
981 static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
982 uint32_t *pseq)
984 struct rpc_pipe_client *samr_pipe;
985 struct policy_handle dom_pol;
986 uint32_t seq = DOM_SEQUENCE_NONE;
987 TALLOC_CTX *tmp_ctx;
988 NTSTATUS status, result;
989 struct dcerpc_binding_handle *b = NULL;
991 DEBUG(3,("samr: sequence number\n"));
993 ZERO_STRUCT(dom_pol);
995 if (pseq) {
996 *pseq = DOM_SEQUENCE_NONE;
999 tmp_ctx = talloc_stackframe();
1000 if (tmp_ctx == NULL) {
1001 return NT_STATUS_NO_MEMORY;
1004 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 goto done;
1009 b = samr_pipe->binding_handle;
1011 status = rpc_sequence_number(tmp_ctx,
1012 samr_pipe,
1013 &dom_pol,
1014 domain->name,
1015 &seq);
1016 if (!NT_STATUS_IS_OK(status)) {
1017 goto done;
1020 if (pseq) {
1021 *pseq = seq;
1023 done:
1024 if (b && is_valid_policy_hnd(&dom_pol)) {
1025 dcerpc_samr_Close(b, tmp_ctx, &dom_pol, &result);
1028 TALLOC_FREE(tmp_ctx);
1029 return status;
1032 /* the rpc backend methods are exposed via this structure */
1033 struct winbindd_methods builtin_passdb_methods = {
1034 .consistent = false,
1036 .query_user_list = builtin_query_user_list,
1037 .enum_dom_groups = builtin_enum_dom_groups,
1038 .enum_local_groups = sam_enum_local_groups,
1039 .name_to_sid = sam_name_to_sid,
1040 .sid_to_name = sam_sid_to_name,
1041 .rids_to_names = sam_rids_to_names,
1042 .query_user = builtin_query_user,
1043 .lookup_usergroups = sam_lookup_usergroups,
1044 .lookup_useraliases = sam_lookup_useraliases,
1045 .lookup_groupmem = sam_lookup_groupmem,
1046 .sequence_number = sam_sequence_number,
1047 .lockout_policy = sam_lockout_policy,
1048 .password_policy = sam_password_policy,
1049 .trusted_domains = builtin_trusted_domains
1052 /* the rpc backend methods are exposed via this structure */
1053 struct winbindd_methods sam_passdb_methods = {
1054 .consistent = false,
1056 .query_user_list = sam_query_user_list,
1057 .enum_dom_groups = sam_enum_dom_groups,
1058 .enum_local_groups = sam_enum_local_groups,
1059 .name_to_sid = sam_name_to_sid,
1060 .sid_to_name = sam_sid_to_name,
1061 .rids_to_names = sam_rids_to_names,
1062 .query_user = sam_query_user,
1063 .lookup_usergroups = sam_lookup_usergroups,
1064 .lookup_useraliases = sam_lookup_useraliases,
1065 .lookup_groupmem = sam_lookup_groupmem,
1066 .sequence_number = sam_sequence_number,
1067 .lockout_policy = sam_lockout_policy,
1068 .password_policy = sam_password_policy,
1069 .trusted_domains = sam_trusted_domains