smbd: Fix crossing automounter mount points
[Samba.git] / source3 / winbindd / winbindd_samr.c
blob65e9932c25ef3b37d9bf526a962425047aabd2e5
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 "lib/util_unixsids.h"
30 #include "rpc_client/rpc_client.h"
31 #include "rpc_client/cli_pipe.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "rpc_client/cli_samr.h"
34 #include "../librpc/gen_ndr/ndr_lsa_c.h"
35 #include "rpc_client/cli_lsarpc.h"
36 #include "rpc_server/rpc_ncacn_np.h"
37 #include "../libcli/security/security.h"
38 #include "passdb/machine_sid.h"
39 #include "auth.h"
40 #include "source3/lib/global_contexts.h"
42 #undef DBGC_CLASS
43 #define DBGC_CLASS DBGC_WINBIND
46 * The other end of this won't go away easily, so we can trust it
48 * It is either a long-lived process with the same lifetime as
49 * winbindd or a part of this process
51 struct winbind_internal_pipes {
52 struct tevent_timer *shutdown_timer;
53 struct rpc_pipe_client *samr_pipe;
54 struct policy_handle samr_domain_hnd;
55 struct rpc_pipe_client *lsa_pipe;
56 struct policy_handle lsa_hnd;
60 NTSTATUS open_internal_samr_conn(TALLOC_CTX *mem_ctx,
61 struct winbindd_domain *domain,
62 struct rpc_pipe_client **samr_pipe,
63 struct policy_handle *samr_domain_hnd)
65 NTSTATUS status, result;
66 struct policy_handle samr_connect_hnd;
67 struct dcerpc_binding_handle *b;
69 status = wb_open_internal_pipe(mem_ctx, &ndr_table_samr, samr_pipe);
70 if (!NT_STATUS_IS_OK(status)) {
71 DBG_ERR("Could not connect to %s pipe: %s\n",
72 ndr_table_samr.name, nt_errstr(status));
73 return status;
76 b = (*samr_pipe)->binding_handle;
78 status = dcerpc_samr_Connect2(b, mem_ctx,
79 (*samr_pipe)->desthost,
80 SEC_FLAG_MAXIMUM_ALLOWED,
81 &samr_connect_hnd,
82 &result);
83 if (!NT_STATUS_IS_OK(status)) {
84 return status;
86 if (!NT_STATUS_IS_OK(result)) {
87 return result;
90 status = dcerpc_samr_OpenDomain(b, mem_ctx,
91 &samr_connect_hnd,
92 SEC_FLAG_MAXIMUM_ALLOWED,
93 &domain->sid,
94 samr_domain_hnd,
95 &result);
96 if (!NT_STATUS_IS_OK(status)) {
97 return status;
100 return result;
103 NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
104 struct rpc_pipe_client **lsa_pipe,
105 struct policy_handle *lsa_hnd)
107 NTSTATUS status;
109 status = wb_open_internal_pipe(mem_ctx, &ndr_table_lsarpc, lsa_pipe);
110 if (!NT_STATUS_IS_OK(status)) {
111 DBG_ERR("Could not connect to %s pipe: %s\n",
112 ndr_table_lsarpc.name, nt_errstr(status));
113 return status;
116 status = rpccli_lsa_open_policy((*lsa_pipe),
117 mem_ctx,
118 true,
119 SEC_FLAG_MAXIMUM_ALLOWED,
120 lsa_hnd);
122 return status;
125 static void cached_internal_pipe_close(
126 struct tevent_context *ev,
127 struct tevent_timer *te,
128 struct timeval current_time,
129 void *private_data)
131 struct winbindd_domain *domain = talloc_get_type_abort(
132 private_data, struct winbindd_domain);
134 * Freeing samr_pipes closes the cached pipes.
136 * We can do a hard close because at the time of this commit
137 * we only use synchronous calls to external pipes. So we can't
138 * have any outstanding requests. Also, we don't set
139 * dcerpc_binding_handle_set_sync_ev in winbind, so we don't
140 * get nested event loops. Once we start to get async in
141 * winbind children, we need to check for outstanding calls
143 TALLOC_FREE(domain->backend_data.samr_pipes);
146 static NTSTATUS open_cached_internal_pipe_conn(
147 struct winbindd_domain *domain,
148 struct rpc_pipe_client **samr_pipe,
149 struct policy_handle *samr_domain_hnd,
150 struct rpc_pipe_client **lsa_pipe,
151 struct policy_handle *lsa_hnd)
153 struct winbind_internal_pipes *internal_pipes =
154 domain->backend_data.samr_pipes;
156 if (internal_pipes == NULL) {
157 TALLOC_CTX *frame = talloc_stackframe();
158 NTSTATUS status;
160 internal_pipes = talloc_zero(frame,
161 struct winbind_internal_pipes);
163 status = open_internal_samr_conn(
164 internal_pipes,
165 domain,
166 &internal_pipes->samr_pipe,
167 &internal_pipes->samr_domain_hnd);
168 if (!NT_STATUS_IS_OK(status)) {
169 TALLOC_FREE(frame);
170 return status;
173 status = open_internal_lsa_conn(internal_pipes,
174 &internal_pipes->lsa_pipe,
175 &internal_pipes->lsa_hnd);
177 if (!NT_STATUS_IS_OK(status)) {
178 TALLOC_FREE(frame);
179 return status;
182 internal_pipes->shutdown_timer = tevent_add_timer(
183 global_event_context(),
184 internal_pipes,
185 timeval_current_ofs(5, 0),
186 cached_internal_pipe_close,
187 domain);
188 if (internal_pipes->shutdown_timer == NULL) {
189 TALLOC_FREE(frame);
190 return NT_STATUS_NO_MEMORY;
193 domain->backend_data.samr_pipes =
194 talloc_steal(domain, internal_pipes);
196 TALLOC_FREE(frame);
199 if (samr_domain_hnd) {
200 *samr_domain_hnd = internal_pipes->samr_domain_hnd;
203 if (samr_pipe) {
204 *samr_pipe = internal_pipes->samr_pipe;
207 if (lsa_hnd) {
208 *lsa_hnd = internal_pipes->lsa_hnd;
211 if (lsa_pipe) {
212 *lsa_pipe = internal_pipes->lsa_pipe;
215 tevent_update_timer(
216 internal_pipes->shutdown_timer,
217 timeval_current_ofs(5, 0));
219 return NT_STATUS_OK;
222 static bool reset_connection_on_error(struct winbindd_domain *domain,
223 struct rpc_pipe_client *p,
224 NTSTATUS status)
226 struct dcerpc_binding_handle *b = p->binding_handle;
228 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
229 NT_STATUS_EQUAL(status, NT_STATUS_IO_DEVICE_ERROR))
231 TALLOC_FREE(domain->backend_data.samr_pipes);
232 return true;
235 if (!dcerpc_binding_handle_is_connected(b)) {
236 TALLOC_FREE(domain->backend_data.samr_pipes);
237 return true;
240 return false;
243 /*********************************************************************
244 SAM specific functions.
245 *********************************************************************/
247 /* List all domain groups */
248 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
249 TALLOC_CTX *mem_ctx,
250 uint32_t *pnum_info,
251 struct wb_acct_info **pinfo)
253 struct rpc_pipe_client *samr_pipe;
254 struct policy_handle dom_pol = { 0 };
255 struct wb_acct_info *info = NULL;
256 uint32_t num_info = 0;
257 TALLOC_CTX *tmp_ctx = talloc_stackframe();
258 NTSTATUS status;
259 bool retry = false;
261 DEBUG(3,("sam_enum_dom_groups\n"));
263 if (pnum_info) {
264 *pnum_info = 0;
267 again:
268 status = open_cached_internal_pipe_conn(domain,
269 &samr_pipe,
270 &dom_pol,
271 NULL,
272 NULL);
273 if (!NT_STATUS_IS_OK(status)) {
274 TALLOC_FREE(tmp_ctx);
275 return status;
278 status = rpc_enum_dom_groups(tmp_ctx,
279 samr_pipe,
280 &dom_pol,
281 &num_info,
282 &info);
284 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
285 retry = true;
286 goto again;
289 if (!NT_STATUS_IS_OK(status)) {
290 TALLOC_FREE(tmp_ctx);
291 return status;
294 if (pnum_info) {
295 *pnum_info = num_info;
298 if (pinfo) {
299 *pinfo = talloc_move(mem_ctx, &info);
302 TALLOC_FREE(tmp_ctx);
303 return status;
306 /* Query display info for a domain */
307 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
308 TALLOC_CTX *mem_ctx,
309 uint32_t **prids)
311 struct rpc_pipe_client *samr_pipe = NULL;
312 struct policy_handle dom_pol = { 0 };
313 uint32_t *rids = NULL;
314 TALLOC_CTX *tmp_ctx = talloc_stackframe();
315 NTSTATUS status;
316 bool retry = false;
318 DEBUG(3,("samr_query_user_list\n"));
320 again:
321 status = open_cached_internal_pipe_conn(domain,
322 &samr_pipe,
323 &dom_pol,
324 NULL,
325 NULL);
326 if (!NT_STATUS_IS_OK(status)) {
327 goto done;
330 status = rpc_query_user_list(tmp_ctx,
331 samr_pipe,
332 &dom_pol,
333 &domain->sid,
334 &rids);
335 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
336 retry = true;
337 goto again;
340 if (!NT_STATUS_IS_OK(status)) {
341 goto done;
344 if (prids != NULL) {
345 *prids = talloc_move(mem_ctx, &rids);
348 done:
349 TALLOC_FREE(rids);
350 TALLOC_FREE(tmp_ctx);
351 return status;
354 /* get a list of trusted domains - builtin domain */
355 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
356 TALLOC_CTX *mem_ctx,
357 struct netr_DomainTrustList *ptrust_list)
359 struct rpc_pipe_client *lsa_pipe;
360 struct policy_handle lsa_policy = { 0 };
361 struct netr_DomainTrust *trusts = NULL;
362 uint32_t num_trusts = 0;
363 TALLOC_CTX *tmp_ctx = talloc_stackframe();
364 NTSTATUS status;
365 bool retry = false;
367 DEBUG(3,("samr: trusted domains\n"));
369 if (ptrust_list) {
370 ZERO_STRUCTP(ptrust_list);
373 again:
374 status = open_cached_internal_pipe_conn(domain,
375 NULL,
376 NULL,
377 &lsa_pipe,
378 &lsa_policy);
379 if (!NT_STATUS_IS_OK(status)) {
380 goto done;
383 status = rpc_trusted_domains(tmp_ctx,
384 lsa_pipe,
385 &lsa_policy,
386 &num_trusts,
387 &trusts);
389 if (!retry && reset_connection_on_error(domain, lsa_pipe, status)) {
390 retry = true;
391 goto again;
394 if (!NT_STATUS_IS_OK(status)) {
395 goto done;
398 if (ptrust_list) {
399 ptrust_list->count = num_trusts;
400 ptrust_list->array = talloc_move(mem_ctx, &trusts);
403 done:
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 = { 0 };
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 = talloc_stackframe();
427 NTSTATUS status;
428 bool retry = false;
430 DEBUG(3,("sam_lookup_groupmem\n"));
432 /* Paranoia check */
433 if (sid_check_is_in_builtin(group_sid) && (type != SID_NAME_ALIAS)) {
434 /* There's no groups, only aliases in BUILTIN */
435 status = NT_STATUS_NO_SUCH_GROUP;
436 goto done;
439 if (pnum_names) {
440 *pnum_names = 0;
443 again:
444 status = open_cached_internal_pipe_conn(domain,
445 &samr_pipe,
446 &dom_pol,
447 NULL,
448 NULL);
449 if (!NT_STATUS_IS_OK(status)) {
450 goto done;
453 status = rpc_lookup_groupmem(tmp_ctx,
454 samr_pipe,
455 &dom_pol,
456 domain->name,
457 &domain->sid,
458 group_sid,
459 type,
460 &num_names,
461 &sid_mem,
462 &names,
463 &name_types);
465 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
466 retry = true;
467 goto again;
470 if (pnum_names) {
471 *pnum_names = num_names;
474 if (pnames) {
475 *pnames = talloc_move(mem_ctx, &names);
478 if (pname_types) {
479 *pname_types = talloc_move(mem_ctx, &name_types);
482 if (psid_mem) {
483 *psid_mem = talloc_move(mem_ctx, &sid_mem);
486 done:
487 TALLOC_FREE(tmp_ctx);
488 return status;
491 /* Lookup alias membership */
492 static NTSTATUS sam_lookup_aliasmem(struct winbindd_domain *domain,
493 TALLOC_CTX *mem_ctx,
494 const struct dom_sid *group_sid,
495 enum lsa_SidType type,
496 uint32_t *pnum_sids,
497 struct dom_sid **psid_mem)
499 struct rpc_pipe_client *samr_pipe;
500 struct policy_handle dom_pol = {0};
502 uint32_t num_sids = 0;
503 struct dom_sid *sid_mem = NULL;
505 TALLOC_CTX *tmp_ctx = talloc_stackframe();
506 NTSTATUS status;
507 bool retry = false;
509 DBG_INFO("sam_lookup_aliasmem\n");
511 /* Paranoia check */
512 if (type != SID_NAME_ALIAS) {
513 status = NT_STATUS_NO_SUCH_ALIAS;
514 goto done;
517 if (pnum_sids) {
518 *pnum_sids = 0;
521 again:
522 status = open_cached_internal_pipe_conn(domain,
523 &samr_pipe,
524 &dom_pol,
525 NULL,
526 NULL);
527 if (!NT_STATUS_IS_OK(status)) {
528 goto done;
531 status = rpc_lookup_aliasmem(tmp_ctx,
532 samr_pipe,
533 &dom_pol,
534 &domain->sid,
535 group_sid,
536 type,
537 &num_sids,
538 &sid_mem);
540 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
541 retry = true;
542 goto again;
545 if (pnum_sids) {
546 *pnum_sids = num_sids;
549 if (psid_mem) {
550 *psid_mem = talloc_move(mem_ctx, &sid_mem);
553 done:
554 TALLOC_FREE(tmp_ctx);
555 return status;
558 /*********************************************************************
559 BUILTIN specific functions.
560 *********************************************************************/
562 /* List all domain groups */
563 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
564 TALLOC_CTX *mem_ctx,
565 uint32_t *num_entries,
566 struct wb_acct_info **info)
568 /* BUILTIN doesn't have domain groups */
569 *num_entries = 0;
570 *info = NULL;
571 return NT_STATUS_OK;
574 /* Query display info for a domain */
575 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
576 TALLOC_CTX *mem_ctx,
577 uint32_t **rids)
579 /* We don't have users */
580 *rids = NULL;
581 return NT_STATUS_OK;
584 /* get a list of trusted domains - builtin domain */
585 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
586 TALLOC_CTX *mem_ctx,
587 struct netr_DomainTrustList *trusts)
589 ZERO_STRUCTP(trusts);
590 return NT_STATUS_OK;
593 /*********************************************************************
594 COMMON functions.
595 *********************************************************************/
597 /* List all local groups (aliases) */
598 static NTSTATUS sam_enum_local_groups(struct winbindd_domain *domain,
599 TALLOC_CTX *mem_ctx,
600 uint32_t *pnum_info,
601 struct wb_acct_info **pinfo)
603 struct rpc_pipe_client *samr_pipe;
604 struct policy_handle dom_pol = { 0 };
605 struct wb_acct_info *info = NULL;
606 uint32_t num_info = 0;
607 TALLOC_CTX *tmp_ctx = talloc_stackframe();
608 NTSTATUS status;
609 bool retry = false;
611 DEBUG(3,("samr: enum local groups\n"));
613 if (pnum_info) {
614 *pnum_info = 0;
617 again:
618 status = open_cached_internal_pipe_conn(domain,
619 &samr_pipe,
620 &dom_pol,
621 NULL,
622 NULL);
623 if (!NT_STATUS_IS_OK(status)) {
624 goto done;
627 status = rpc_enum_local_groups(mem_ctx,
628 samr_pipe,
629 &dom_pol,
630 &num_info,
632 &info);
633 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
634 retry = true;
635 goto again;
638 if (!NT_STATUS_IS_OK(status)) {
639 goto done;
642 if (pnum_info) {
643 *pnum_info = num_info;
646 if (pinfo) {
647 *pinfo = talloc_move(mem_ctx, &info);
650 done:
651 TALLOC_FREE(tmp_ctx);
652 return status;
655 /* convert a single name to a sid in a domain */
656 static NTSTATUS sam_name_to_sid(struct winbindd_domain *domain,
657 TALLOC_CTX *mem_ctx,
658 const char *domain_name,
659 const char *name,
660 uint32_t flags,
661 const char **pdom_name,
662 struct dom_sid *psid,
663 enum lsa_SidType *ptype)
665 struct rpc_pipe_client *samr_pipe = NULL;
666 struct dcerpc_binding_handle *h = NULL;
667 struct policy_handle dom_pol = { .handle_type = 0, };
668 struct dom_sid sid;
669 const char *dom_name = domain_name;
670 struct lsa_String lsa_name = { .string = name };
671 struct samr_Ids rids = { .count = 0 };
672 struct samr_Ids types = { .count = 0 };
673 enum lsa_SidType type;
674 TALLOC_CTX *tmp_ctx = talloc_stackframe();
675 NTSTATUS status = NT_STATUS_NONE_MAPPED;
676 NTSTATUS result;
677 bool retry = false;
678 bool ok;
680 DBG_NOTICE("%s\\%s\n", domain_name, name);
682 if (strequal(domain_name, unix_users_domain_name())) {
683 struct passwd *pwd = NULL;
685 if (name[0] == '\0') {
686 sid_copy(&sid, &global_sid_Unix_Users);
687 type = SID_NAME_DOMAIN;
688 goto done;
691 pwd = Get_Pwnam_alloc(tmp_ctx, name);
692 if (pwd == NULL) {
693 goto fail;
695 ok = sid_compose(&sid, &global_sid_Unix_Users, pwd->pw_uid);
696 if (!ok) {
697 status = NT_STATUS_INTERNAL_ERROR;
698 goto fail;
700 type = SID_NAME_USER;
701 goto done;
704 if (strequal(domain_name, unix_groups_domain_name())) {
705 struct group *grp = NULL;
707 if (name[0] == '\0') {
708 sid_copy(&sid, &global_sid_Unix_Groups);
709 type = SID_NAME_DOMAIN;
710 goto done;
713 grp = getgrnam(name);
714 if (grp == NULL) {
715 goto fail;
717 ok = sid_compose(&sid, &global_sid_Unix_Groups, grp->gr_gid);
718 if (!ok) {
719 status = NT_STATUS_INTERNAL_ERROR;
720 goto fail;
722 type = SID_NAME_DOM_GRP;
723 goto done;
726 if (name[0] == '\0') {
727 sid_copy(&sid, &domain->sid);
728 type = SID_NAME_DOMAIN;
729 goto done;
732 ok = lookup_wellknown_name(tmp_ctx, name, &sid, &dom_name);
733 if (ok) {
734 type = SID_NAME_WKN_GRP;
735 goto done;
739 char *normalized = NULL;
740 NTSTATUS nstatus = normalize_name_unmap(
741 tmp_ctx, name, &normalized);
742 if (NT_STATUS_IS_OK(nstatus) ||
743 NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
744 lsa_name.string = normalized;
748 again:
749 status = open_cached_internal_pipe_conn(
750 domain, &samr_pipe, &dom_pol, NULL, NULL);
751 if (!NT_STATUS_IS_OK(status)) {
752 goto fail;
754 h = samr_pipe->binding_handle;
756 status = dcerpc_samr_LookupNames(
757 h, tmp_ctx, &dom_pol, 1, &lsa_name, &rids, &types, &result);
759 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
760 retry = true;
761 goto again;
764 if (!NT_STATUS_IS_OK(status)) {
765 DBG_DEBUG("dcerpc_samr_LookupNames returned %s\n",
766 nt_errstr(status));
767 goto fail;
769 if (!NT_STATUS_IS_OK(result)) {
770 DBG_DEBUG("dcerpc_samr_LookupNames resulted in %s\n",
771 nt_errstr(status));
772 status = result;
773 goto fail;
776 sid_compose(&sid, &domain->sid, rids.ids[0]);
777 type = types.ids[0];
779 done:
780 if (pdom_name != NULL) {
781 *pdom_name = talloc_strdup(mem_ctx, dom_name);
782 if (*pdom_name == NULL) {
783 status = NT_STATUS_NO_MEMORY;
784 goto fail;
788 if (psid) {
789 sid_copy(psid, &sid);
791 if (ptype) {
792 *ptype = type;
795 status = NT_STATUS_OK;
796 fail:
797 TALLOC_FREE(tmp_ctx);
798 return status;
801 /* convert a domain SID to a user or group name */
802 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
803 TALLOC_CTX *mem_ctx,
804 const struct dom_sid *sid,
805 char **pdomain_name,
806 char **pname,
807 enum lsa_SidType *ptype)
809 struct rpc_pipe_client *samr_pipe = NULL;
810 struct dcerpc_binding_handle *h = NULL;
811 struct policy_handle dom_pol = { .handle_type = 0, };
812 const char *domain_name = "";
813 const char *name = "";
814 enum lsa_SidType type = SID_NAME_USE_NONE;
815 struct lsa_Strings names = { .count = 0, };
816 struct samr_Ids types = { .count = 0 };
817 struct dom_sid domain_sid;
818 uint32_t rid;
819 TALLOC_CTX *tmp_ctx = talloc_stackframe();
820 NTSTATUS status = NT_STATUS_NONE_MAPPED;
821 NTSTATUS result;
822 bool retry = false;
823 bool ok;
825 DEBUG(3,("sam_sid_to_name\n"));
827 if (sid_check_is_unix_users(sid)) {
828 domain_name = unix_users_domain_name();
829 type = SID_NAME_DOMAIN;
830 goto done;
832 if (sid_check_is_in_unix_users(sid)) {
833 struct passwd *pwd = NULL;
835 ok = sid_peek_rid(sid, &rid);
836 if (!ok) {
837 goto fail;
839 pwd = getpwuid(rid);
840 if (pwd == NULL) {
841 goto fail;
844 domain_name = unix_users_domain_name();
845 name = talloc_strdup(tmp_ctx, pwd->pw_name);
846 if (name == NULL) {
847 status = NT_STATUS_NO_MEMORY;
848 goto fail;
850 type = SID_NAME_USER;
851 goto done;
854 if (sid_check_is_unix_groups(sid)) {
855 domain_name = unix_groups_domain_name();
856 type = SID_NAME_DOMAIN;
857 goto done;
859 if (sid_check_is_in_unix_groups(sid)) {
860 struct group *grp = NULL;
862 ok = sid_peek_rid(sid, &rid);
863 if (!ok) {
864 goto fail;
866 grp = getgrgid(rid);
867 if (grp == NULL) {
868 goto fail;
871 domain_name = unix_groups_domain_name();
872 name = talloc_strdup(tmp_ctx, grp->gr_name);
873 if (name == NULL) {
874 status = NT_STATUS_NO_MEMORY;
875 goto fail;
877 type = SID_NAME_DOM_GRP;
878 goto done;
881 ok = lookup_wellknown_sid(tmp_ctx, sid, &domain_name, &name);
882 if (ok) {
883 type = SID_NAME_WKN_GRP;
884 goto done;
887 if (dom_sid_equal(sid, &domain->sid)) {
888 domain_name = domain->name;
889 type = SID_NAME_DOMAIN;
890 goto done;
893 sid_copy(&domain_sid, sid);
894 ok = sid_split_rid(&domain_sid, &rid);
895 if (!ok) {
896 goto fail;
899 if (!dom_sid_equal(&domain_sid, &domain->sid)) {
900 goto fail;
903 again:
904 status = open_cached_internal_pipe_conn(
905 domain, &samr_pipe, &dom_pol, NULL, NULL);
906 if (!NT_STATUS_IS_OK(status)) {
907 goto fail;
909 h = samr_pipe->binding_handle;
911 status = dcerpc_samr_LookupRids(
912 h, tmp_ctx, &dom_pol, 1, &rid, &names, &types, &result);
914 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
915 retry = true;
916 goto again;
919 if (!NT_STATUS_IS_OK(status)) {
920 DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
921 nt_errstr(status));
922 goto fail;
924 if (!NT_STATUS_IS_OK(result)) {
925 DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
926 nt_errstr(result));
927 status = result;
928 goto fail;
931 domain_name = domain->name;
932 name = names.names[0].string;
933 type = types.ids[0];
935 if (name != NULL) {
936 char *normalized = NULL;
937 NTSTATUS nstatus = normalize_name_map(
938 tmp_ctx, domain_name, name, &normalized);
939 if (NT_STATUS_IS_OK(nstatus) ||
940 NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
941 name = normalized;
945 done:
946 if (ptype) {
947 *ptype = type;
950 if (pname) {
951 *pname = talloc_strdup(mem_ctx, name);
952 if (*pname == NULL) {
953 status = NT_STATUS_NO_MEMORY;
954 goto fail;
958 if (pdomain_name) {
959 *pdomain_name = talloc_strdup(mem_ctx, domain_name);
960 if (*pdomain_name == NULL) {
961 status = NT_STATUS_NO_MEMORY;
962 goto fail;
966 status = NT_STATUS_OK;
967 fail:
968 TALLOC_FREE(tmp_ctx);
969 return status;
972 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
973 TALLOC_CTX *mem_ctx,
974 const struct dom_sid *domain_sid,
975 uint32_t *rids,
976 size_t num_rids,
977 char **pdomain_name,
978 char ***pnames,
979 enum lsa_SidType **ptypes)
981 struct rpc_pipe_client *samr_pipe = NULL;
982 struct dcerpc_binding_handle *h = NULL;
983 struct policy_handle dom_pol = { .handle_type = 0, };
984 enum lsa_SidType *types = NULL;
985 char **names = NULL;
986 const char *domain_name = NULL;
987 TALLOC_CTX *tmp_ctx = talloc_stackframe();
988 NTSTATUS status = NT_STATUS_NO_MEMORY;
989 NTSTATUS result;
990 bool retry = false;
991 uint32_t i;
993 DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
995 types = talloc_array(tmp_ctx, enum lsa_SidType, num_rids);
996 if (types == NULL) {
997 goto fail;
1000 names = talloc_array(tmp_ctx, char *, num_rids);
1001 if (names == NULL) {
1002 goto fail;
1005 if (sid_check_is_unix_users(domain_sid)) {
1006 domain_name = unix_users_domain_name();
1007 domain_sid = &global_sid_Unix_Users;
1009 if (sid_check_is_unix_groups(domain_sid)) {
1010 domain_name = unix_groups_domain_name();
1011 domain_sid = &global_sid_Unix_Groups;
1014 /* Here we're only interested in the domain name being set */
1015 sid_check_is_wellknown_domain(domain_sid, &domain_name);
1017 if (domain_name != NULL) {
1018 uint32_t num_mapped = 0;
1021 * Do unix users/groups and wkn in a loop. There is no
1022 * getpwuids() call & friends anyway
1025 for (i=0; i<num_rids; i++) {
1026 struct dom_sid sid;
1027 char *name = NULL;
1029 sid_compose(&sid, domain_sid, rids[i]);
1031 types[i] = SID_NAME_UNKNOWN;
1032 names[i] = NULL;
1034 status = sam_sid_to_name(
1035 domain,
1036 tmp_ctx,
1037 &sid,
1038 NULL,
1039 &name,
1040 &types[i]);
1041 if (NT_STATUS_IS_OK(status)) {
1042 names[i] = talloc_move(names, &name);
1043 num_mapped += 1;
1047 status = NT_STATUS_NONE_MAPPED;
1048 if (num_mapped > 0) {
1049 status = (num_mapped == num_rids) ?
1050 NT_STATUS_OK : STATUS_SOME_UNMAPPED;
1052 goto done;
1055 domain_name = domain->name;
1057 again:
1058 status = open_cached_internal_pipe_conn(
1059 domain, &samr_pipe, &dom_pol, NULL, NULL);
1060 if (!NT_STATUS_IS_OK(status)) {
1061 goto done;
1063 h = samr_pipe->binding_handle;
1066 * Magic number 1000 comes from samr.idl
1069 for (i = 0; i < num_rids; i += 1000) {
1070 uint32_t num_lookup_rids = MIN(num_rids - i, 1000);
1071 struct lsa_Strings lsa_names = {
1072 .count = 0,
1074 struct samr_Ids samr_types = {
1075 .count = 0,
1077 uint32_t j;
1079 status = dcerpc_samr_LookupRids(h,
1080 tmp_ctx,
1081 &dom_pol,
1082 num_lookup_rids,
1083 &rids[i],
1084 &lsa_names,
1085 &samr_types,
1086 &result);
1088 if (!retry &&
1089 reset_connection_on_error(domain, samr_pipe, status)) {
1090 retry = true;
1091 goto again;
1094 if (!NT_STATUS_IS_OK(status)) {
1095 DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
1096 nt_errstr(status));
1097 goto fail;
1099 if (!NT_STATUS_IS_OK(result) &&
1100 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
1101 DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
1102 nt_errstr(result));
1103 status = result;
1104 goto fail;
1107 for (j = 0; j < num_lookup_rids; j++) {
1108 uint32_t dst = i + j;
1110 types[dst] = samr_types.ids[j];
1111 names[dst] = talloc_move(
1112 names,
1113 discard_const_p(char *,
1114 &lsa_names.names[j].string));
1115 if (names[dst] != NULL) {
1116 char *normalized = NULL;
1117 NTSTATUS nstatus =
1118 normalize_name_map(names,
1119 domain_name,
1120 names[dst],
1121 &normalized);
1122 if (NT_STATUS_IS_OK(nstatus) ||
1123 NT_STATUS_EQUAL(nstatus,
1124 NT_STATUS_FILE_RENAMED)) {
1125 names[dst] = normalized;
1130 TALLOC_FREE(samr_types.ids);
1131 TALLOC_FREE(lsa_names.names);
1134 done:
1135 if (pdomain_name) {
1136 *pdomain_name = talloc_strdup(mem_ctx, domain_name);
1137 if (*pdomain_name == NULL) {
1138 status = NT_STATUS_NO_MEMORY;
1139 goto fail;
1143 if (ptypes) {
1144 *ptypes = talloc_move(mem_ctx, &types);
1147 if (pnames) {
1148 *pnames = talloc_move(mem_ctx, &names);
1151 fail:
1152 TALLOC_FREE(tmp_ctx);
1153 return status;
1156 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
1157 TALLOC_CTX *mem_ctx,
1158 struct samr_DomInfo12 *lockout_policy)
1160 struct rpc_pipe_client *samr_pipe;
1161 struct policy_handle dom_pol = { 0 };
1162 union samr_DomainInfo *info = NULL;
1163 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1164 NTSTATUS status, result;
1165 struct dcerpc_binding_handle *b = NULL;
1166 bool retry = false;
1168 DEBUG(3,("sam_lockout_policy\n"));
1170 again:
1171 status = open_cached_internal_pipe_conn(domain,
1172 &samr_pipe,
1173 &dom_pol,
1174 NULL,
1175 NULL);
1176 if (!NT_STATUS_IS_OK(status)) {
1177 goto error;
1180 b = samr_pipe->binding_handle;
1182 status = dcerpc_samr_QueryDomainInfo(b,
1183 mem_ctx,
1184 &dom_pol,
1185 DomainLockoutInformation,
1186 &info,
1187 &result);
1189 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1190 retry = true;
1191 goto again;
1194 if (!NT_STATUS_IS_OK(status)) {
1195 goto error;
1197 if (!NT_STATUS_IS_OK(result)) {
1198 status = result;
1199 goto error;
1202 *lockout_policy = info->info12;
1204 error:
1205 TALLOC_FREE(tmp_ctx);
1206 return status;
1209 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
1210 TALLOC_CTX *mem_ctx,
1211 struct samr_DomInfo1 *passwd_policy)
1213 struct rpc_pipe_client *samr_pipe;
1214 struct policy_handle dom_pol = { 0 };
1215 union samr_DomainInfo *info = NULL;
1216 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1217 NTSTATUS status, result;
1218 struct dcerpc_binding_handle *b = NULL;
1219 bool retry = false;
1221 DEBUG(3,("sam_password_policy\n"));
1223 again:
1224 status = open_cached_internal_pipe_conn(domain,
1225 &samr_pipe,
1226 &dom_pol,
1227 NULL,
1228 NULL);
1229 if (!NT_STATUS_IS_OK(status)) {
1230 goto error;
1233 b = samr_pipe->binding_handle;
1235 status = dcerpc_samr_QueryDomainInfo(b,
1236 mem_ctx,
1237 &dom_pol,
1238 DomainPasswordInformation,
1239 &info,
1240 &result);
1242 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1243 retry = true;
1244 goto again;
1247 if (!NT_STATUS_IS_OK(status)) {
1248 goto error;
1250 if (!NT_STATUS_IS_OK(result)) {
1251 status = result;
1252 goto error;
1255 *passwd_policy = info->info1;
1257 error:
1258 TALLOC_FREE(tmp_ctx);
1259 return status;
1262 /* Lookup groups a user is a member of. */
1263 static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
1264 TALLOC_CTX *mem_ctx,
1265 const struct dom_sid *user_sid,
1266 uint32_t *pnum_groups,
1267 struct dom_sid **puser_grpsids)
1269 struct rpc_pipe_client *samr_pipe;
1270 struct policy_handle dom_pol;
1271 struct dom_sid *user_grpsids = NULL;
1272 uint32_t num_groups = 0;
1273 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1274 NTSTATUS status;
1275 bool retry = false;
1277 DEBUG(3,("sam_lookup_usergroups\n"));
1279 ZERO_STRUCT(dom_pol);
1281 if (pnum_groups) {
1282 *pnum_groups = 0;
1285 again:
1286 status = open_cached_internal_pipe_conn(domain,
1287 &samr_pipe,
1288 &dom_pol,
1289 NULL,
1290 NULL);
1291 if (!NT_STATUS_IS_OK(status)) {
1292 goto done;
1295 status = rpc_lookup_usergroups(tmp_ctx,
1296 samr_pipe,
1297 &dom_pol,
1298 &domain->sid,
1299 user_sid,
1300 &num_groups,
1301 &user_grpsids);
1303 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1304 retry = true;
1305 goto again;
1308 if (!NT_STATUS_IS_OK(status)) {
1309 goto done;
1312 if (pnum_groups) {
1313 *pnum_groups = num_groups;
1316 if (puser_grpsids) {
1317 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
1320 done:
1322 TALLOC_FREE(tmp_ctx);
1323 return status;
1326 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
1327 TALLOC_CTX *mem_ctx,
1328 uint32_t num_sids,
1329 const struct dom_sid *sids,
1330 uint32_t *pnum_aliases,
1331 uint32_t **palias_rids)
1333 struct rpc_pipe_client *samr_pipe;
1334 struct policy_handle dom_pol = { 0 };
1335 uint32_t num_aliases = 0;
1336 uint32_t *alias_rids = NULL;
1337 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1338 NTSTATUS status;
1339 bool retry = false;
1341 DEBUG(3,("sam_lookup_useraliases\n"));
1343 if (pnum_aliases) {
1344 *pnum_aliases = 0;
1347 again:
1348 status = open_cached_internal_pipe_conn(domain,
1349 &samr_pipe,
1350 &dom_pol,
1351 NULL,
1352 NULL);
1353 if (!NT_STATUS_IS_OK(status)) {
1354 goto done;
1357 status = rpc_lookup_useraliases(tmp_ctx,
1358 samr_pipe,
1359 &dom_pol,
1360 num_sids,
1361 sids,
1362 &num_aliases,
1363 &alias_rids);
1365 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1366 retry = true;
1367 goto again;
1370 if (!NT_STATUS_IS_OK(status)) {
1371 goto done;
1374 if (pnum_aliases) {
1375 *pnum_aliases = num_aliases;
1378 if (palias_rids) {
1379 *palias_rids = talloc_move(mem_ctx, &alias_rids);
1382 done:
1384 TALLOC_FREE(tmp_ctx);
1385 return status;
1388 /* the rpc backend methods are exposed via this structure */
1389 struct winbindd_methods builtin_passdb_methods = {
1390 .consistent = false,
1392 .query_user_list = builtin_query_user_list,
1393 .enum_dom_groups = builtin_enum_dom_groups,
1394 .enum_local_groups = sam_enum_local_groups,
1395 .name_to_sid = sam_name_to_sid,
1396 .sid_to_name = sam_sid_to_name,
1397 .rids_to_names = sam_rids_to_names,
1398 .lookup_usergroups = sam_lookup_usergroups,
1399 .lookup_useraliases = sam_lookup_useraliases,
1400 .lookup_groupmem = sam_lookup_groupmem,
1401 .lookup_aliasmem = sam_lookup_aliasmem,
1402 .lockout_policy = sam_lockout_policy,
1403 .password_policy = sam_password_policy,
1404 .trusted_domains = builtin_trusted_domains
1407 /* the rpc backend methods are exposed via this structure */
1408 struct winbindd_methods sam_passdb_methods = {
1409 .consistent = false,
1411 .query_user_list = sam_query_user_list,
1412 .enum_dom_groups = sam_enum_dom_groups,
1413 .enum_local_groups = sam_enum_local_groups,
1414 .name_to_sid = sam_name_to_sid,
1415 .sid_to_name = sam_sid_to_name,
1416 .rids_to_names = sam_rids_to_names,
1417 .lookup_usergroups = sam_lookup_usergroups,
1418 .lookup_useraliases = sam_lookup_useraliases,
1419 .lookup_groupmem = sam_lookup_groupmem,
1420 .lookup_aliasmem = sam_lookup_aliasmem,
1421 .lockout_policy = sam_lockout_policy,
1422 .password_policy = sam_password_policy,
1423 .trusted_domains = sam_trusted_domains