s3-winbind: Implemented samr backend function common_lookup_useraliases.
[Samba/gebeck_regimport.git] / source3 / winbindd / winbindd_samr.c
blobb611602e8b058240c35d1c64b005a926a2fc5d05
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 "../librpc/gen_ndr/cli_samr.h"
29 #include "rpc_client/cli_samr.h"
30 #include "../librpc/gen_ndr/srv_samr.h"
31 #include "../librpc/gen_ndr/cli_lsa.h"
32 #include "rpc_client/cli_lsarpc.h"
33 #include "../librpc/gen_ndr/srv_lsa.h"
35 #undef DBGC_CLASS
36 #define DBGC_CLASS DBGC_WINBIND
38 static NTSTATUS open_internal_samr_pipe(TALLOC_CTX *mem_ctx,
39 struct rpc_pipe_client **samr_pipe)
41 static struct rpc_pipe_client *cli = NULL;
42 struct auth_serversupplied_info *server_info = NULL;
43 NTSTATUS status;
45 if (cli != NULL) {
46 goto done;
49 if (server_info == NULL) {
50 status = make_server_info_system(mem_ctx, &server_info);
51 if (!NT_STATUS_IS_OK(status)) {
52 DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
53 nt_errstr(status)));
54 return status;
58 /* create a samr connection */
59 status = rpc_pipe_open_internal(talloc_autofree_context(),
60 &ndr_table_samr.syntax_id,
61 rpc_samr_dispatch,
62 server_info,
63 &cli);
64 if (!NT_STATUS_IS_OK(status)) {
65 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
66 nt_errstr(status)));
67 return status;
70 done:
71 if (samr_pipe) {
72 *samr_pipe = cli;
75 return NT_STATUS_OK;
78 static 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;
84 struct policy_handle samr_connect_hnd;
86 status = open_internal_samr_pipe(mem_ctx, samr_pipe);
87 if (!NT_STATUS_IS_OK(status)) {
88 return status;
91 status = rpccli_samr_Connect2((*samr_pipe),
92 mem_ctx,
93 (*samr_pipe)->desthost,
94 SEC_FLAG_MAXIMUM_ALLOWED,
95 &samr_connect_hnd);
96 if (!NT_STATUS_IS_OK(status)) {
97 return status;
100 status = rpccli_samr_OpenDomain((*samr_pipe),
101 mem_ctx,
102 &samr_connect_hnd,
103 SEC_FLAG_MAXIMUM_ALLOWED,
104 &domain->sid,
105 samr_domain_hnd);
107 return status;
110 static NTSTATUS open_internal_lsa_pipe(TALLOC_CTX *mem_ctx,
111 struct rpc_pipe_client **lsa_pipe)
113 static struct rpc_pipe_client *cli = NULL;
114 struct auth_serversupplied_info *server_info = NULL;
115 NTSTATUS status;
117 if (cli != NULL) {
118 goto done;
121 if (server_info == NULL) {
122 status = make_server_info_system(mem_ctx, &server_info);
123 if (!NT_STATUS_IS_OK(status)) {
124 DEBUG(0, ("open_samr_pipe: Could not create auth_serversupplied_info: %s\n",
125 nt_errstr(status)));
126 return status;
130 /* create a samr connection */
131 status = rpc_pipe_open_internal(talloc_autofree_context(),
132 &ndr_table_lsarpc.syntax_id,
133 rpc_lsarpc_dispatch,
134 server_info,
135 &cli);
136 if (!NT_STATUS_IS_OK(status)) {
137 DEBUG(0, ("open_samr_pipe: Could not connect to samr_pipe: %s\n",
138 nt_errstr(status)));
139 return status;
142 done:
143 if (lsa_pipe) {
144 *lsa_pipe = cli;
147 return NT_STATUS_OK;
150 static NTSTATUS open_internal_lsa_conn(TALLOC_CTX *mem_ctx,
151 struct rpc_pipe_client **lsa_pipe,
152 struct policy_handle *lsa_hnd)
154 NTSTATUS status;
156 status = open_internal_lsa_pipe(mem_ctx, lsa_pipe);
157 if (!NT_STATUS_IS_OK(status)) {
158 return status;
161 status = rpccli_lsa_open_policy((*lsa_pipe),
162 mem_ctx,
163 true,
164 SEC_FLAG_MAXIMUM_ALLOWED,
165 lsa_hnd);
167 return status;
170 /*********************************************************************
171 SAM specific functions.
172 *********************************************************************/
174 /* List all domain groups */
175 static NTSTATUS sam_enum_dom_groups(struct winbindd_domain *domain,
176 TALLOC_CTX *mem_ctx,
177 uint32_t *pnum_info,
178 struct acct_info **pinfo)
180 struct rpc_pipe_client *samr_pipe;
181 struct policy_handle dom_pol;
182 struct acct_info *info = NULL;
183 TALLOC_CTX *tmp_ctx;
184 uint32_t start = 0;
185 uint32_t num_info = 0;
186 NTSTATUS status;
188 DEBUG(3,("samr: query_user_list\n"));
190 if (pnum_info) {
191 *pnum_info = 0;
194 tmp_ctx = talloc_stackframe();
195 if (tmp_ctx == NULL) {
196 return NT_STATUS_NO_MEMORY;
199 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
200 if (!NT_STATUS_IS_OK(status)) {
201 goto error;
204 do {
205 struct samr_SamArray *sam_array = NULL;
206 uint32_t count = 0;
207 uint32_t g;
209 /* start is updated by this call. */
210 status = rpccli_samr_EnumDomainGroups(samr_pipe,
211 tmp_ctx,
212 &dom_pol,
213 &start,
214 &sam_array,
215 0xFFFF, /* buffer size? */
216 &count);
217 if (!NT_STATUS_IS_OK(status)) {
218 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
219 DEBUG(2,("query_user_list: failed to enum domain groups: %s\n",
220 nt_errstr(status)));
221 goto error;
225 info = TALLOC_REALLOC_ARRAY(tmp_ctx,
226 info,
227 struct acct_info,
228 num_info + count);
229 if (info == NULL) {
230 status = NT_STATUS_NO_MEMORY;
231 goto error;
234 for (g = 0; g < count; g++) {
235 fstrcpy(info[num_info + g].acct_name,
236 sam_array->entries[g].name.string);
238 info[num_info + g].rid = sam_array->entries[g].idx;
241 num_info += count;
242 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
244 if (pnum_info) {
245 *pnum_info = num_info;
248 if (pinfo) {
249 *pinfo = talloc_move(mem_ctx, &info);
252 error:
253 TALLOC_FREE(tmp_ctx);
254 return status;
257 /* Query display info for a domain */
258 static NTSTATUS sam_query_user_list(struct winbindd_domain *domain,
259 TALLOC_CTX *mem_ctx,
260 uint32_t *pnum_info,
261 struct wbint_userinfo **pinfo)
263 struct rpc_pipe_client *samr_pipe = NULL;
264 struct wbint_userinfo *info = NULL;
265 struct policy_handle dom_pol;
266 uint32_t num_info = 0;
267 uint32_t loop_count = 0;
268 uint32_t start_idx = 0;
269 uint32_t i = 0;
270 TALLOC_CTX *tmp_ctx;
271 NTSTATUS status;
273 DEBUG(3,("samr: query_user_list\n"));
275 if (pnum_info) {
276 *pnum_info = 0;
279 tmp_ctx = talloc_stackframe();
280 if (tmp_ctx == NULL) {
281 return NT_STATUS_NO_MEMORY;
284 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
285 if (!NT_STATUS_IS_OK(status)) {
286 goto error;
289 do {
290 uint32_t j;
291 uint32_t num_dom_users;
292 uint32_t max_entries, max_size;
293 uint32_t total_size, returned_size;
294 union samr_DispInfo disp_info;
296 get_query_dispinfo_params(loop_count,
297 &max_entries,
298 &max_size);
300 status = rpccli_samr_QueryDisplayInfo(samr_pipe,
301 tmp_ctx,
302 &dom_pol,
303 1, /* level */
304 start_idx,
305 max_entries,
306 max_size,
307 &total_size,
308 &returned_size,
309 &disp_info);
310 if (!NT_STATUS_IS_OK(status)) {
311 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
312 goto error;
316 /* increment required start query values */
317 start_idx += disp_info.info1.count;
318 loop_count++;
319 num_dom_users = disp_info.info1.count;
321 num_info += num_dom_users;
323 info = TALLOC_REALLOC_ARRAY(tmp_ctx,
324 info,
325 struct wbint_userinfo,
326 num_info);
327 if (info == NULL) {
328 status = NT_STATUS_NO_MEMORY;
329 goto error;
332 for (j = 0; j < num_dom_users; i++, j++) {
333 uint32_t rid = disp_info.info1.entries[j].rid;
334 struct samr_DispEntryGeneral *src;
335 struct wbint_userinfo *dst;
337 src = &(disp_info.info1.entries[j]);
338 dst = &(info[i]);
340 dst->acct_name = talloc_strdup(info,
341 src->account_name.string);
342 if (dst->acct_name == NULL) {
343 status = NT_STATUS_NO_MEMORY;
344 goto error;
347 dst->full_name = talloc_strdup(info, src->full_name.string);
348 if (dst->full_name == NULL) {
349 status = NT_STATUS_NO_MEMORY;
350 goto error;
353 dst->homedir = NULL;
354 dst->shell = NULL;
356 sid_compose(&dst->user_sid, &domain->sid, rid);
358 /* For the moment we set the primary group for
359 every user to be the Domain Users group.
360 There are serious problems with determining
361 the actual primary group for large domains.
362 This should really be made into a 'winbind
363 force group' smb.conf parameter or
364 something like that. */
365 sid_compose(&dst->group_sid, &domain->sid,
366 DOMAIN_RID_USERS);
368 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
370 if (pnum_info) {
371 *pnum_info = num_info;
374 if (pinfo) {
375 *pinfo = talloc_move(mem_ctx, &info);
378 error:
379 TALLOC_FREE(tmp_ctx);
380 return status;
383 /* Lookup user information from a rid or username. */
384 static NTSTATUS sam_query_user(struct winbindd_domain *domain,
385 TALLOC_CTX *mem_ctx,
386 const struct dom_sid *user_sid,
387 struct wbint_userinfo *user_info)
389 struct rpc_pipe_client *samr_pipe;
390 struct policy_handle dom_pol, user_pol;
391 union samr_UserInfo *info = NULL;
392 TALLOC_CTX *tmp_ctx;
393 uint32_t user_rid;
394 NTSTATUS status;
396 DEBUG(3,("samr: query_user\n"));
398 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
399 return NT_STATUS_UNSUCCESSFUL;
402 if (user_info) {
403 user_info->homedir = NULL;
404 user_info->shell = NULL;
405 user_info->primary_gid = (gid_t) -1;
408 tmp_ctx = talloc_stackframe();
409 if (tmp_ctx == NULL) {
410 return NT_STATUS_NO_MEMORY;
413 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
414 if (!NT_STATUS_IS_OK(status)) {
415 goto error;
418 /* Get user handle */
419 status = rpccli_samr_OpenUser(samr_pipe,
420 tmp_ctx,
421 &dom_pol,
422 SEC_FLAG_MAXIMUM_ALLOWED,
423 user_rid,
424 &user_pol);
425 if (!NT_STATUS_IS_OK(status)) {
426 goto error;
429 /* Get user info */
430 status = rpccli_samr_QueryUserInfo(samr_pipe,
431 tmp_ctx,
432 &user_pol,
433 0x15,
434 &info);
436 rpccli_samr_Close(samr_pipe, tmp_ctx, &user_pol);
438 if (!NT_STATUS_IS_OK(status)) {
439 goto error;
442 sid_compose(&user_info->user_sid, &domain->sid, user_rid);
443 sid_compose(&user_info->group_sid, &domain->sid,
444 info->info21.primary_gid);
446 if (user_info) {
447 user_info->acct_name = talloc_strdup(mem_ctx,
448 info->info21.account_name.string);
449 if (user_info->acct_name == NULL) {
450 status = NT_STATUS_NO_MEMORY;
451 goto error;
454 user_info->full_name = talloc_strdup(mem_ctx,
455 info->info21.full_name.string);
456 if (user_info->acct_name == NULL) {
457 status = NT_STATUS_NO_MEMORY;
458 goto error;
461 user_info->homedir = NULL;
462 user_info->shell = NULL;
463 user_info->primary_gid = (gid_t)-1;
466 status = NT_STATUS_OK;
467 error:
468 TALLOC_FREE(tmp_ctx);
469 return status;
472 /* get a list of trusted domains - builtin domain */
473 static NTSTATUS sam_trusted_domains(struct winbindd_domain *domain,
474 TALLOC_CTX *mem_ctx,
475 struct netr_DomainTrustList *trusts)
477 struct rpc_pipe_client *lsa_pipe;
478 struct netr_DomainTrust *array = NULL;
479 struct policy_handle lsa_policy;
480 uint32_t enum_ctx = 0;
481 uint32_t count = 0;
482 TALLOC_CTX *tmp_ctx;
483 NTSTATUS status;
485 DEBUG(3,("samr: trusted domains\n"));
487 tmp_ctx = talloc_stackframe();
488 if (tmp_ctx == NULL) {
489 return NT_STATUS_NO_MEMORY;
492 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
493 if (!NT_STATUS_IS_OK(status)) {
494 goto error;
497 do {
498 struct lsa_DomainList dom_list;
499 uint32_t start_idx;
500 uint32_t i;
503 * We don't run into deadlocks here, cause winbind_off() is
504 * called in the main function.
506 status = rpccli_lsa_EnumTrustDom(lsa_pipe,
507 tmp_ctx,
508 &lsa_policy,
509 &enum_ctx,
510 &dom_list,
511 (uint32_t) -1);
512 if (!NT_STATUS_IS_OK(status)) {
513 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
514 goto error;
518 start_idx = trusts->count;
519 count += dom_list.count;
521 array = talloc_realloc(tmp_ctx,
522 array,
523 struct netr_DomainTrust,
524 count);
525 if (array == NULL) {
526 status = NT_STATUS_NO_MEMORY;
527 goto error;
530 for (i = 0; i < dom_list.count; i++) {
531 struct netr_DomainTrust *trust = &array[i];
532 struct dom_sid *sid;
534 ZERO_STRUCTP(trust);
536 trust->netbios_name = talloc_move(array,
537 &dom_list.domains[i].name.string);
538 trust->dns_name = NULL;
540 sid = talloc(array, struct dom_sid);
541 if (sid == NULL) {
542 status = NT_STATUS_NO_MEMORY;
543 goto error;
545 sid_copy(sid, dom_list.domains[i].sid);
546 trust->sid = sid;
548 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
550 if (trusts) {
551 trusts->count = count;
552 trusts->array = talloc_move(mem_ctx, &array);
555 error:
556 TALLOC_FREE(tmp_ctx);
557 return status;
560 /* Lookup group membership given a rid. */
561 static NTSTATUS sam_lookup_groupmem(struct winbindd_domain *domain,
562 TALLOC_CTX *mem_ctx,
563 const struct dom_sid *group_sid,
564 enum lsa_SidType type,
565 uint32_t *pnum_names,
566 struct dom_sid **psid_mem,
567 char ***pnames,
568 uint32_t **pname_types)
570 struct rpc_pipe_client *samr_pipe;
571 struct policy_handle dom_pol, group_pol;
572 uint32_t samr_access = SEC_FLAG_MAXIMUM_ALLOWED;
573 struct samr_RidTypeArray *rids = NULL;
574 uint32_t group_rid;
575 uint32_t *rid_mem = NULL;
577 uint32_t num_names = 0;
578 uint32_t total_names = 0;
579 struct dom_sid *sid_mem = NULL;
580 char **names = NULL;
581 uint32_t *name_types = NULL;
583 struct lsa_Strings tmp_names;
584 struct samr_Ids tmp_types;
586 uint32_t j, r;
587 TALLOC_CTX *tmp_ctx;
588 NTSTATUS status;
590 DEBUG(3,("samr: lookup groupmem\n"));
592 if (pnum_names) {
593 pnum_names = 0;
596 if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) {
597 return NT_STATUS_UNSUCCESSFUL;
600 tmp_ctx = talloc_stackframe();
601 if (tmp_ctx == NULL) {
602 return NT_STATUS_NO_MEMORY;
605 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
606 if (!NT_STATUS_IS_OK(status)) {
607 goto error;
610 status = rpccli_samr_OpenGroup(samr_pipe,
611 tmp_ctx,
612 &dom_pol,
613 samr_access,
614 group_rid,
615 &group_pol);
616 if (!NT_STATUS_IS_OK(status)) {
617 goto error;
621 * Step #1: Get a list of user rids that are the members of the group.
623 status = rpccli_samr_QueryGroupMember(samr_pipe,
624 tmp_ctx,
625 &group_pol,
626 &rids);
628 rpccli_samr_Close(samr_pipe, tmp_ctx, &group_pol);
630 if (!NT_STATUS_IS_OK(status)) {
631 goto error;
634 if (rids == NULL || rids->count == 0) {
635 pnum_names = 0;
636 pnames = NULL;
637 pname_types = NULL;
638 psid_mem = NULL;
640 status = NT_STATUS_OK;
641 goto error;
644 num_names = rids->count;
645 rid_mem = rids->rids;
648 * Step #2: Convert list of rids into list of usernames.
650 #define MAX_LOOKUP_RIDS 900
652 if (num_names > 0) {
653 names = TALLOC_ZERO_ARRAY(tmp_ctx, char *, num_names);
654 name_types = TALLOC_ZERO_ARRAY(tmp_ctx, uint32_t, num_names);
655 sid_mem = TALLOC_ZERO_ARRAY(tmp_ctx, struct dom_sid, num_names);
656 if (names == NULL || name_types == NULL || sid_mem == NULL) {
657 status = NT_STATUS_NO_MEMORY;
658 goto error;
662 for (j = 0; j < num_names; j++) {
663 sid_compose(&sid_mem[j], &domain->sid, rid_mem[j]);
666 status = rpccli_samr_LookupRids(samr_pipe,
667 tmp_ctx,
668 &dom_pol,
669 num_names,
670 rid_mem,
671 &tmp_names,
672 &tmp_types);
673 if (!NT_STATUS_IS_OK(status)) {
674 if (!NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
675 goto error;
679 /* Copy result into array. The talloc system will take
680 care of freeing the temporary arrays later on. */
681 if (tmp_names.count != tmp_types.count) {
682 status = NT_STATUS_UNSUCCESSFUL;
683 goto error;
686 for (r = 0; r < tmp_names.count; r++) {
687 if (tmp_types.ids[r] == SID_NAME_UNKNOWN) {
688 continue;
690 names[total_names] = fill_domain_username_talloc(names,
691 domain->name,
692 tmp_names.names[r].string,
693 true);
694 name_types[total_names] = tmp_types.ids[r];
695 total_names++;
698 if (pnum_names) {
699 *pnum_names = total_names;
702 if (pnames) {
703 *pnames = talloc_move(mem_ctx, &names);
706 if (pname_types) {
707 *pname_types = talloc_move(mem_ctx, &name_types);
710 if (psid_mem) {
711 *psid_mem = talloc_move(mem_ctx, &sid_mem);
714 error:
715 TALLOC_FREE(tmp_ctx);
716 return status;
719 /*********************************************************************
720 BUILTIN specific functions.
721 *********************************************************************/
723 /* List all domain groups */
724 static NTSTATUS builtin_enum_dom_groups(struct winbindd_domain *domain,
725 TALLOC_CTX *mem_ctx,
726 uint32 *num_entries,
727 struct acct_info **info)
729 /* BUILTIN doesn't have domain groups */
730 *num_entries = 0;
731 *info = NULL;
732 return NT_STATUS_OK;
735 /* Query display info for a domain */
736 static NTSTATUS builtin_query_user_list(struct winbindd_domain *domain,
737 TALLOC_CTX *mem_ctx,
738 uint32 *num_entries,
739 struct wbint_userinfo **info)
741 /* We don't have users */
742 *num_entries = 0;
743 *info = NULL;
744 return NT_STATUS_OK;
747 /* Lookup user information from a rid or username. */
748 static NTSTATUS builtin_query_user(struct winbindd_domain *domain,
749 TALLOC_CTX *mem_ctx,
750 const struct dom_sid *user_sid,
751 struct wbint_userinfo *user_info)
753 return NT_STATUS_NO_SUCH_USER;
756 /* get a list of trusted domains - builtin domain */
757 static NTSTATUS builtin_trusted_domains(struct winbindd_domain *domain,
758 TALLOC_CTX *mem_ctx,
759 struct netr_DomainTrustList *trusts)
761 ZERO_STRUCTP(trusts);
762 return NT_STATUS_OK;
765 /*********************************************************************
766 COMMON functions.
767 *********************************************************************/
769 /* List all local groups (aliases) */
770 static NTSTATUS common_enum_local_groups(struct winbindd_domain *domain,
771 TALLOC_CTX *mem_ctx,
772 uint32_t *pnum_info,
773 struct acct_info **pinfo)
775 struct rpc_pipe_client *samr_pipe;
776 struct policy_handle dom_pol;
777 struct acct_info *info = NULL;
778 uint32_t num_info = 0;
779 TALLOC_CTX *tmp_ctx;
780 NTSTATUS status;
782 DEBUG(3,("samr: enum local groups\n"));
784 if (pnum_info) {
785 *pnum_info = 0;
788 tmp_ctx = talloc_stackframe();
789 if (tmp_ctx == NULL) {
790 return NT_STATUS_NO_MEMORY;
793 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
794 if (!NT_STATUS_IS_OK(status)) {
795 goto error;
798 do {
799 struct samr_SamArray *sam_array = NULL;
800 uint32_t count = 0;
801 uint32_t start = num_info;
802 uint32_t g;
804 status = rpccli_samr_EnumDomainAliases(samr_pipe,
805 tmp_ctx,
806 &dom_pol,
807 &start,
808 &sam_array,
809 0xFFFF, /* buffer size? */
810 &count);
811 if (!NT_STATUS_IS_OK(status)) {
812 if (!NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
813 goto error;
817 info = TALLOC_REALLOC_ARRAY(tmp_ctx,
818 info,
819 struct acct_info,
820 num_info + count);
821 if (info == NULL) {
822 status = NT_STATUS_NO_MEMORY;
823 goto error;
826 for (g = 0; g < count; g++) {
827 fstrcpy(info[num_info + g].acct_name,
828 sam_array->entries[g].name.string);
829 info[num_info + g].rid = sam_array->entries[g].idx;
832 num_info += count;
833 } while (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES));
835 if (pnum_info) {
836 *pnum_info = num_info;
839 if (pinfo) {
840 *pinfo = talloc_move(mem_ctx, &info);
843 error:
844 TALLOC_FREE(tmp_ctx);
845 return status;
848 /* convert a single name to a sid in a domain */
849 static NTSTATUS common_name_to_sid(struct winbindd_domain *domain,
850 TALLOC_CTX *mem_ctx,
851 const char *domain_name,
852 const char *name,
853 uint32_t flags,
854 struct dom_sid *sid,
855 enum lsa_SidType *type)
857 struct rpc_pipe_client *lsa_pipe;
858 struct policy_handle lsa_policy;
859 enum lsa_SidType *types = NULL;
860 struct dom_sid *sids = NULL;
861 char *full_name = NULL;
862 char *mapped_name = NULL;
863 TALLOC_CTX *tmp_ctx;
864 NTSTATUS status;
866 DEBUG(3,("samr: name to sid\n"));
868 tmp_ctx = talloc_stackframe();
869 if (tmp_ctx == NULL) {
870 return NT_STATUS_NO_MEMORY;
873 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
874 if (!NT_STATUS_IS_OK(status)) {
875 goto error;
878 if (name == NULL || name[0] == '\0') {
879 full_name = talloc_asprintf(tmp_ctx, "%s", domain_name);
880 } else if (domain_name == NULL || domain_name[0] == '\0') {
881 full_name = talloc_asprintf(tmp_ctx, "%s", name);
882 } else {
883 full_name = talloc_asprintf(tmp_ctx, "%s\\%s", domain_name, name);
886 if (full_name == NULL) {
887 status = NT_STATUS_NO_MEMORY;
890 status = normalize_name_unmap(tmp_ctx, full_name, &mapped_name);
891 /* Reset the full_name pointer if we mapped anything */
892 if (NT_STATUS_IS_OK(status) ||
893 NT_STATUS_EQUAL(status, NT_STATUS_FILE_RENAMED)) {
894 full_name = mapped_name;
897 DEBUG(3,("name_to_sid: %s for domain %s\n",
898 full_name ? full_name : "", domain_name ));
901 * We don't run into deadlocks here, cause winbind_off() is
902 * called in the main function.
904 status = rpccli_lsa_lookup_names(lsa_pipe,
905 tmp_ctx,
906 &lsa_policy,
907 1, /* num_names */
908 (const char **) &full_name,
909 NULL, /* domains */
910 1, /* level */
911 &sids,
912 &types);
913 if (!NT_STATUS_IS_OK(status)) {
914 DEBUG(2,("name_to_sid: failed to lookup name: %s\n",
915 nt_errstr(status)));
916 goto error;
919 if (sid) {
920 sid_copy(sid, &sids[0]);
922 if (type) {
923 *type = types[0];
926 error:
927 TALLOC_FREE(tmp_ctx);
928 return status;
931 /* convert a domain SID to a user or group name */
932 static NTSTATUS common_sid_to_name(struct winbindd_domain *domain,
933 TALLOC_CTX *mem_ctx,
934 const struct dom_sid *sid,
935 char **domain_name,
936 char **name,
937 enum lsa_SidType *type)
939 struct rpc_pipe_client *lsa_pipe;
940 struct policy_handle lsa_policy;
941 char *mapped_name = NULL;
942 char **domains = NULL;
943 char **names = NULL;
944 enum lsa_SidType *types = NULL;
945 TALLOC_CTX *tmp_ctx;
946 NTSTATUS map_status;
947 NTSTATUS status;
949 DEBUG(3,("samr: sid to name\n"));
951 tmp_ctx = talloc_stackframe();
952 if (tmp_ctx == NULL) {
953 return NT_STATUS_NO_MEMORY;
956 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
957 if (!NT_STATUS_IS_OK(status)) {
958 goto error;
962 * We don't run into deadlocks here, cause winbind_off() is called in
963 * the main function.
965 status = rpccli_lsa_lookup_sids(lsa_pipe,
966 tmp_ctx,
967 &lsa_policy,
968 1, /* num_sids */
969 sid,
970 &domains,
971 &names,
972 &types);
973 if (!NT_STATUS_IS_OK(status)) {
974 DEBUG(2,("sid_to_name: failed to lookup sids: %s\n",
975 nt_errstr(status)));
976 goto error;
979 if (type) {
980 *type = (enum lsa_SidType) types[0];
983 if (name) {
984 map_status = normalize_name_map(tmp_ctx,
985 domain,
986 *name,
987 &mapped_name);
988 if (NT_STATUS_IS_OK(map_status) ||
989 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
990 *name = talloc_strdup(mem_ctx, mapped_name);
991 DEBUG(5,("returning mapped name -- %s\n", *name));
992 } else {
993 *name = talloc_strdup(mem_ctx, names[0]);
995 if (*name == NULL) {
996 status = NT_STATUS_NO_MEMORY;
997 goto error;
1001 if (domain_name) {
1002 *domain_name = talloc_strdup(mem_ctx, domains[0]);
1003 if (*domain_name == NULL) {
1004 status = NT_STATUS_NO_MEMORY;
1005 goto error;
1009 error:
1010 TALLOC_FREE(tmp_ctx);
1011 return status;
1014 static NTSTATUS common_rids_to_names(struct winbindd_domain *domain,
1015 TALLOC_CTX *mem_ctx,
1016 const struct dom_sid *sid,
1017 uint32 *rids,
1018 size_t num_rids,
1019 char **pdomain_name,
1020 char ***pnames,
1021 enum lsa_SidType **ptypes)
1023 struct rpc_pipe_client *lsa_pipe;
1024 struct policy_handle lsa_policy;
1025 enum lsa_SidType *types = NULL;
1026 char *domain_name = NULL;
1027 char **domains = NULL;
1028 char **names = NULL;
1029 struct dom_sid *sids;
1030 size_t i;
1031 TALLOC_CTX *tmp_ctx;
1032 NTSTATUS status;
1034 DEBUG(3,("samr: rids to names for domain %s\n", domain->name));
1036 tmp_ctx = talloc_stackframe();
1037 if (tmp_ctx == NULL) {
1038 return NT_STATUS_NO_MEMORY;
1041 status = open_internal_lsa_conn(tmp_ctx, &lsa_pipe, &lsa_policy);
1042 if (!NT_STATUS_IS_OK(status)) {
1043 goto error;
1046 if (num_rids) {
1047 sids = TALLOC_ARRAY(tmp_ctx, struct dom_sid, num_rids);
1048 if (sids == NULL) {
1049 status = NT_STATUS_NO_MEMORY;
1050 goto error;
1052 } else {
1053 sids = NULL;
1056 for (i = 0; i < num_rids; i++) {
1057 if (!sid_compose(&sids[i], sid, rids[i])) {
1058 status = NT_STATUS_INTERNAL_ERROR;
1059 goto error;
1064 * We don't run into deadlocks here, cause winbind_off() is called in
1065 * the main function.
1067 status = rpccli_lsa_lookup_sids(lsa_pipe,
1068 tmp_ctx,
1069 &lsa_policy,
1070 num_rids,
1071 sids,
1072 &domains,
1073 &names,
1074 &types);
1075 if (!NT_STATUS_IS_OK(status) &&
1076 !NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED)) {
1077 DEBUG(2,("rids_to_names: failed to lookup sids: %s\n",
1078 nt_errstr(status)));
1079 goto error;
1082 for (i = 0; i < num_rids; i++) {
1083 char *mapped_name = NULL;
1084 NTSTATUS map_status;
1086 if (types[i] != SID_NAME_UNKNOWN) {
1087 map_status = normalize_name_map(tmp_ctx,
1088 domain,
1089 names[i],
1090 &mapped_name);
1091 if (NT_STATUS_IS_OK(map_status) ||
1092 NT_STATUS_EQUAL(map_status, NT_STATUS_FILE_RENAMED)) {
1093 TALLOC_FREE(names[i]);
1094 names[i] = talloc_strdup(names, mapped_name);
1095 if (names[i] == NULL) {
1096 status = NT_STATUS_NO_MEMORY;
1097 goto error;
1101 domain_name = domains[i];
1105 if (pdomain_name) {
1106 *pdomain_name = talloc_strdup(mem_ctx, domain_name);
1107 if (*pdomain_name == NULL) {
1108 status = NT_STATUS_NO_MEMORY;
1109 goto error;
1113 if (ptypes) {
1114 *ptypes = talloc_move(mem_ctx, &types);
1117 if (pnames) {
1118 *pnames = talloc_move(mem_ctx, &names);
1121 error:
1122 TALLOC_FREE(tmp_ctx);
1123 return status;
1126 static NTSTATUS common_lockout_policy(struct winbindd_domain *domain,
1127 TALLOC_CTX *mem_ctx,
1128 struct samr_DomInfo12 *lockout_policy)
1130 struct rpc_pipe_client *samr_pipe;
1131 struct policy_handle dom_pol;
1132 union samr_DomainInfo *info = NULL;
1133 TALLOC_CTX *tmp_ctx;
1134 NTSTATUS status;
1136 DEBUG(3,("samr: lockout policy\n"));
1138 tmp_ctx = talloc_stackframe();
1139 if (tmp_ctx == NULL) {
1140 return NT_STATUS_NO_MEMORY;
1143 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
1144 if (!NT_STATUS_IS_OK(status)) {
1145 goto error;
1148 status = rpccli_samr_QueryDomainInfo(samr_pipe,
1149 mem_ctx,
1150 &dom_pol,
1152 &info);
1153 if (!NT_STATUS_IS_OK(status)) {
1154 goto error;
1157 *lockout_policy = info->info12;
1159 error:
1160 TALLOC_FREE(tmp_ctx);
1161 return status;
1164 static NTSTATUS common_password_policy(struct winbindd_domain *domain,
1165 TALLOC_CTX *mem_ctx,
1166 struct samr_DomInfo1 *passwd_policy)
1168 struct rpc_pipe_client *samr_pipe;
1169 struct policy_handle dom_pol;
1170 union samr_DomainInfo *info = NULL;
1171 TALLOC_CTX *tmp_ctx;
1172 NTSTATUS status;
1174 DEBUG(3,("samr: password policy\n"));
1176 tmp_ctx = talloc_stackframe();
1177 if (tmp_ctx == NULL) {
1178 return NT_STATUS_NO_MEMORY;
1181 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
1182 if (!NT_STATUS_IS_OK(status)) {
1183 goto error;
1186 status = rpccli_samr_QueryDomainInfo(samr_pipe,
1187 mem_ctx,
1188 &dom_pol,
1190 &info);
1191 if (!NT_STATUS_IS_OK(status)) {
1192 goto error;
1195 *passwd_policy = info->info1;
1197 error:
1198 TALLOC_FREE(tmp_ctx);
1199 return status;
1202 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
1203 static NTSTATUS common_lookup_usergroups(struct winbindd_domain *domain,
1204 TALLOC_CTX *mem_ctx,
1205 const struct dom_sid *user_sid,
1206 uint32_t *pnum_groups,
1207 struct dom_sid **puser_grpsids)
1209 struct rpc_pipe_client *samr_pipe;
1210 struct policy_handle dom_pol, usr_pol;
1211 uint32_t samr_access = SEC_FLAG_MAXIMUM_ALLOWED;
1212 struct samr_RidWithAttributeArray *rid_array = NULL;
1213 struct dom_sid *user_grpsids = NULL;
1214 uint32_t num_groups = 0, i;
1215 uint32_t user_rid;
1216 TALLOC_CTX *tmp_ctx;
1217 NTSTATUS status;
1219 DEBUG(3,("samr: lookup usergroups\n"));
1221 if (!sid_peek_check_rid(&domain->sid, user_sid, &user_rid)) {
1222 return NT_STATUS_UNSUCCESSFUL;
1225 if (pnum_groups) {
1226 *pnum_groups = 0;
1229 if (puser_grpsids) {
1230 *puser_grpsids = NULL;
1233 tmp_ctx = talloc_stackframe();
1234 if (tmp_ctx == NULL) {
1235 return NT_STATUS_NO_MEMORY;
1238 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
1239 if (!NT_STATUS_IS_OK(status)) {
1240 goto error;
1243 /* Get user handle */
1244 status = rpccli_samr_OpenUser(samr_pipe,
1245 tmp_ctx,
1246 &dom_pol,
1247 samr_access,
1248 user_rid,
1249 &usr_pol);
1250 if (!NT_STATUS_IS_OK(status)) {
1251 return status;
1254 /* Query user rids */
1255 status = rpccli_samr_GetGroupsForUser(samr_pipe,
1256 tmp_ctx,
1257 &usr_pol,
1258 &rid_array);
1259 num_groups = rid_array->count;
1261 rpccli_samr_Close(samr_pipe, tmp_ctx, &usr_pol);
1263 if (!NT_STATUS_IS_OK(status) || num_groups == 0) {
1264 return status;
1267 user_grpsids = TALLOC_ARRAY(tmp_ctx, struct dom_sid, num_groups);
1268 if (user_grpsids == NULL) {
1269 status = NT_STATUS_NO_MEMORY;
1270 goto error;
1273 for (i = 0; i < num_groups; i++) {
1274 sid_compose(&(user_grpsids[i]), &domain->sid,
1275 rid_array->rids[i].rid);
1278 if (pnum_groups) {
1279 *pnum_groups = num_groups;
1282 if (puser_grpsids) {
1283 *puser_grpsids = talloc_move(mem_ctx, &user_grpsids);
1286 error:
1287 TALLOC_FREE(tmp_ctx);
1288 return status;
1291 static NTSTATUS common_lookup_useraliases(struct winbindd_domain *domain,
1292 TALLOC_CTX *mem_ctx,
1293 uint32_t num_sids,
1294 const struct dom_sid *sids,
1295 uint32_t *pnum_aliases,
1296 uint32_t **palias_rids)
1298 #define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
1299 struct rpc_pipe_client *samr_pipe;
1300 struct policy_handle dom_pol;
1301 uint32_t num_query_sids = 0;
1302 uint32_t num_queries = 1;
1303 uint32_t num_aliases = 0;
1304 uint32_t total_sids = 0;
1305 uint32_t rangesize = MAX_SAM_ENTRIES_W2K;
1306 uint32_t i;
1307 struct samr_Ids alias_rids_query;
1308 TALLOC_CTX *tmp_ctx;
1309 NTSTATUS status;
1311 DEBUG(3,("samr: lookup useraliases\n"));
1313 if (pnum_aliases) {
1314 *pnum_aliases = 0;
1317 if (palias_rids) {
1318 *palias_rids = NULL;
1321 tmp_ctx = talloc_stackframe();
1322 if (tmp_ctx == NULL) {
1323 return NT_STATUS_NO_MEMORY;
1326 status = open_internal_samr_conn(tmp_ctx, domain, &samr_pipe, &dom_pol);
1327 if (!NT_STATUS_IS_OK(status)) {
1328 goto error;
1331 do {
1332 /* prepare query */
1333 struct lsa_SidArray sid_array;
1335 ZERO_STRUCT(sid_array);
1337 num_query_sids = MIN(num_sids - total_sids, rangesize);
1339 DEBUG(10,("rpc: lookup_useraliases: entering query %d for %d sids\n",
1340 num_queries, num_query_sids));
1342 if (num_query_sids) {
1343 sid_array.sids = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_SidPtr, num_query_sids);
1344 if (sid_array.sids == NULL) {
1345 status = NT_STATUS_NO_MEMORY;
1346 goto error;
1348 } else {
1349 sid_array.sids = NULL;
1352 for (i = 0; i < num_query_sids; i++) {
1353 sid_array.sids[i].sid = sid_dup_talloc(tmp_ctx, &sids[total_sids++]);
1354 if (sid_array.sids[i].sid == NULL) {
1355 status = NT_STATUS_NO_MEMORY;
1356 goto error;
1359 sid_array.num_sids = num_query_sids;
1361 /* do request */
1362 status = rpccli_samr_GetAliasMembership(samr_pipe,
1363 tmp_ctx,
1364 &dom_pol,
1365 &sid_array,
1366 &alias_rids_query);
1367 if (!NT_STATUS_IS_OK(status)) {
1368 goto error;
1371 if (palias_rids) {
1372 /* process output */
1373 for (i = 0; i < alias_rids_query.count; i++) {
1374 size_t na = num_aliases;
1376 if (!add_rid_to_array_unique(mem_ctx,
1377 alias_rids_query.ids[i],
1378 palias_rids,
1379 &na)) {
1380 status = NT_STATUS_NO_MEMORY;
1381 goto error;
1383 num_aliases = na;
1387 num_queries++;
1389 } while (total_sids < num_sids);
1391 if (pnum_aliases) {
1392 *pnum_aliases = num_aliases;
1395 error:
1396 TALLOC_FREE(tmp_ctx);
1397 return status;
1398 #undef MAX_SAM_ENTRIES_W2K
1401 /* find the sequence number for a domain */
1402 static NTSTATUS common_sequence_number(struct winbindd_domain *domain,
1403 uint32_t *seq)
1405 /* TODO FIXME */
1406 return NT_STATUS_NOT_IMPLEMENTED;
1409 #if 0
1410 /* the rpc backend methods are exposed via this structure */
1411 struct winbindd_methods builtin_passdb_methods = {
1412 .consistent = false,
1414 .query_user_list = builtin_query_user_list,
1415 .enum_dom_groups = builtin_enum_dom_groups,
1416 .enum_local_groups = common_enum_local_groups,
1417 .name_to_sid = common_name_to_sid,
1418 .sid_to_name = common_sid_to_name,
1419 .rids_to_names = common_rids_to_names,
1420 .query_user = builtin_query_user,
1421 .lookup_usergroups = common_lookup_usergroups,
1422 .lookup_useraliases = common_lookup_useraliases,
1423 .lookup_groupmem = sam_lookup_groupmem,
1424 .sequence_number = common_sequence_number,
1425 .lockout_policy = common_lockout_policy,
1426 .password_policy = common_password_policy,
1427 .trusted_domains = builtin_trusted_domains
1430 /* the rpc backend methods are exposed via this structure */
1431 struct winbindd_methods sam_passdb_methods = {
1432 .consistent = false,
1434 .query_user_list = sam_query_user_list,
1435 .enum_dom_groups = sam_enum_dom_groups,
1436 .enum_local_groups = common_enum_local_groups,
1437 .name_to_sid = common_name_to_sid,
1438 .sid_to_name = common_sid_to_name,
1439 .rids_to_names = common_rids_to_names,
1440 .query_user = sam_query_user,
1441 .lookup_usergroups = common_lookup_usergroups,
1442 .lookup_useraliases = common_lookup_useraliases,
1443 .lookup_groupmem = sam_lookup_groupmem,
1444 .sequence_number = common_sequence_number,
1445 .lockout_policy = common_lockout_policy,
1446 .password_policy = common_password_policy,
1447 .trusted_domains = sam_trusted_domains
1449 #endif