2 Unix SMB/CIFS implementation.
4 Winbind rpc backend functions
6 Copyright (C) Tim Potter 2000-2001,2003
7 Copyright (C) Andrew Tridgell 2001
8 Copyright (C) Volker Lendecke 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #define DBGC_CLASS DBGC_WINBIND
32 /* Query display info for a domain. This returns enough information plus a
33 bit extra to give an overview of domain users for the User Manager
35 static NTSTATUS
query_user_list(struct winbindd_domain
*domain
,
38 WINBIND_USERINFO
**info
)
42 unsigned int i
, start_idx
;
44 struct rpc_pipe_client
*cli
;
46 DEBUG(3,("rpc: query_user_list\n"));
51 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
52 if (!NT_STATUS_IS_OK(result
))
60 uint32 num_dom_users
, j
;
61 uint32 max_entries
, max_size
;
67 ctr
.sam
.info1
= &info1
;
69 if (!(ctx2
= talloc_init("winbindd enum_users")))
70 return NT_STATUS_NO_MEMORY
;
72 /* this next bit is copied from net_user_list_internal() */
74 get_query_dispinfo_params(loop_count
, &max_entries
,
77 result
= rpccli_samr_query_dispinfo(cli
, mem_ctx
, &dom_pol
,
80 max_entries
, max_size
,
85 *num_entries
+= num_dom_users
;
87 *info
= TALLOC_REALLOC_ARRAY(mem_ctx
, *info
, WINBIND_USERINFO
,
92 return NT_STATUS_NO_MEMORY
;
95 for (j
= 0; j
< num_dom_users
; i
++, j
++) {
96 fstring username
, fullname
;
97 uint32 rid
= ctr
.sam
.info1
->sam
[j
].rid_user
;
99 unistr2_to_ascii( username
, &(&ctr
.sam
.info1
->str
[j
])->uni_acct_name
, sizeof(username
)-1);
100 unistr2_to_ascii( fullname
, &(&ctr
.sam
.info1
->str
[j
])->uni_full_name
, sizeof(fullname
)-1);
102 (*info
)[i
].acct_name
= talloc_strdup(mem_ctx
, username
);
103 (*info
)[i
].full_name
= talloc_strdup(mem_ctx
, fullname
);
104 sid_compose(&(*info
)[i
].user_sid
, &domain
->sid
, rid
);
106 /* For the moment we set the primary group for
107 every user to be the Domain Users group.
108 There are serious problems with determining
109 the actual primary group for large domains.
110 This should really be made into a 'winbind
111 force group' smb.conf parameter or
112 something like that. */
114 sid_compose(&(*info
)[i
].group_sid
, &domain
->sid
,
115 DOMAIN_GROUP_RID_USERS
);
118 talloc_destroy(ctx2
);
120 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
125 /* list all domain groups */
126 static NTSTATUS
enum_dom_groups(struct winbindd_domain
*domain
,
129 struct acct_info
**info
)
134 struct rpc_pipe_client
*cli
;
139 DEBUG(3,("rpc: enum_dom_groups\n"));
141 status
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
142 if (!NT_STATUS_IS_OK(status
))
146 struct acct_info
*info2
= NULL
;
148 TALLOC_CTX
*mem_ctx2
;
150 mem_ctx2
= talloc_init("enum_dom_groups[rpc]");
152 /* start is updated by this call. */
153 status
= rpccli_samr_enum_dom_groups(cli
, mem_ctx2
, &dom_pol
,
155 0xFFFF, /* buffer size? */
158 if (!NT_STATUS_IS_OK(status
) &&
159 !NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
)) {
160 talloc_destroy(mem_ctx2
);
164 (*info
) = TALLOC_REALLOC_ARRAY(mem_ctx
, *info
,
166 (*num_entries
) + count
);
168 talloc_destroy(mem_ctx2
);
169 status
= NT_STATUS_NO_MEMORY
;
173 memcpy(&(*info
)[*num_entries
], info2
, count
*sizeof(*info2
));
174 (*num_entries
) += count
;
175 talloc_destroy(mem_ctx2
);
176 } while (NT_STATUS_EQUAL(status
, STATUS_MORE_ENTRIES
));
181 /* List all domain groups */
183 static NTSTATUS
enum_local_groups(struct winbindd_domain
*domain
,
186 struct acct_info
**info
)
190 struct rpc_pipe_client
*cli
;
195 DEBUG(3,("rpc: enum_local_groups\n"));
197 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
198 if (!NT_STATUS_IS_OK(result
))
202 struct acct_info
*info2
= NULL
;
203 uint32 count
= 0, start
= *num_entries
;
204 TALLOC_CTX
*mem_ctx2
;
206 mem_ctx2
= talloc_init("enum_dom_local_groups[rpc]");
208 result
= rpccli_samr_enum_als_groups( cli
, mem_ctx2
, &dom_pol
,
209 &start
, 0xFFFF, &info2
,
212 if (!NT_STATUS_IS_OK(result
) &&
213 !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
) )
215 talloc_destroy(mem_ctx2
);
219 (*info
) = TALLOC_REALLOC_ARRAY(mem_ctx
, *info
,
221 (*num_entries
) + count
);
223 talloc_destroy(mem_ctx2
);
224 return NT_STATUS_NO_MEMORY
;
227 memcpy(&(*info
)[*num_entries
], info2
, count
*sizeof(*info2
));
228 (*num_entries
) += count
;
229 talloc_destroy(mem_ctx2
);
231 } while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
));
236 /* convert a single name to a sid in a domain */
237 NTSTATUS
msrpc_name_to_sid(struct winbindd_domain
*domain
,
239 const char *domain_name
,
242 enum SID_NAME_USE
*type
)
245 DOM_SID
*sids
= NULL
;
246 uint32
*types
= NULL
;
247 const char *full_name
;
248 struct rpc_pipe_client
*cli
;
249 POLICY_HND lsa_policy
;
251 if(name
== NULL
|| *name
=='\0') {
252 DEBUG(3,("rpc: name_to_sid name=%s\n", domain_name
));
253 full_name
= talloc_asprintf(mem_ctx
, "%s", domain_name
);
255 DEBUG(3,("rpc: name_to_sid name=%s\\%s\n", domain_name
, name
));
256 full_name
= talloc_asprintf(mem_ctx
, "%s\\%s", domain_name
, name
);
259 DEBUG(0, ("talloc_asprintf failed!\n"));
260 return NT_STATUS_NO_MEMORY
;
263 DEBUG(3,("name_to_sid [rpc] %s for domain %s\n", name
?name
:"", domain_name
));
265 result
= cm_connect_lsa(domain
, mem_ctx
, &cli
, &lsa_policy
);
266 if (!NT_STATUS_IS_OK(result
))
269 result
= rpccli_lsa_lookup_names(cli
, mem_ctx
, &lsa_policy
, 1,
270 &full_name
, &sids
, &types
);
272 if (!NT_STATUS_IS_OK(result
))
275 /* Return rid and type if lookup successful */
277 sid_copy(sid
, &sids
[0]);
278 *type
= (enum SID_NAME_USE
)types
[0];
284 convert a domain SID to a user or group name
286 NTSTATUS
msrpc_sid_to_name(struct winbindd_domain
*domain
,
291 enum SID_NAME_USE
*type
)
297 struct rpc_pipe_client
*cli
;
298 POLICY_HND lsa_policy
;
300 DEBUG(3,("sid_to_name [rpc] %s for domain %s\n", sid_string_static(sid
),
303 result
= cm_connect_lsa(domain
, mem_ctx
, &cli
, &lsa_policy
);
304 if (!NT_STATUS_IS_OK(result
))
307 result
= rpccli_lsa_lookup_sids(cli
, mem_ctx
, &lsa_policy
,
308 1, sid
, &domains
, &names
, &types
);
309 if (!NT_STATUS_IS_OK(result
))
312 *type
= (enum SID_NAME_USE
)types
[0];
313 *domain_name
= domains
[0];
315 DEBUG(5,("Mapped sid to [%s]\\[%s]\n", domains
[0], *name
));
319 /* Lookup user information from a rid or username. */
320 static NTSTATUS
query_user(struct winbindd_domain
*domain
,
322 const DOM_SID
*user_sid
,
323 WINBIND_USERINFO
*user_info
)
325 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
326 POLICY_HND dom_pol
, user_pol
;
327 SAM_USERINFO_CTR
*ctr
;
330 NET_USER_INFO_3
*user
;
331 struct rpc_pipe_client
*cli
;
333 DEBUG(3,("rpc: query_user rid=%s\n",
334 sid_to_string(sid_string
, user_sid
)));
336 if (!sid_peek_check_rid(&domain
->sid
, user_sid
, &user_rid
))
337 return NT_STATUS_UNSUCCESSFUL
;
339 /* try netsamlogon cache first */
341 if ( (user
= netsamlogon_cache_get( mem_ctx
, user_sid
)) != NULL
)
344 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
345 sid_string_static(user_sid
)));
347 sid_compose(&user_info
->user_sid
, &domain
->sid
, user_rid
);
348 sid_compose(&user_info
->group_sid
, &domain
->sid
,
351 user_info
->acct_name
= unistr2_tdup(mem_ctx
,
352 &user
->uni_user_name
);
353 user_info
->full_name
= unistr2_tdup(mem_ctx
,
354 &user
->uni_full_name
);
361 /* no cache; hit the wire */
363 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
364 if (!NT_STATUS_IS_OK(result
))
367 /* Get user handle */
368 result
= rpccli_samr_open_user(cli
, mem_ctx
, &dom_pol
,
369 SEC_RIGHTS_MAXIMUM_ALLOWED
, user_rid
,
372 if (!NT_STATUS_IS_OK(result
))
376 result
= rpccli_samr_query_userinfo(cli
, mem_ctx
, &user_pol
,
379 rpccli_samr_close(cli
, mem_ctx
, &user_pol
);
381 if (!NT_STATUS_IS_OK(result
))
384 sid_compose(&user_info
->user_sid
, &domain
->sid
, user_rid
);
385 sid_compose(&user_info
->group_sid
, &domain
->sid
,
386 ctr
->info
.id21
->group_rid
);
387 user_info
->acct_name
= unistr2_tdup(mem_ctx
,
388 &ctr
->info
.id21
->uni_user_name
);
389 user_info
->full_name
= unistr2_tdup(mem_ctx
,
390 &ctr
->info
.id21
->uni_full_name
);
395 /* Lookup groups a user is a member of. I wish Unix had a call like this! */
396 static NTSTATUS
lookup_usergroups(struct winbindd_domain
*domain
,
398 const DOM_SID
*user_sid
,
399 uint32
*num_groups
, DOM_SID
**user_grpsids
)
401 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
402 POLICY_HND dom_pol
, user_pol
;
403 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
404 DOM_GID
*user_groups
;
408 NET_USER_INFO_3
*user
;
409 struct rpc_pipe_client
*cli
;
411 DEBUG(3,("rpc: lookup_usergroups sid=%s\n",
412 sid_to_string(sid_string
, user_sid
)));
414 if (!sid_peek_check_rid(&domain
->sid
, user_sid
, &user_rid
))
415 return NT_STATUS_UNSUCCESSFUL
;
418 *user_grpsids
= NULL
;
420 /* so lets see if we have a cached user_info_3 */
422 if ( (user
= netsamlogon_cache_get( mem_ctx
, user_sid
)) != NULL
)
424 DEBUG(5,("query_user: Cache lookup succeeded for %s\n",
425 sid_string_static(user_sid
)));
427 *num_groups
= user
->num_groups
;
429 (*user_grpsids
) = TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_groups
);
430 for (i
=0;i
<(*num_groups
);i
++) {
431 sid_copy(&((*user_grpsids
)[i
]), &domain
->sid
);
432 sid_append_rid(&((*user_grpsids
)[i
]),
433 user
->gids
[i
].g_rid
);
441 /* no cache; hit the wire */
443 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
444 if (!NT_STATUS_IS_OK(result
))
447 /* Get user handle */
448 result
= rpccli_samr_open_user(cli
, mem_ctx
, &dom_pol
,
449 des_access
, user_rid
, &user_pol
);
451 if (!NT_STATUS_IS_OK(result
))
454 /* Query user rids */
455 result
= rpccli_samr_query_usergroups(cli
, mem_ctx
, &user_pol
,
456 num_groups
, &user_groups
);
458 rpccli_samr_close(cli
, mem_ctx
, &user_pol
);
460 if (!NT_STATUS_IS_OK(result
) || (*num_groups
) == 0)
463 (*user_grpsids
) = TALLOC_ARRAY(mem_ctx
, DOM_SID
, *num_groups
);
464 if (!(*user_grpsids
))
465 return NT_STATUS_NO_MEMORY
;
467 for (i
=0;i
<(*num_groups
);i
++) {
468 sid_copy(&((*user_grpsids
)[i
]), &domain
->sid
);
469 sid_append_rid(&((*user_grpsids
)[i
]),
470 user_groups
[i
].g_rid
);
476 NTSTATUS
msrpc_lookup_useraliases(struct winbindd_domain
*domain
,
478 uint32 num_sids
, const DOM_SID
*sids
,
479 uint32
*num_aliases
, uint32
**alias_rids
)
481 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
485 struct rpc_pipe_client
*cli
;
490 DEBUG(3,("rpc: lookup_useraliases\n"));
492 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
493 if (!NT_STATUS_IS_OK(result
))
496 sid2
= TALLOC_ARRAY(mem_ctx
, DOM_SID2
, num_sids
);
499 return NT_STATUS_NO_MEMORY
;
501 for (i
=0; i
<num_sids
; i
++) {
502 sid_copy(&sid2
[i
].sid
, &sids
[i
]);
503 sid2
[i
].num_auths
= sid2
[i
].sid
.num_auths
;
506 result
= rpccli_samr_query_useraliases(cli
, mem_ctx
, &dom_pol
,
508 num_aliases
, alias_rids
);
514 /* Lookup group membership given a rid. */
515 static NTSTATUS
lookup_groupmem(struct winbindd_domain
*domain
,
517 const DOM_SID
*group_sid
, uint32
*num_names
,
518 DOM_SID
**sid_mem
, char ***names
,
521 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
522 uint32 i
, total_names
= 0;
523 POLICY_HND dom_pol
, group_pol
;
524 uint32 des_access
= SEC_RIGHTS_MAXIMUM_ALLOWED
;
525 uint32
*rid_mem
= NULL
;
529 struct rpc_pipe_client
*cli
;
531 DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain
->name
,
532 sid_to_string(sid_string
, group_sid
)));
534 if (!sid_peek_check_rid(&domain
->sid
, group_sid
, &group_rid
))
535 return NT_STATUS_UNSUCCESSFUL
;
539 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
540 if (!NT_STATUS_IS_OK(result
))
543 result
= rpccli_samr_open_group(cli
, mem_ctx
, &dom_pol
,
544 des_access
, group_rid
, &group_pol
);
546 if (!NT_STATUS_IS_OK(result
))
549 /* Step #1: Get a list of user rids that are the members of the
552 result
= rpccli_samr_query_groupmem(cli
, mem_ctx
,
553 &group_pol
, num_names
, &rid_mem
,
556 rpccli_samr_close(cli
, mem_ctx
, &group_pol
);
558 if (!NT_STATUS_IS_OK(result
))
568 /* Step #2: Convert list of rids into list of usernames. Do this
569 in bunches of ~1000 to avoid crashing NT4. It looks like there
570 is a buffer overflow or something like that lurking around
573 #define MAX_LOOKUP_RIDS 900
575 *names
= TALLOC_ZERO_ARRAY(mem_ctx
, char *, *num_names
);
576 *name_types
= TALLOC_ZERO_ARRAY(mem_ctx
, uint32
, *num_names
);
577 *sid_mem
= TALLOC_ZERO_ARRAY(mem_ctx
, DOM_SID
, *num_names
);
579 for (j
=0;j
<(*num_names
);j
++)
580 sid_compose(&(*sid_mem
)[j
], &domain
->sid
, rid_mem
[j
]);
582 if (*num_names
>0 && (!*names
|| !*name_types
))
583 return NT_STATUS_NO_MEMORY
;
585 for (i
= 0; i
< *num_names
; i
+= MAX_LOOKUP_RIDS
) {
586 int num_lookup_rids
= MIN(*num_names
- i
, MAX_LOOKUP_RIDS
);
587 uint32 tmp_num_names
= 0;
588 char **tmp_names
= NULL
;
589 uint32
*tmp_types
= NULL
;
591 /* Lookup a chunk of rids */
593 result
= rpccli_samr_lookup_rids(cli
, mem_ctx
,
598 &tmp_names
, &tmp_types
);
600 /* see if we have a real error (and yes the
601 STATUS_SOME_UNMAPPED is the one returned from 2k) */
603 if (!NT_STATUS_IS_OK(result
) &&
604 !NT_STATUS_EQUAL(result
, STATUS_SOME_UNMAPPED
))
607 /* Copy result into array. The talloc system will take
608 care of freeing the temporary arrays later on. */
610 memcpy(&(*names
)[i
], tmp_names
, sizeof(char *) *
613 memcpy(&(*name_types
)[i
], tmp_types
, sizeof(uint32
) *
616 total_names
+= tmp_num_names
;
619 *num_names
= total_names
;
628 static int get_ldap_seq(const char *server
, int port
, uint32
*seq
)
632 const char *attrs
[] = {"highestCommittedUSN", NULL
};
633 LDAPMessage
*res
= NULL
;
634 char **values
= NULL
;
637 *seq
= DOM_SEQUENCE_NONE
;
640 * Parameterised (5) second timeout on open. This is needed as the
641 * search timeout doesn't seem to apply to doing an open as well. JRA.
644 ldp
= ldap_open_with_timeout(server
, port
, lp_ldap_timeout());
648 /* Timeout if no response within 20 seconds. */
652 if (ldap_search_st(ldp
, "", LDAP_SCOPE_BASE
, "(objectclass=*)",
653 CONST_DISCARD(char **, attrs
), 0, &to
, &res
))
656 if (ldap_count_entries(ldp
, res
) != 1)
659 values
= ldap_get_values(ldp
, res
, "highestCommittedUSN");
660 if (!values
|| !values
[0])
663 *seq
= atoi(values
[0]);
669 ldap_value_free(values
);
677 /**********************************************************************
678 Get the sequence number for a Windows AD native mode domain using
680 **********************************************************************/
682 static int get_ldap_sequence_number( const char* domain
, uint32
*seq
)
685 int i
, port
= LDAP_PORT
;
686 struct ip_service
*ip_list
= NULL
;
689 if ( !get_sorted_dc_list(domain
, &ip_list
, &count
, False
) ) {
690 DEBUG(3, ("Could not look up dc's for domain %s\n", domain
));
694 /* Finally return first DC that we can contact */
696 for (i
= 0; i
< count
; i
++) {
699 /* since the is an LDAP lookup, default to the LDAP_PORT is
701 port
= (ip_list
[i
].port
!= PORT_NONE
) ?
702 ip_list
[i
].port
: LDAP_PORT
;
704 fstrcpy( ipstr
, inet_ntoa(ip_list
[i
].ip
) );
706 if (is_zero_ip(ip_list
[i
].ip
))
709 if ( (ret
= get_ldap_seq( ipstr
, port
, seq
)) == 0 )
712 /* add to failed connection cache */
713 add_failed_connection_entry( domain
, ipstr
,
714 NT_STATUS_UNSUCCESSFUL
);
719 DEBUG(3, ("get_ldap_sequence_number: Retrieved sequence "
720 "number for Domain (%s) from DC (%s:%d)\n",
721 domain
, inet_ntoa(ip_list
[i
].ip
), port
));
729 #endif /* HAVE_LDAP */
731 /* find the sequence number for a domain */
732 static NTSTATUS
sequence_number(struct winbindd_domain
*domain
, uint32
*seq
)
738 BOOL got_seq_num
= False
;
740 struct rpc_pipe_client
*cli
;
742 DEBUG(10,("rpc: fetch sequence_number for %s\n", domain
->name
));
744 *seq
= DOM_SEQUENCE_NONE
;
746 if (!(mem_ctx
= talloc_init("sequence_number[rpc]")))
747 return NT_STATUS_NO_MEMORY
;
752 if ( domain
->native_mode
)
756 DEBUG(8,("using get_ldap_seq() to retrieve the "
757 "sequence number\n"));
759 res
= get_ldap_sequence_number( domain
->name
, seq
);
762 result
= NT_STATUS_OK
;
763 DEBUG(10,("domain_sequence_number: LDAP for "
765 domain
->name
, *seq
));
769 DEBUG(10,("domain_sequence_number: failed to get LDAP "
770 "sequence number for domain %s\n",
773 #endif /* HAVE_LDAP */
775 result
= cm_connect_sam(domain
, mem_ctx
, &cli
, &dom_pol
);
776 if (!NT_STATUS_IS_OK(result
)) {
780 /* Query domain info */
782 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 8, &ctr
);
784 if (NT_STATUS_IS_OK(result
)) {
785 *seq
= ctr
.info
.inf8
.seq_num
.low
;
790 /* retry with info-level 2 in case the dc does not support info-level 8
791 * (like all older samba2 and samba3 dc's - Guenther */
793 result
= rpccli_samr_query_dom_info(cli
, mem_ctx
, &dom_pol
, 2, &ctr
);
795 if (NT_STATUS_IS_OK(result
)) {
796 *seq
= ctr
.info
.inf2
.seq_num
.low
;
802 DEBUG(10,("domain_sequence_number: for domain %s is %u\n",
803 domain
->name
, (unsigned)*seq
));
805 DEBUG(10,("domain_sequence_number: failed to get sequence "
806 "number (%u) for domain %s\n",
807 (unsigned)*seq
, domain
->name
));
812 talloc_destroy(mem_ctx
);
817 /* get a list of trusted domains */
818 static NTSTATUS
trusted_domains(struct winbindd_domain
*domain
,
825 NTSTATUS result
= NT_STATUS_UNSUCCESSFUL
;
827 struct rpc_pipe_client
*cli
;
828 POLICY_HND lsa_policy
;
830 DEBUG(3,("rpc: trusted_domains\n"));
837 result
= cm_connect_lsa(domain
, mem_ctx
, &cli
, &lsa_policy
);
838 if (!NT_STATUS_IS_OK(result
))
841 result
= STATUS_MORE_ENTRIES
;
843 while (NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
)) {
844 uint32 start_idx
, num
;
849 result
= rpccli_lsa_enum_trust_dom(cli
, mem_ctx
,
850 &lsa_policy
, &enum_ctx
,
854 if (!NT_STATUS_IS_OK(result
) &&
855 !NT_STATUS_EQUAL(result
, STATUS_MORE_ENTRIES
))
858 start_idx
= *num_domains
;
860 *names
= TALLOC_REALLOC_ARRAY(mem_ctx
, *names
,
861 char *, *num_domains
);
862 *dom_sids
= TALLOC_REALLOC_ARRAY(mem_ctx
, *dom_sids
,
863 DOM_SID
, *num_domains
);
864 *alt_names
= TALLOC_REALLOC_ARRAY(mem_ctx
, *alt_names
,
865 char *, *num_domains
);
866 if ((*names
== NULL
) || (*dom_sids
== NULL
) ||
867 (*alt_names
== NULL
))
868 return NT_STATUS_NO_MEMORY
;
870 for (i
=0; i
<num
; i
++) {
871 (*names
)[start_idx
+i
] = tmp_names
[i
];
872 (*dom_sids
)[start_idx
+i
] = tmp_sids
[i
];
873 (*alt_names
)[start_idx
+i
] = talloc_strdup(mem_ctx
, "");
879 /* find alternate names list for the domain - none for rpc */
880 static NTSTATUS
alternate_name(struct winbindd_domain
*domain
)
886 /* the rpc backend methods are exposed via this structure */
887 struct winbindd_methods msrpc_methods
= {
896 msrpc_lookup_useraliases
,