s3:smbd/open: try the primary sid (user) as group_sid if the token has just one sid
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_samr.c
blob9f45126d5c5465c5b99eadc4046a094ee206beb5
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 static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx,
43 struct rpc_pipe_client **samr_pipe)
45 struct rpc_pipe_client *cli = NULL;
46 struct auth_session_info *session_info = NULL;
47 NTSTATUS status;
49 if (session_info == NULL) {
50 status = make_session_info_system(mem_ctx, &session_info);
51 if (!NT_STATUS_IS_OK(status)) {
52 DEBUG(0, ("open_samr_pipe: Could not create auth_session_info: %s\n",
53 nt_errstr(status)));
54 return status;
58 /* create a samr connection */
59 status = rpc_pipe_open_internal(mem_ctx,
60 &ndr_table_samr.syntax_id,
61 session_info,
62 NULL,
63 winbind_messaging_context(),
64 &cli);
65 if (!NT_STATUS_IS_OK(status)) {
66 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
67 nt_errstr(status)));
68 return status;
71 if (samr_pipe) {
72 *samr_pipe = cli;
75 return NT_STATUS_OK;
78 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
79 struct winbindd_domain *domain,
80 struct rpc_pipe_client **samr_pipe,
81 struct policy_handle *samr_domain_hnd)
83 NTSTATUS status, result;
84 struct policy_handle samr_connect_hnd;
85 struct dcerpc_binding_handle *b;
87 status = open_internal_samr_pipe(mem_ctx, samr_pipe);
88 if (!NT_STATUS_IS_OK(status)) {
89 return status;
92 b = (*samr_pipe)->binding_handle;
94 status = dcerpc_samr_Connect2(b, mem_ctx,
95 (*samr_pipe)->desthost,
96 SEC_FLAG_MAXIMUM_ALLOWED,
97 &samr_connect_hnd,
98 &result);
99 if (!NT_STATUS_IS_OK(status)) {
100 return status;
102 if (!NT_STATUS_IS_OK(result)) {
103 return result;
106 status = dcerpc_samr_OpenDomain(b, mem_ctx,
107 &samr_connect_hnd,
108 SEC_FLAG_MAXIMUM_ALLOWED,
109 &domain->sid,
110 samr_domain_hnd,
111 &result);
112 if (!NT_STATUS_IS_OK(status)) {
113 return status;
116 return result;
119 static NTSTATUS open_internal_lsa_pipe(TALLOC_CTX *mem_ctx,
120 struct rpc_pipe_client **lsa_pipe)
122 struct rpc_pipe_client *cli = NULL;
123 struct auth_session_info *session_info = NULL;
124 NTSTATUS status;
126 if (session_info == NULL) {
127 status = make_session_info_system(mem_ctx, &session_info);
128 if (!NT_STATUS_IS_OK(status)) {
129 DEBUG(0, ("open_lsa_pipe: Could not create auth_session_info: %s\n",
130 nt_errstr(status)));
131 return status;
135 /* create a lsa connection */
136 status = rpc_pipe_open_internal(mem_ctx,
137 &ndr_table_lsarpc.syntax_id,
138 session_info,
139 NULL,
140 winbind_messaging_context(),
141 &cli);
142 if (!NT_STATUS_IS_OK(status)) {
143 DEBUG(0, ("open_lsa_pipe: Could not connect to lsa_pipe: %s\n",
144 nt_errstr(status)));
145 return status;
148 if (lsa_pipe) {
149 *lsa_pipe = cli;
152 return NT_STATUS_OK;
155 static NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
156 struct rpc_pipe_client **lsa_pipe,
157 struct policy_handle *lsa_hnd)
159 NTSTATUS status;
161 status = open_internal_lsa_pipe(mem_ctx, lsa_pipe);
162 if (!NT_STATUS_IS_OK(status)) {
163 return status;
166 status = rpccli_lsa_open_policy((*lsa_pipe),
167 mem_ctx,
168 true,
169 SEC_FLAG_MAXIMUM_ALLOWED,
170 lsa_hnd);
172 return status;
175 /*********************************************************************
176 SAM specific functions.
177 *********************************************************************/
179 /* List all domain groups */
180 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
181 TALLOC_CTX *mem_ctx,
182 uint32_t *pnum_info,
183 struct wb_acct_info **pinfo)
185 struct rpc_pipe_client *samr_pipe;
186 struct policy_handle dom_pol;
187 struct wb_acct_info *info = NULL;
188 uint32_t num_info = 0;
189 TALLOC_CTX *tmp_ctx;
190 NTSTATUS status, result;
191 struct dcerpc_binding_handle *b = NULL;
193 DEBUG(3,("sam_enum_dom_groups\n"));
195 ZERO_STRUCT(dom_pol);
197 if (pnum_info) {
198 *pnum_info = 0;
201 tmp_ctx = talloc_stackframe();
202 if (tmp_ctx == NULL) {
203 return NT_STATUS_NO_MEMORY;
206 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
207 if (!NT_STATUS_IS_OK(status)) {
208 goto error;
211 b = samr_pipe->binding_handle;
213 status = rpc_enum_dom_groups(tmp_ctx,
214 samr_pipe,
215 &dom_pol,
216 &num_info,
217 &info);
218 if (!NT_STATUS_IS_OK(status)) {
219 goto error;
222 if (pnum_info) {
223 *pnum_info = num_info;
226 if (pinfo) {
227 *pinfo = talloc_move(mem_ctx, &info);
230 error:
231 if (b && is_valid_policy_hnd(&dom_pol)) {
232 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
234 TALLOC_FREE(tmp_ctx);
235 return status;
238 /* Query display info for a domain */
239 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
240 TALLOC_CTX *mem_ctx,
241 uint32_t *pnum_info,
242 struct wbint_userinfo **pinfo)
244 struct rpc_pipe_client *samr_pipe = NULL;
245 struct policy_handle dom_pol;
246 struct wbint_userinfo *info = NULL;
247 uint32_t num_info = 0;
248 TALLOC_CTX *tmp_ctx;
249 NTSTATUS status, result;
250 struct dcerpc_binding_handle *b = NULL;
252 DEBUG(3,("samr_query_user_list\n"));
254 ZERO_STRUCT(dom_pol);
256 if (pnum_info) {
257 *pnum_info = 0;
260 tmp_ctx = talloc_stackframe();
261 if (tmp_ctx == NULL) {
262 return NT_STATUS_NO_MEMORY;
265 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
266 if (!NT_STATUS_IS_OK(status)) {
267 goto done;
270 b = samr_pipe->binding_handle;
272 status = rpc_query_user_list(tmp_ctx,
273 samr_pipe,
274 &dom_pol,
275 &domain->sid,
276 &num_info,
277 &info);
278 if (!NT_STATUS_IS_OK(status)) {
279 goto done;
282 if (pnum_info) {
283 *pnum_info = num_info;
286 if (pinfo) {
287 *pinfo = talloc_move(mem_ctx, &info);
290 done:
291 if (b && is_valid_policy_hnd(&dom_pol)) {
292 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
295 TALLOC_FREE(tmp_ctx);
296 return status;
299 /* Lookup user information from a rid or username. */
300 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
301 TALLOC_CTX *mem_ctx,
302 const struct dom_sid *user_sid,
303 struct wbint_userinfo *user_info)
305 struct rpc_pipe_client *samr_pipe;
306 struct policy_handle dom_pol;
307 TALLOC_CTX *tmp_ctx;
308 NTSTATUS status, result;
309 struct dcerpc_binding_handle *b = NULL;
311 DEBUG(3,("sam_query_user\n"));
313 ZERO_STRUCT(dom_pol);
315 /* Paranoia check */
316 if (!sid_check_is_in_our_sam(user_sid)) {
317 return NT_STATUS_NO_SUCH_USER;
320 user_info->homedir = NULL;
321 user_info->shell = NULL;
322 user_info->primary_gid = (gid_t) -1;
324 tmp_ctx = talloc_stackframe();
325 if (tmp_ctx == NULL) {
326 return NT_STATUS_NO_MEMORY;
329 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
330 if (!NT_STATUS_IS_OK(status)) {
331 goto done;
334 b = samr_pipe->binding_handle;
336 status = rpc_query_user(tmp_ctx,
337 samr_pipe,
338 &dom_pol,
339 &domain->sid,
340 user_sid,
341 user_info);
343 done:
344 if (b && is_valid_policy_hnd(&dom_pol)) {
345 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
348 TALLOC_FREE(tmp_ctx);
349 return status;
352 /* get a list of trusted domains - builtin domain */
353 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
354 TALLOC_CTX *mem_ctx,
355 struct netr_DomainTrustList *ptrust_list)
357 struct rpc_pipe_client *lsa_pipe;
358 struct policy_handle lsa_policy;
359 struct netr_DomainTrust *trusts = NULL;
360 uint32_t num_trusts = 0;
361 TALLOC_CTX *tmp_ctx;
362 NTSTATUS status, result;
363 struct dcerpc_binding_handle *b = NULL;
365 DEBUG(3,("samr: trusted domains\n"));
367 ZERO_STRUCT(lsa_policy);
369 if (ptrust_list) {
370 ZERO_STRUCTP(ptrust_list);
373 tmp_ctx = talloc_stackframe();
374 if (tmp_ctx == NULL) {
375 return NT_STATUS_NO_MEMORY;
378 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
379 if (!NT_STATUS_IS_OK(status)) {
380 goto done;
383 b = lsa_pipe->binding_handle;
385 status = rpc_trusted_domains(tmp_ctx,
386 lsa_pipe,
387 &lsa_policy,
388 &num_trusts,
389 &trusts);
390 if (!NT_STATUS_IS_OK(status)) {
391 goto done;
394 if (ptrust_list) {
395 ptrust_list->count = num_trusts;
396 ptrust_list->array = talloc_move(mem_ctx, &trusts);
399 done:
400 if (b && is_valid_policy_hnd(&lsa_policy)) {
401 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
404 TALLOC_FREE(tmp_ctx);
405 return status;
408 /* Lookup group membership given a rid. */
409 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
410 TALLOC_CTX *mem_ctx,
411 const struct dom_sid *group_sid,
412 enum lsa_SidType type,
413 uint32_t *pnum_names,
414 struct dom_sid **psid_mem,
415 char ***pnames,
416 uint32_t **pname_types)
418 struct rpc_pipe_client *samr_pipe;
419 struct policy_handle dom_pol;
421 uint32_t num_names = 0;
422 struct dom_sid *sid_mem = NULL;
423 char **names = NULL;
424 uint32_t *name_types = NULL;
426 TALLOC_CTX *tmp_ctx;
427 NTSTATUS status, result;
428 struct dcerpc_binding_handle *b = NULL;
430 DEBUG(3,("sam_lookup_groupmem\n"));
432 ZERO_STRUCT(dom_pol);
434 /* Paranoia check */
435 if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
436 /* There's no groups, only aliases in BUILTIN */
437 return NT_STATUS_NO_SUCH_GROUP;
440 if (pnum_names) {
441 *pnum_names = 0;
444 tmp_ctx = talloc_stackframe();
445 if (tmp_ctx == NULL) {
446 return NT_STATUS_NO_MEMORY;
449 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
450 if (!NT_STATUS_IS_OK(status)) {
451 goto done;
454 b = samr_pipe->binding_handle;
456 status = rpc_lookup_groupmem(tmp_ctx,
457 samr_pipe,
458 &dom_pol,
459 domain->name,
460 &domain->sid,
461 group_sid,
462 type,
463 &num_names,
464 &sid_mem,
465 &names,
466 &name_types);
468 if (pnum_names) {
469 *pnum_names = num_names;
472 if (pnames) {
473 *pnames = talloc_move(mem_ctx, &names);
476 if (pname_types) {
477 *pname_types = talloc_move(mem_ctx, &name_types);
480 if (psid_mem) {
481 *psid_mem = talloc_move(mem_ctx, &sid_mem);
484 done:
485 if (b && is_valid_policy_hnd(&dom_pol)) {
486 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
489 TALLOC_FREE(tmp_ctx);
490 return status;
493 /*********************************************************************
494 BUILTIN specific functions.
495 *********************************************************************/
497 /* List all domain groups */
498 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
499 TALLOC_CTX *mem_ctx,
500 uint32 *num_entries,
501 struct wb_acct_info **info)
503 /* BUILTIN doesn't have domain groups */
504 *num_entries = 0;
505 *info = NULL;
506 return NT_STATUS_OK;
509 /* Query display info for a domain */
510 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
511 TALLOC_CTX *mem_ctx,
512 uint32 *num_entries,
513 struct wbint_userinfo **info)
515 /* We don't have users */
516 *num_entries = 0;
517 *info = NULL;
518 return NT_STATUS_OK;
521 /* Lookup user information from a rid or username. */
522 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
523 TALLOC_CTX *mem_ctx,
524 const struct dom_sid *user_sid,
525 struct wbint_userinfo *user_info)
527 return NT_STATUS_NO_SUCH_USER;
530 /* get a list of trusted domains - builtin domain */
531 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
532 TALLOC_CTX *mem_ctx,
533 struct netr_DomainTrustList *trusts)
535 ZERO_STRUCTP(trusts);
536 return NT_STATUS_OK;
539 /*********************************************************************
540 COMMON functions.
541 *********************************************************************/
543 /* List all local groups (aliases) */
544 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
545 TALLOC_CTX *mem_ctx,
546 uint32_t *pnum_info,
547 struct wb_acct_info **pinfo)
549 struct rpc_pipe_client *samr_pipe;
550 struct policy_handle dom_pol;
551 struct wb_acct_info *info = NULL;
552 uint32_t num_info = 0;
553 TALLOC_CTX *tmp_ctx;
554 NTSTATUS status, result;
555 struct dcerpc_binding_handle *b = NULL;
557 DEBUG(3,("samr: enum local groups\n"));
559 ZERO_STRUCT(dom_pol);
561 if (pnum_info) {
562 *pnum_info = 0;
565 tmp_ctx = talloc_stackframe();
566 if (tmp_ctx == NULL) {
567 return NT_STATUS_NO_MEMORY;
570 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
571 if (!NT_STATUS_IS_OK(status)) {
572 goto done;
575 b = samr_pipe->binding_handle;
577 status = rpc_enum_local_groups(mem_ctx,
578 samr_pipe,
579 &dom_pol,
580 &num_info,
581 &info);
582 if (!NT_STATUS_IS_OK(status)) {
583 goto done;
586 if (pnum_info) {
587 *pnum_info = num_info;
590 if (pinfo) {
591 *pinfo = talloc_move(mem_ctx, &info);
594 done:
595 if (b && is_valid_policy_hnd(&dom_pol)) {
596 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
599 TALLOC_FREE(tmp_ctx);
600 return status;
603 /* convert a single name to a sid in a domain */
604 static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
605 TALLOC_CTX *mem_ctx,
606 const char *domain_name,
607 const char *name,
608 uint32_t flags,
609 struct dom_sid *psid,
610 enum lsa_SidType *ptype)
612 struct rpc_pipe_client *lsa_pipe;
613 struct policy_handle lsa_policy;
614 struct dom_sid sid;
615 enum lsa_SidType type;
616 TALLOC_CTX *tmp_ctx;
617 NTSTATUS status, result;
618 struct dcerpc_binding_handle *b = NULL;
620 DEBUG(3,("sam_name_to_sid\n"));
622 ZERO_STRUCT(lsa_policy);
624 tmp_ctx = talloc_stackframe();
625 if (tmp_ctx == NULL) {
626 return NT_STATUS_NO_MEMORY;
629 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
630 if (!NT_STATUS_IS_OK(status)) {
631 goto done;
634 b = lsa_pipe->binding_handle;
636 status = rpc_name_to_sid(tmp_ctx,
637 lsa_pipe,
638 &lsa_policy,
639 domain_name,
640 name,
641 flags,
642 &sid,
643 &type);
644 if (!NT_STATUS_IS_OK(status)) {
645 goto done;
648 if (psid) {
649 sid_copy(psid, &sid);
651 if (ptype) {
652 *ptype = type;
655 done:
656 if (b && is_valid_policy_hnd(&lsa_policy)) {
657 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
660 TALLOC_FREE(tmp_ctx);
661 return status;
664 /* convert a domain SID to a user or group name */
665 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
666 TALLOC_CTX *mem_ctx,
667 const struct dom_sid *sid,
668 char **pdomain_name,
669 char **pname,
670 enum lsa_SidType *ptype)
672 struct rpc_pipe_client *lsa_pipe;
673 struct policy_handle lsa_policy;
674 char *domain_name = NULL;
675 char *name = NULL;
676 enum lsa_SidType type;
677 TALLOC_CTX *tmp_ctx;
678 NTSTATUS status, result;
679 struct dcerpc_binding_handle *b = NULL;
681 DEBUG(3,("sam_sid_to_name\n"));
683 ZERO_STRUCT(lsa_policy);
685 /* Paranoia check */
686 if (!sid_check_is_in_builtin(sid) &&
687 !sid_check_is_in_our_sam(sid) &&
688 !sid_check_is_in_unix_users(sid) &&
689 !sid_check_is_unix_users(sid) &&
690 !sid_check_is_in_unix_groups(sid) &&
691 !sid_check_is_unix_groups(sid) &&
692 !sid_check_is_in_wellknown_domain(sid)) {
693 DEBUG(0, ("sam_sid_to_name: possible deadlock - trying to "
694 "lookup SID %s\n", sid_string_dbg(sid)));
695 return NT_STATUS_NONE_MAPPED;
698 tmp_ctx = talloc_stackframe();
699 if (tmp_ctx == NULL) {
700 return NT_STATUS_NO_MEMORY;
703 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
704 if (!NT_STATUS_IS_OK(status)) {
705 goto done;
708 b = lsa_pipe->binding_handle;
710 status = rpc_sid_to_name(tmp_ctx,
711 lsa_pipe,
712 &lsa_policy,
713 domain,
714 sid,
715 &domain_name,
716 &name,
717 &type);
719 if (ptype) {
720 *ptype = type;
723 if (pname) {
724 *pname = talloc_move(mem_ctx, &name);
727 if (pdomain_name) {
728 *pdomain_name = talloc_move(mem_ctx, &domain_name);
731 done:
732 if (b && is_valid_policy_hnd(&lsa_policy)) {
733 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
736 TALLOC_FREE(tmp_ctx);
737 return status;
740 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
741 TALLOC_CTX *mem_ctx,
742 const struct dom_sid *domain_sid,
743 uint32 *rids,
744 size_t num_rids,
745 char **pdomain_name,
746 char ***pnames,
747 enum lsa_SidType **ptypes)
749 struct rpc_pipe_client *lsa_pipe;
750 struct policy_handle lsa_policy;
751 enum lsa_SidType *types = NULL;
752 char *domain_name = NULL;
753 char **names = NULL;
754 TALLOC_CTX *tmp_ctx;
755 NTSTATUS status, result;
756 struct dcerpc_binding_handle *b = NULL;
758 DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
760 ZERO_STRUCT(lsa_policy);
762 /* Paranoia check */
763 if (!sid_check_is_builtin(domain_sid) &&
764 !sid_check_is_our_sam(domain_sid) &&
765 !sid_check_is_unix_users(domain_sid) &&
766 !sid_check_is_unix_groups(domain_sid) &&
767 !sid_check_is_in_wellknown_domain(domain_sid)) {
768 DEBUG(0, ("sam_rids_to_names: possible deadlock - trying to "
769 "lookup SID %s\n", sid_string_dbg(domain_sid)));
770 return NT_STATUS_NONE_MAPPED;
773 tmp_ctx = talloc_stackframe();
774 if (tmp_ctx == NULL) {
775 return NT_STATUS_NO_MEMORY;
778 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
779 if (!NT_STATUS_IS_OK(status)) {
780 goto done;
783 b = lsa_pipe->binding_handle;
785 status = rpc_rids_to_names(tmp_ctx,
786 lsa_pipe,
787 &lsa_policy,
788 domain,
789 domain_sid,
790 rids,
791 num_rids,
792 &domain_name,
793 &names,
794 &types);
795 if (!NT_STATUS_IS_OK(status)) {
796 goto done;
799 if (pdomain_name) {
800 *pdomain_name = talloc_move(mem_ctx, &domain_name);
803 if (ptypes) {
804 *ptypes = talloc_move(mem_ctx, &types);
807 if (pnames) {
808 *pnames = talloc_move(mem_ctx, &names);
811 done:
812 if (b && is_valid_policy_hnd(&lsa_policy)) {
813 dcerpc_lsa_Close(b, mem_ctx, &lsa_policy, &result);
816 TALLOC_FREE(tmp_ctx);
817 return status;
820 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
821 TALLOC_CTX *mem_ctx,
822 struct samr_DomInfo12 *lockout_policy)
824 struct rpc_pipe_client *samr_pipe;
825 struct policy_handle dom_pol;
826 union samr_DomainInfo *info = NULL;
827 TALLOC_CTX *tmp_ctx;
828 NTSTATUS status, result;
829 struct dcerpc_binding_handle *b = NULL;
831 DEBUG(3,("sam_lockout_policy\n"));
833 ZERO_STRUCT(dom_pol);
835 tmp_ctx = talloc_stackframe();
836 if (tmp_ctx == NULL) {
837 return NT_STATUS_NO_MEMORY;
840 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
841 if (!NT_STATUS_IS_OK(status)) {
842 goto error;
845 b = samr_pipe->binding_handle;
847 status = dcerpc_samr_QueryDomainInfo(b,
848 mem_ctx,
849 &dom_pol,
850 DomainLockoutInformation,
851 &info,
852 &result);
853 if (!NT_STATUS_IS_OK(status)) {
854 goto error;
856 if (!NT_STATUS_IS_OK(result)) {
857 status = result;
858 goto error;
861 *lockout_policy = info->info12;
863 error:
864 if (b && is_valid_policy_hnd(&dom_pol)) {
865 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
868 TALLOC_FREE(tmp_ctx);
869 return status;
872 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
873 TALLOC_CTX *mem_ctx,
874 struct samr_DomInfo1 *passwd_policy)
876 struct rpc_pipe_client *samr_pipe;
877 struct policy_handle dom_pol;
878 union samr_DomainInfo *info = NULL;
879 TALLOC_CTX *tmp_ctx;
880 NTSTATUS status, result;
881 struct dcerpc_binding_handle *b = NULL;
883 DEBUG(3,("sam_password_policy\n"));
885 ZERO_STRUCT(dom_pol);
887 tmp_ctx = talloc_stackframe();
888 if (tmp_ctx == NULL) {
889 return NT_STATUS_NO_MEMORY;
892 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
893 if (!NT_STATUS_IS_OK(status)) {
894 goto error;
897 b = samr_pipe->binding_handle;
899 status = dcerpc_samr_QueryDomainInfo(b,
900 mem_ctx,
901 &dom_pol,
902 DomainPasswordInformation,
903 &info,
904 &result);
905 if (!NT_STATUS_IS_OK(status)) {
906 goto error;
908 if (!NT_STATUS_IS_OK(result)) {
909 status = result;
910 goto error;
913 *passwd_policy = info->info1;
915 error:
916 if (b && is_valid_policy_hnd(&dom_pol)) {
917 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
920 TALLOC_FREE(tmp_ctx);
921 return status;
924 /* Lookup groups a user is a member of. */
925 static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
926 TALLOC_CTX *mem_ctx,
927 const struct dom_sid *user_sid,
928 uint32_t *pnum_groups,
929 struct dom_sid **puser_grpsids)
931 struct rpc_pipe_client *samr_pipe;
932 struct policy_handle dom_pol;
933 struct dom_sid *user_grpsids = NULL;
934 uint32_t num_groups = 0;
935 TALLOC_CTX *tmp_ctx;
936 NTSTATUS status, result;
937 struct dcerpc_binding_handle *b = NULL;
939 DEBUG(3,("sam_lookup_usergroups\n"));
941 ZERO_STRUCT(dom_pol);
943 if (pnum_groups) {
944 *pnum_groups = 0;
947 tmp_ctx = talloc_stackframe();
948 if (tmp_ctx == NULL) {
949 return NT_STATUS_NO_MEMORY;
952 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
953 if (!NT_STATUS_IS_OK(status)) {
954 goto done;
957 b = samr_pipe->binding_handle;
959 status = rpc_lookup_usergroups(tmp_ctx,
960 samr_pipe,
961 &dom_pol,
962 &domain->sid,
963 user_sid,
964 &num_groups,
965 &user_grpsids);
966 if (!NT_STATUS_IS_OK(status)) {
967 goto done;
970 if (pnum_groups) {
971 *pnum_groups = num_groups;
974 if (puser_grpsids) {
975 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
978 done:
979 if (b && is_valid_policy_hnd(&dom_pol)) {
980 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
983 TALLOC_FREE(tmp_ctx);
984 return status;
987 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
988 TALLOC_CTX *mem_ctx,
989 uint32_t num_sids,
990 const struct dom_sid *sids,
991 uint32_t *pnum_aliases,
992 uint32_t **palias_rids)
994 struct rpc_pipe_client *samr_pipe;
995 struct policy_handle dom_pol;
996 uint32_t num_aliases = 0;
997 uint32_t *alias_rids = NULL;
998 TALLOC_CTX *tmp_ctx;
999 NTSTATUS status, result;
1000 struct dcerpc_binding_handle *b = NULL;
1002 DEBUG(3,("sam_lookup_useraliases\n"));
1004 ZERO_STRUCT(dom_pol);
1006 if (pnum_aliases) {
1007 *pnum_aliases = 0;
1010 tmp_ctx = talloc_stackframe();
1011 if (tmp_ctx == NULL) {
1012 return NT_STATUS_NO_MEMORY;
1015 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
1016 if (!NT_STATUS_IS_OK(status)) {
1017 goto done;
1020 b = samr_pipe->binding_handle;
1022 status = rpc_lookup_useraliases(tmp_ctx,
1023 samr_pipe,
1024 &dom_pol,
1025 num_sids,
1026 sids,
1027 &num_aliases,
1028 &alias_rids);
1029 if (!NT_STATUS_IS_OK(status)) {
1030 goto done;
1033 if (pnum_aliases) {
1034 *pnum_aliases = num_aliases;
1037 if (palias_rids) {
1038 *palias_rids = talloc_move(mem_ctx, &alias_rids);
1041 done:
1042 if (b && is_valid_policy_hnd(&dom_pol)) {
1043 dcerpc_samr_Close(b, mem_ctx, &dom_pol, &result);
1046 TALLOC_FREE(tmp_ctx);
1047 return status;
1050 /* find the sequence number for a domain */
1051 static NTSTATUS sam_sequence_number(struct winbindd_domain *domain,
1052 uint32_t *pseq)
1054 struct rpc_pipe_client *samr_pipe;
1055 struct policy_handle dom_pol;
1056 uint32_t seq;
1057 TALLOC_CTX *tmp_ctx;
1058 NTSTATUS status, result;
1059 struct dcerpc_binding_handle *b = NULL;
1061 DEBUG(3,("samr: sequence number\n"));
1063 ZERO_STRUCT(dom_pol);
1065 if (pseq) {
1066 *pseq = DOM_SEQUENCE_NONE;
1069 tmp_ctx = talloc_stackframe();
1070 if (tmp_ctx == NULL) {
1071 return NT_STATUS_NO_MEMORY;
1074 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 goto done;
1079 b = samr_pipe->binding_handle;
1081 status = rpc_sequence_number(tmp_ctx,
1082 samr_pipe,
1083 &dom_pol,
1084 domain->name,
1085 &seq);
1086 if (!NT_STATUS_IS_OK(status)) {
1087 goto done;
1090 if (pseq) {
1091 *pseq = seq;
1093 done:
1094 if (b && is_valid_policy_hnd(&dom_pol)) {
1095 dcerpc_samr_Close(b, tmp_ctx, &dom_pol, &result);
1098 TALLOC_FREE(tmp_ctx);
1099 return status;
1102 /* the rpc backend methods are exposed via this structure */
1103 struct winbindd_methods builtin_passdb_methods = {
1104 .consistent = false,
1106 .query_user_list = builtin_query_user_list,
1107 .enum_dom_groups = builtin_enum_dom_groups,
1108 .enum_local_groups = sam_enum_local_groups,
1109 .name_to_sid = sam_name_to_sid,
1110 .sid_to_name = sam_sid_to_name,
1111 .rids_to_names = sam_rids_to_names,
1112 .query_user = builtin_query_user,
1113 .lookup_usergroups = sam_lookup_usergroups,
1114 .lookup_useraliases = sam_lookup_useraliases,
1115 .lookup_groupmem = sam_lookup_groupmem,
1116 .sequence_number = sam_sequence_number,
1117 .lockout_policy = sam_lockout_policy,
1118 .password_policy = sam_password_policy,
1119 .trusted_domains = builtin_trusted_domains
1122 /* the rpc backend methods are exposed via this structure */
1123 struct winbindd_methods sam_passdb_methods = {
1124 .consistent = false,
1126 .query_user_list = sam_query_user_list,
1127 .enum_dom_groups = sam_enum_dom_groups,
1128 .enum_local_groups = sam_enum_local_groups,
1129 .name_to_sid = sam_name_to_sid,
1130 .sid_to_name = sam_sid_to_name,
1131 .rids_to_names = sam_rids_to_names,
1132 .query_user = sam_query_user,
1133 .lookup_usergroups = sam_lookup_usergroups,
1134 .lookup_useraliases = sam_lookup_useraliases,
1135 .lookup_groupmem = sam_lookup_groupmem,
1136 .sequence_number = sam_sequence_number,
1137 .lockout_policy = sam_lockout_policy,
1138 .password_policy = sam_password_policy,
1139 .trusted_domains = sam_trusted_domains