ctdb-scripts: Move connection tracking to 10.interface
[samba4-gss.git] / source3 / winbindd / winbindd_samr.c
blob9ba9f22eb4a5198f7f1175315ff2be7c8ceda5f5
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 *ptype = SID_NAME_UNKNOWN;
684 if (strequal(domain_name, unix_users_domain_name())) {
685 struct passwd *pwd = NULL;
687 if (name[0] == '\0') {
688 sid_copy(&sid, &global_sid_Unix_Users);
689 type = SID_NAME_DOMAIN;
690 goto done;
693 pwd = Get_Pwnam_alloc(tmp_ctx, name);
694 if (pwd == NULL) {
695 goto fail;
697 ok = sid_compose(&sid, &global_sid_Unix_Users, pwd->pw_uid);
698 if (!ok) {
699 status = NT_STATUS_INTERNAL_ERROR;
700 goto fail;
702 type = SID_NAME_USER;
703 goto done;
706 if (strequal(domain_name, unix_groups_domain_name())) {
707 struct group *grp = NULL;
709 if (name[0] == '\0') {
710 sid_copy(&sid, &global_sid_Unix_Groups);
711 type = SID_NAME_DOMAIN;
712 goto done;
715 grp = getgrnam(name);
716 if (grp == NULL) {
717 goto fail;
719 ok = sid_compose(&sid, &global_sid_Unix_Groups, grp->gr_gid);
720 if (!ok) {
721 status = NT_STATUS_INTERNAL_ERROR;
722 goto fail;
724 type = SID_NAME_DOM_GRP;
725 goto done;
728 if (name[0] == '\0') {
729 sid_copy(&sid, &domain->sid);
730 type = SID_NAME_DOMAIN;
731 goto done;
734 ok = lookup_wellknown_name(tmp_ctx, name, &sid, &dom_name);
735 if (ok) {
736 type = SID_NAME_WKN_GRP;
737 goto done;
741 char *normalized = NULL;
742 NTSTATUS nstatus = normalize_name_unmap(
743 tmp_ctx, name, &normalized);
744 if (NT_STATUS_IS_OK(nstatus) ||
745 NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
746 lsa_name.string = normalized;
750 again:
751 status = open_cached_internal_pipe_conn(
752 domain, &samr_pipe, &dom_pol, NULL, NULL);
753 if (!NT_STATUS_IS_OK(status)) {
754 goto fail;
756 h = samr_pipe->binding_handle;
758 status = dcerpc_samr_LookupNames(
759 h, tmp_ctx, &dom_pol, 1, &lsa_name, &rids, &types, &result);
761 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
762 retry = true;
763 goto again;
766 if (!NT_STATUS_IS_OK(status)) {
767 DBG_DEBUG("dcerpc_samr_LookupNames returned %s\n",
768 nt_errstr(status));
769 goto fail;
771 if (!NT_STATUS_IS_OK(result)) {
772 DBG_DEBUG("dcerpc_samr_LookupNames resulted in %s\n",
773 nt_errstr(status));
774 status = result;
775 goto fail;
778 sid_compose(&sid, &domain->sid, rids.ids[0]);
779 type = types.ids[0];
781 done:
782 if (pdom_name != NULL) {
783 *pdom_name = talloc_strdup(mem_ctx, dom_name);
784 if (*pdom_name == NULL) {
785 status = NT_STATUS_NO_MEMORY;
786 goto fail;
790 if (psid) {
791 sid_copy(psid, &sid);
793 if (ptype) {
794 *ptype = type;
797 status = NT_STATUS_OK;
798 fail:
799 if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED) ||
800 NT_STATUS_EQUAL(status, NT_STATUS_SOME_NOT_MAPPED))
802 status = NT_STATUS_OK;
804 TALLOC_FREE(tmp_ctx);
805 return status;
808 /* convert a domain SID to a user or group name */
809 static NTSTATUS sam_sid_to_name(struct winbindd_domain *domain,
810 TALLOC_CTX *mem_ctx,
811 const struct dom_sid *sid,
812 char **pdomain_name,
813 char **pname,
814 enum lsa_SidType *ptype)
816 struct rpc_pipe_client *samr_pipe = NULL;
817 struct dcerpc_binding_handle *h = NULL;
818 struct policy_handle dom_pol = { .handle_type = 0, };
819 const char *domain_name = "";
820 const char *name = "";
821 enum lsa_SidType type = SID_NAME_USE_NONE;
822 struct lsa_Strings names = { .count = 0, };
823 struct samr_Ids types = { .count = 0 };
824 struct dom_sid domain_sid;
825 uint32_t rid;
826 TALLOC_CTX *tmp_ctx = talloc_stackframe();
827 NTSTATUS status = NT_STATUS_NONE_MAPPED;
828 NTSTATUS result;
829 bool retry = false;
830 bool ok;
832 DEBUG(3,("sam_sid_to_name\n"));
834 if (sid_check_is_unix_users(sid)) {
835 domain_name = unix_users_domain_name();
836 type = SID_NAME_DOMAIN;
837 goto done;
839 if (sid_check_is_in_unix_users(sid)) {
840 struct passwd *pwd = NULL;
842 ok = sid_peek_rid(sid, &rid);
843 if (!ok) {
844 goto fail;
846 pwd = getpwuid(rid);
847 if (pwd == NULL) {
848 goto fail;
851 domain_name = unix_users_domain_name();
852 name = talloc_strdup(tmp_ctx, pwd->pw_name);
853 if (name == NULL) {
854 status = NT_STATUS_NO_MEMORY;
855 goto fail;
857 type = SID_NAME_USER;
858 goto done;
861 if (sid_check_is_unix_groups(sid)) {
862 domain_name = unix_groups_domain_name();
863 type = SID_NAME_DOMAIN;
864 goto done;
866 if (sid_check_is_in_unix_groups(sid)) {
867 struct group *grp = NULL;
869 ok = sid_peek_rid(sid, &rid);
870 if (!ok) {
871 goto fail;
873 grp = getgrgid(rid);
874 if (grp == NULL) {
875 goto fail;
878 domain_name = unix_groups_domain_name();
879 name = talloc_strdup(tmp_ctx, grp->gr_name);
880 if (name == NULL) {
881 status = NT_STATUS_NO_MEMORY;
882 goto fail;
884 type = SID_NAME_DOM_GRP;
885 goto done;
888 ok = lookup_wellknown_sid(tmp_ctx, sid, &domain_name, &name);
889 if (ok) {
890 type = SID_NAME_WKN_GRP;
891 goto done;
894 if (dom_sid_equal(sid, &domain->sid)) {
895 domain_name = domain->name;
896 type = SID_NAME_DOMAIN;
897 goto done;
900 sid_copy(&domain_sid, sid);
901 ok = sid_split_rid(&domain_sid, &rid);
902 if (!ok) {
903 goto fail;
906 if (!dom_sid_equal(&domain_sid, &domain->sid)) {
907 goto fail;
910 again:
911 status = open_cached_internal_pipe_conn(
912 domain, &samr_pipe, &dom_pol, NULL, NULL);
913 if (!NT_STATUS_IS_OK(status)) {
914 goto fail;
916 h = samr_pipe->binding_handle;
918 status = dcerpc_samr_LookupRids(
919 h, tmp_ctx, &dom_pol, 1, &rid, &names, &types, &result);
921 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
922 retry = true;
923 goto again;
926 if (!NT_STATUS_IS_OK(status)) {
927 DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
928 nt_errstr(status));
929 goto fail;
931 if (!NT_STATUS_IS_OK(result)) {
932 DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
933 nt_errstr(result));
934 status = result;
935 goto fail;
938 domain_name = domain->name;
939 name = names.names[0].string;
940 type = types.ids[0];
942 if (name != NULL) {
943 char *normalized = NULL;
944 NTSTATUS nstatus = normalize_name_map(
945 tmp_ctx, domain_name, name, &normalized);
946 if (NT_STATUS_IS_OK(nstatus) ||
947 NT_STATUS_EQUAL(nstatus, NT_STATUS_FILE_RENAMED)) {
948 name = normalized;
952 done:
953 if (ptype) {
954 *ptype = type;
957 if (pname) {
958 *pname = talloc_strdup(mem_ctx, name);
959 if (*pname == NULL) {
960 status = NT_STATUS_NO_MEMORY;
961 goto fail;
965 if (pdomain_name) {
966 *pdomain_name = talloc_strdup(mem_ctx, domain_name);
967 if (*pdomain_name == NULL) {
968 status = NT_STATUS_NO_MEMORY;
969 goto fail;
973 status = NT_STATUS_OK;
974 fail:
975 TALLOC_FREE(tmp_ctx);
976 return status;
979 static NTSTATUS sam_rids_to_names(struct winbindd_domain *domain,
980 TALLOC_CTX *mem_ctx,
981 const struct dom_sid *domain_sid,
982 uint32_t *rids,
983 size_t num_rids,
984 char **pdomain_name,
985 char ***pnames,
986 enum lsa_SidType **ptypes)
988 struct rpc_pipe_client *samr_pipe = NULL;
989 struct dcerpc_binding_handle *h = NULL;
990 struct policy_handle dom_pol = { .handle_type = 0, };
991 enum lsa_SidType *types = NULL;
992 char **names = NULL;
993 const char *domain_name = NULL;
994 TALLOC_CTX *tmp_ctx = talloc_stackframe();
995 NTSTATUS status = NT_STATUS_NO_MEMORY;
996 NTSTATUS result;
997 bool retry = false;
998 uint32_t i;
1000 DEBUG(3,("sam_rids_to_names for %s\n", domain->name));
1002 types = talloc_array(tmp_ctx, enum lsa_SidType, num_rids);
1003 if (types == NULL) {
1004 goto fail;
1007 names = talloc_array(tmp_ctx, char *, num_rids);
1008 if (names == NULL) {
1009 goto fail;
1012 if (sid_check_is_unix_users(domain_sid)) {
1013 domain_name = unix_users_domain_name();
1014 domain_sid = &global_sid_Unix_Users;
1016 if (sid_check_is_unix_groups(domain_sid)) {
1017 domain_name = unix_groups_domain_name();
1018 domain_sid = &global_sid_Unix_Groups;
1021 /* Here we're only interested in the domain name being set */
1022 sid_check_is_wellknown_domain(domain_sid, &domain_name);
1024 if (domain_name != NULL) {
1025 uint32_t num_mapped = 0;
1028 * Do unix users/groups and wkn in a loop. There is no
1029 * getpwuids() call & friends anyway
1032 for (i=0; i<num_rids; i++) {
1033 struct dom_sid sid;
1034 char *name = NULL;
1036 sid_compose(&sid, domain_sid, rids[i]);
1038 types[i] = SID_NAME_UNKNOWN;
1039 names[i] = NULL;
1041 status = sam_sid_to_name(
1042 domain,
1043 tmp_ctx,
1044 &sid,
1045 NULL,
1046 &name,
1047 &types[i]);
1048 if (NT_STATUS_IS_OK(status)) {
1049 names[i] = talloc_move(names, &name);
1050 num_mapped += 1;
1054 status = NT_STATUS_NONE_MAPPED;
1055 if (num_mapped > 0) {
1056 status = (num_mapped == num_rids) ?
1057 NT_STATUS_OK : STATUS_SOME_UNMAPPED;
1059 goto done;
1062 domain_name = domain->name;
1064 again:
1065 status = open_cached_internal_pipe_conn(
1066 domain, &samr_pipe, &dom_pol, NULL, NULL);
1067 if (!NT_STATUS_IS_OK(status)) {
1068 goto done;
1070 h = samr_pipe->binding_handle;
1073 * Magic number 1000 comes from samr.idl
1076 for (i = 0; i < num_rids; i += 1000) {
1077 uint32_t num_lookup_rids = MIN(num_rids - i, 1000);
1078 struct lsa_Strings lsa_names = {
1079 .count = 0,
1081 struct samr_Ids samr_types = {
1082 .count = 0,
1084 uint32_t j;
1086 status = dcerpc_samr_LookupRids(h,
1087 tmp_ctx,
1088 &dom_pol,
1089 num_lookup_rids,
1090 &rids[i],
1091 &lsa_names,
1092 &samr_types,
1093 &result);
1095 if (!retry &&
1096 reset_connection_on_error(domain, samr_pipe, status)) {
1097 retry = true;
1098 goto again;
1101 if (!NT_STATUS_IS_OK(status)) {
1102 DBG_DEBUG("dcerpc_samr_LookupRids failed: %s\n",
1103 nt_errstr(status));
1104 goto fail;
1106 if (!NT_STATUS_IS_OK(result) &&
1107 !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) {
1108 DBG_DEBUG("dcerpc_samr_LookupRids resulted in %s\n",
1109 nt_errstr(result));
1110 status = result;
1111 goto fail;
1114 for (j = 0; j < num_lookup_rids; j++) {
1115 uint32_t dst = i + j;
1117 types[dst] = samr_types.ids[j];
1118 names[dst] = talloc_move(
1119 names,
1120 discard_const_p(char *,
1121 &lsa_names.names[j].string));
1122 if (names[dst] != NULL) {
1123 char *normalized = NULL;
1124 NTSTATUS nstatus =
1125 normalize_name_map(names,
1126 domain_name,
1127 names[dst],
1128 &normalized);
1129 if (NT_STATUS_IS_OK(nstatus) ||
1130 NT_STATUS_EQUAL(nstatus,
1131 NT_STATUS_FILE_RENAMED)) {
1132 names[dst] = normalized;
1137 TALLOC_FREE(samr_types.ids);
1138 TALLOC_FREE(lsa_names.names);
1141 done:
1142 if (pdomain_name) {
1143 *pdomain_name = talloc_strdup(mem_ctx, domain_name);
1144 if (*pdomain_name == NULL) {
1145 status = NT_STATUS_NO_MEMORY;
1146 goto fail;
1150 if (ptypes) {
1151 *ptypes = talloc_move(mem_ctx, &types);
1154 if (pnames) {
1155 *pnames = talloc_move(mem_ctx, &names);
1158 fail:
1159 TALLOC_FREE(tmp_ctx);
1160 return status;
1163 static NTSTATUS sam_lockout_policy(struct winbindd_domain *domain,
1164 TALLOC_CTX *mem_ctx,
1165 struct samr_DomInfo12 *lockout_policy)
1167 struct rpc_pipe_client *samr_pipe;
1168 struct policy_handle dom_pol = { 0 };
1169 union samr_DomainInfo *info = NULL;
1170 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1171 NTSTATUS status, result;
1172 struct dcerpc_binding_handle *b = NULL;
1173 bool retry = false;
1175 DEBUG(3,("sam_lockout_policy\n"));
1177 again:
1178 status = open_cached_internal_pipe_conn(domain,
1179 &samr_pipe,
1180 &dom_pol,
1181 NULL,
1182 NULL);
1183 if (!NT_STATUS_IS_OK(status)) {
1184 goto error;
1187 b = samr_pipe->binding_handle;
1189 status = dcerpc_samr_QueryDomainInfo(b,
1190 mem_ctx,
1191 &dom_pol,
1192 DomainLockoutInformation,
1193 &info,
1194 &result);
1196 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1197 retry = true;
1198 goto again;
1201 if (!NT_STATUS_IS_OK(status)) {
1202 goto error;
1204 if (!NT_STATUS_IS_OK(result)) {
1205 status = result;
1206 goto error;
1209 *lockout_policy = info->info12;
1211 error:
1212 TALLOC_FREE(tmp_ctx);
1213 return status;
1216 static NTSTATUS sam_password_policy(struct winbindd_domain *domain,
1217 TALLOC_CTX *mem_ctx,
1218 struct samr_DomInfo1 *passwd_policy)
1220 struct rpc_pipe_client *samr_pipe;
1221 struct policy_handle dom_pol = { 0 };
1222 union samr_DomainInfo *info = NULL;
1223 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1224 NTSTATUS status, result;
1225 struct dcerpc_binding_handle *b = NULL;
1226 bool retry = false;
1228 DEBUG(3,("sam_password_policy\n"));
1230 again:
1231 status = open_cached_internal_pipe_conn(domain,
1232 &samr_pipe,
1233 &dom_pol,
1234 NULL,
1235 NULL);
1236 if (!NT_STATUS_IS_OK(status)) {
1237 goto error;
1240 b = samr_pipe->binding_handle;
1242 status = dcerpc_samr_QueryDomainInfo(b,
1243 mem_ctx,
1244 &dom_pol,
1245 DomainPasswordInformation,
1246 &info,
1247 &result);
1249 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1250 retry = true;
1251 goto again;
1254 if (!NT_STATUS_IS_OK(status)) {
1255 goto error;
1257 if (!NT_STATUS_IS_OK(result)) {
1258 status = result;
1259 goto error;
1262 *passwd_policy = info->info1;
1264 error:
1265 TALLOC_FREE(tmp_ctx);
1266 return status;
1269 /* Lookup groups a user is a member of. */
1270 static NTSTATUS sam_lookup_usergroups(struct winbindd_domain *domain,
1271 TALLOC_CTX *mem_ctx,
1272 const struct dom_sid *user_sid,
1273 uint32_t *pnum_groups,
1274 struct dom_sid **puser_grpsids)
1276 struct rpc_pipe_client *samr_pipe;
1277 struct policy_handle dom_pol;
1278 struct dom_sid *user_grpsids = NULL;
1279 uint32_t num_groups = 0;
1280 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1281 NTSTATUS status;
1282 bool retry = false;
1284 DEBUG(3,("sam_lookup_usergroups\n"));
1286 ZERO_STRUCT(dom_pol);
1288 if (pnum_groups) {
1289 *pnum_groups = 0;
1292 again:
1293 status = open_cached_internal_pipe_conn(domain,
1294 &samr_pipe,
1295 &dom_pol,
1296 NULL,
1297 NULL);
1298 if (!NT_STATUS_IS_OK(status)) {
1299 goto done;
1302 status = rpc_lookup_usergroups(tmp_ctx,
1303 samr_pipe,
1304 &dom_pol,
1305 &domain->sid,
1306 user_sid,
1307 &num_groups,
1308 &user_grpsids);
1310 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1311 retry = true;
1312 goto again;
1315 if (!NT_STATUS_IS_OK(status)) {
1316 goto done;
1319 if (pnum_groups) {
1320 *pnum_groups = num_groups;
1323 if (puser_grpsids) {
1324 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
1327 done:
1329 TALLOC_FREE(tmp_ctx);
1330 return status;
1333 static NTSTATUS sam_lookup_useraliases(struct winbindd_domain *domain,
1334 TALLOC_CTX *mem_ctx,
1335 uint32_t num_sids,
1336 const struct dom_sid *sids,
1337 uint32_t *pnum_aliases,
1338 uint32_t **palias_rids)
1340 struct rpc_pipe_client *samr_pipe;
1341 struct policy_handle dom_pol = { 0 };
1342 uint32_t num_aliases = 0;
1343 uint32_t *alias_rids = NULL;
1344 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1345 NTSTATUS status;
1346 bool retry = false;
1348 DEBUG(3,("sam_lookup_useraliases\n"));
1350 if (pnum_aliases) {
1351 *pnum_aliases = 0;
1354 again:
1355 status = open_cached_internal_pipe_conn(domain,
1356 &samr_pipe,
1357 &dom_pol,
1358 NULL,
1359 NULL);
1360 if (!NT_STATUS_IS_OK(status)) {
1361 goto done;
1364 status = rpc_lookup_useraliases(tmp_ctx,
1365 samr_pipe,
1366 &dom_pol,
1367 num_sids,
1368 sids,
1369 &num_aliases,
1370 &alias_rids);
1372 if (!retry && reset_connection_on_error(domain, samr_pipe, status)) {
1373 retry = true;
1374 goto again;
1377 if (!NT_STATUS_IS_OK(status)) {
1378 goto done;
1381 if (pnum_aliases) {
1382 *pnum_aliases = num_aliases;
1385 if (palias_rids) {
1386 *palias_rids = talloc_move(mem_ctx, &alias_rids);
1389 done:
1391 TALLOC_FREE(tmp_ctx);
1392 return status;
1395 /* the rpc backend methods are exposed via this structure */
1396 struct winbindd_methods builtin_passdb_methods = {
1397 .consistent = false,
1399 .query_user_list = builtin_query_user_list,
1400 .enum_dom_groups = builtin_enum_dom_groups,
1401 .enum_local_groups = sam_enum_local_groups,
1402 .name_to_sid = sam_name_to_sid,
1403 .sid_to_name = sam_sid_to_name,
1404 .rids_to_names = sam_rids_to_names,
1405 .lookup_usergroups = sam_lookup_usergroups,
1406 .lookup_useraliases = sam_lookup_useraliases,
1407 .lookup_groupmem = sam_lookup_groupmem,
1408 .lookup_aliasmem = sam_lookup_aliasmem,
1409 .lockout_policy = sam_lockout_policy,
1410 .password_policy = sam_password_policy,
1411 .trusted_domains = builtin_trusted_domains
1414 /* the rpc backend methods are exposed via this structure */
1415 struct winbindd_methods sam_passdb_methods = {
1416 .consistent = false,
1418 .query_user_list = sam_query_user_list,
1419 .enum_dom_groups = sam_enum_dom_groups,
1420 .enum_local_groups = sam_enum_local_groups,
1421 .name_to_sid = sam_name_to_sid,
1422 .sid_to_name = sam_sid_to_name,
1423 .rids_to_names = sam_rids_to_names,
1424 .lookup_usergroups = sam_lookup_usergroups,
1425 .lookup_useraliases = sam_lookup_useraliases,
1426 .lookup_groupmem = sam_lookup_groupmem,
1427 .lookup_aliasmem = sam_lookup_aliasmem,
1428 .lockout_policy = sam_lockout_policy,
1429 .password_policy = sam_password_policy,
1430 .trusted_domains = sam_trusted_domains