2010-06-16 23:15:54 +04:00
/*
* Unix SMB / CIFS implementation .
*
* Winbind rpc backend functions
*
* Copyright ( c ) 2000 - 2003 Tim Potter
* Copyright ( c ) 2001 Andrew Tridgell
* Copyright ( c ) 2005 Volker Lendecke
* Copyright ( c ) 2008 Guenther Deschner ( pidl conversion )
* Copyright ( c ) 2010 Andreas Schneider < asn @ samba . org >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "winbindd.h"
# include "winbindd_rpc.h"
2011-04-13 16:32:16 +04:00
# include "rpc_client/rpc_client.h"
2011-01-18 15:07:18 +03:00
# include "librpc/gen_ndr/ndr_samr_c.h"
2011-01-18 20:05:49 +03:00
# include "librpc/gen_ndr/ndr_lsa_c.h"
2010-06-16 23:15:54 +04:00
# include "rpc_client/cli_samr.h"
# include "rpc_client/cli_lsarpc.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2010-06-16 23:15:54 +04:00
2010-06-17 16:54:02 +04:00
/* Query display info for a domain */
NTSTATUS rpc_query_user_list ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * samr_pipe ,
struct policy_handle * samr_policy ,
const struct dom_sid * domain_sid ,
2017-01-03 15:11:30 +03:00
uint32_t * * prids )
2010-06-17 16:54:02 +04:00
{
2017-02-11 11:34:17 +03:00
struct dcerpc_binding_handle * b = samr_pipe - > binding_handle ;
2017-01-03 15:11:30 +03:00
uint32_t * rids = NULL ;
uint32_t num_rids = 0 ;
2010-06-17 16:54:02 +04:00
uint32_t i = 0 ;
2017-02-11 11:34:17 +03:00
uint32_t resume_handle = 0 ;
NTSTATUS result ;
2010-06-17 16:54:02 +04:00
2017-01-03 15:11:30 +03:00
* prids = NULL ;
2010-06-17 16:54:02 +04:00
do {
2017-02-11 11:34:17 +03:00
struct samr_SamArray * sam_array = NULL ;
uint32_t count = 0 ;
NTSTATUS status ;
uint32_t * tmp ;
2010-06-17 16:54:02 +04:00
2017-02-11 11:34:17 +03:00
status = dcerpc_samr_EnumDomainUsers (
b , mem_ctx , samr_policy , & resume_handle ,
ACB_NORMAL , & sam_array , 0xffff , & count , & result ) ;
2010-06-17 16:54:02 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-18 15:07:18 +03:00
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
if ( ! NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) {
2017-02-11 11:34:17 +03:00
DBG_WARNING ( " EnumDomainUsers failed: %s \n " ,
nt_errstr ( result ) ) ;
2017-01-10 16:26:13 +03:00
TALLOC_FREE ( rids ) ;
2017-02-11 11:34:17 +03:00
TALLOC_FREE ( sam_array ) ;
2011-01-18 15:07:18 +03:00
return result ;
2010-06-17 16:54:02 +04:00
}
}
2017-02-11 11:34:17 +03:00
if ( num_rids + count < num_rids ) {
TALLOC_FREE ( sam_array ) ;
TALLOC_FREE ( rids ) ;
return NT_STATUS_INTEGER_OVERFLOW ;
2016-11-02 19:19:09 +03:00
}
2010-06-17 16:54:02 +04:00
2017-02-11 11:34:17 +03:00
tmp = talloc_realloc ( mem_ctx , rids , uint32_t , num_rids + count ) ;
if ( tmp = = NULL ) {
TALLOC_FREE ( sam_array ) ;
TALLOC_FREE ( rids ) ;
2010-06-17 16:54:02 +04:00
return NT_STATUS_NO_MEMORY ;
}
2017-02-11 11:34:17 +03:00
rids = tmp ;
2010-06-17 16:54:02 +04:00
2017-02-11 11:34:17 +03:00
for ( i = 0 ; i < count ; i + + ) {
rids [ num_rids + + ] = sam_array - > entries [ i ] . idx ;
2010-06-17 16:54:02 +04:00
}
2011-01-18 15:07:18 +03:00
} while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) ;
2010-06-17 16:54:02 +04:00
2017-01-03 15:11:30 +03:00
* prids = rids ;
2010-06-17 16:54:02 +04:00
return NT_STATUS_OK ;
}
2010-06-16 23:15:54 +04:00
/* List all domain groups */
NTSTATUS rpc_enum_dom_groups ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * samr_pipe ,
struct policy_handle * samr_policy ,
uint32_t * pnum_info ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info * * pinfo )
2010-06-16 23:15:54 +04:00
{
2011-03-22 19:43:39 +03:00
struct wb_acct_info * info = NULL ;
2010-06-16 23:15:54 +04:00
uint32_t start = 0 ;
uint32_t num_info = 0 ;
2011-01-18 15:07:18 +03:00
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = samr_pipe - > binding_handle ;
2010-06-16 23:15:54 +04:00
* pnum_info = 0 ;
do {
struct samr_SamArray * sam_array = NULL ;
uint32_t count = 0 ;
uint32_t g ;
/* start is updated by this call. */
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_EnumDomainGroups ( b ,
2010-06-16 23:15:54 +04:00
mem_ctx ,
samr_policy ,
& start ,
& sam_array ,
0xFFFF , /* buffer size? */
2011-01-18 15:07:18 +03:00
& count ,
& result ) ;
2010-06-16 23:15:54 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-18 15:07:18 +03:00
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
if ( ! NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) {
2010-06-16 23:15:54 +04:00
DEBUG ( 2 , ( " query_user_list: failed to enum domain groups: %s \n " ,
2011-01-18 15:07:18 +03:00
nt_errstr ( result ) ) ) ;
return result ;
2010-06-16 23:15:54 +04:00
}
}
2011-06-07 05:10:15 +04:00
info = talloc_realloc ( mem_ctx ,
2010-06-16 23:15:54 +04:00
info ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info ,
2010-06-16 23:15:54 +04:00
num_info + count ) ;
if ( info = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
for ( g = 0 ; g < count ; g + + ) {
2015-07-16 08:00:08 +03:00
struct wb_acct_info * i = & info [ num_info + g ] ;
2010-06-16 23:15:54 +04:00
2015-07-16 08:00:08 +03:00
fstrcpy ( i - > acct_name ,
sam_array - > entries [ g ] . name . string ) ;
fstrcpy ( i - > acct_desc , " " ) ;
i - > rid = sam_array - > entries [ g ] . idx ;
2010-06-16 23:15:54 +04:00
}
num_info + = count ;
2011-01-18 15:07:18 +03:00
} while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) ;
2010-06-16 23:15:54 +04:00
* pnum_info = num_info ;
* pinfo = info ;
return NT_STATUS_OK ;
}
2010-06-17 17:51:58 +04:00
NTSTATUS rpc_enum_local_groups ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * samr_pipe ,
struct policy_handle * samr_policy ,
uint32_t * pnum_info ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info * * pinfo )
2010-06-17 17:51:58 +04:00
{
2011-03-22 19:43:39 +03:00
struct wb_acct_info * info = NULL ;
2010-06-17 17:51:58 +04:00
uint32_t num_info = 0 ;
2011-01-18 15:07:18 +03:00
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = samr_pipe - > binding_handle ;
2010-06-17 17:51:58 +04:00
* pnum_info = 0 ;
do {
struct samr_SamArray * sam_array = NULL ;
uint32_t count = 0 ;
uint32_t start = num_info ;
uint32_t g ;
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_EnumDomainAliases ( b ,
2010-06-17 17:51:58 +04:00
mem_ctx ,
samr_policy ,
& start ,
& sam_array ,
0xFFFF , /* buffer size? */
2011-01-18 15:07:18 +03:00
& count ,
& result ) ;
2010-06-17 17:51:58 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-18 15:07:18 +03:00
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
if ( ! NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) {
return result ;
2010-06-17 17:51:58 +04:00
}
}
2011-06-07 05:10:15 +04:00
info = talloc_realloc ( mem_ctx ,
2010-06-17 17:51:58 +04:00
info ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info ,
2010-06-17 17:51:58 +04:00
num_info + count ) ;
if ( info = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
for ( g = 0 ; g < count ; g + + ) {
2015-07-16 08:00:08 +03:00
struct wb_acct_info * i = & info [ num_info + g ] ;
fstrcpy ( i - > acct_name ,
2010-06-17 17:51:58 +04:00
sam_array - > entries [ g ] . name . string ) ;
2015-07-16 08:00:08 +03:00
fstrcpy ( i - > acct_desc , " " ) ;
i - > rid = sam_array - > entries [ g ] . idx ;
2010-06-17 17:51:58 +04:00
}
num_info + = count ;
2011-01-18 15:07:18 +03:00
} while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) ;
2010-06-17 17:51:58 +04:00
* pnum_info = num_info ;
* pinfo = info ;
return NT_STATUS_OK ;
}
2010-06-17 18:06:34 +04:00
/* convert a single name to a sid in a domain */
NTSTATUS rpc_name_to_sid ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * lsa_pipe ,
struct policy_handle * lsa_policy ,
const char * domain_name ,
const char * name ,
uint32_t flags ,
struct dom_sid * sid ,
enum lsa_SidType * type )
{
enum lsa_SidType * types = NULL ;
struct dom_sid * sids = NULL ;
char * full_name = NULL ;
2014-02-26 23:16:26 +04:00
const char * names [ 1 ] ;
2010-06-17 18:06:34 +04:00
char * mapped_name = NULL ;
NTSTATUS status ;
if ( name = = NULL | | name [ 0 ] = = ' \0 ' ) {
full_name = talloc_asprintf ( mem_ctx , " %s " , domain_name ) ;
} else if ( domain_name = = NULL | | domain_name [ 0 ] = = ' \0 ' ) {
full_name = talloc_asprintf ( mem_ctx , " %s " , name ) ;
} else {
full_name = talloc_asprintf ( mem_ctx , " %s \\ %s " , domain_name , name ) ;
}
if ( full_name = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
status = normalize_name_unmap ( mem_ctx , full_name , & mapped_name ) ;
/* Reset the full_name pointer if we mapped anything */
if ( NT_STATUS_IS_OK ( status ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_FILE_RENAMED ) ) {
full_name = mapped_name ;
}
DEBUG ( 3 , ( " name_to_sid: %s for domain %s \n " ,
full_name ? full_name : " " , domain_name ) ) ;
2014-02-26 23:16:26 +04:00
names [ 0 ] = full_name ;
2010-06-17 18:06:34 +04:00
/*
* We don ' t run into deadlocks here , cause winbind_off ( ) is
* called in the main function .
*/
status = rpccli_lsa_lookup_names ( lsa_pipe ,
mem_ctx ,
lsa_policy ,
1 , /* num_names */
2014-02-26 23:16:26 +04:00
names ,
2010-06-17 18:06:34 +04:00
NULL , /* domains */
1 , /* level */
& sids ,
& types ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " name_to_sid: failed to lookup name: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
sid_copy ( sid , & sids [ 0 ] ) ;
* type = types [ 0 ] ;
return NT_STATUS_OK ;
}
2010-06-17 18:25:07 +04:00
/* Convert a domain SID to a user or group name */
NTSTATUS rpc_sid_to_name ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * lsa_pipe ,
struct policy_handle * lsa_policy ,
struct winbindd_domain * domain ,
const struct dom_sid * sid ,
char * * pdomain_name ,
char * * pname ,
enum lsa_SidType * ptype )
{
char * mapped_name = NULL ;
char * * domains = NULL ;
char * * names = NULL ;
enum lsa_SidType * types = NULL ;
NTSTATUS map_status ;
NTSTATUS status ;
status = rpccli_lsa_lookup_sids ( lsa_pipe ,
mem_ctx ,
lsa_policy ,
1 , /* num_sids */
sid ,
& domains ,
& names ,
& types ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 2 , ( " sid_to_name: failed to lookup sids: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
* ptype = ( enum lsa_SidType ) types [ 0 ] ;
map_status = normalize_name_map ( mem_ctx ,
domain ,
2014-02-20 19:55:15 +04:00
names [ 0 ] ,
2010-06-17 18:25:07 +04:00
& mapped_name ) ;
if ( NT_STATUS_IS_OK ( map_status ) | |
NT_STATUS_EQUAL ( map_status , NT_STATUS_FILE_RENAMED ) ) {
* pname = talloc_strdup ( mem_ctx , mapped_name ) ;
DEBUG ( 5 , ( " returning mapped name -- %s \n " , * pname ) ) ;
} else {
* pname = talloc_strdup ( mem_ctx , names [ 0 ] ) ;
}
2014-02-20 19:53:51 +04:00
if ( ( names [ 0 ] ! = NULL ) & & ( * pname = = NULL ) ) {
2010-06-17 18:25:07 +04:00
return NT_STATUS_NO_MEMORY ;
}
* pdomain_name = talloc_strdup ( mem_ctx , domains [ 0 ] ) ;
if ( * pdomain_name = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
}
2010-06-17 21:31:51 +04:00
/* Convert a bunch of rids to user or group names */
NTSTATUS rpc_rids_to_names ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * lsa_pipe ,
struct policy_handle * lsa_policy ,
struct winbindd_domain * domain ,
const struct dom_sid * sid ,
uint32_t * rids ,
size_t num_rids ,
char * * pdomain_name ,
char * * * pnames ,
enum lsa_SidType * * ptypes )
{
enum lsa_SidType * types = NULL ;
char * domain_name = NULL ;
char * * domains = NULL ;
char * * names = NULL ;
struct dom_sid * sids ;
size_t i ;
NTSTATUS status ;
if ( num_rids > 0 ) {
2011-06-07 05:30:12 +04:00
sids = talloc_array ( mem_ctx , struct dom_sid , num_rids ) ;
2010-06-17 21:31:51 +04:00
if ( sids = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
} else {
sids = NULL ;
}
for ( i = 0 ; i < num_rids ; i + + ) {
if ( ! sid_compose ( & sids [ i ] , sid , rids [ i ] ) ) {
return NT_STATUS_INTERNAL_ERROR ;
}
}
status = rpccli_lsa_lookup_sids ( lsa_pipe ,
mem_ctx ,
lsa_policy ,
num_rids ,
sids ,
& domains ,
& names ,
& types ) ;
if ( ! NT_STATUS_IS_OK ( status ) & &
! NT_STATUS_EQUAL ( status , STATUS_SOME_UNMAPPED ) ) {
DEBUG ( 2 , ( " rids_to_names: failed to lookup sids: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
for ( i = 0 ; i < num_rids ; i + + ) {
char * mapped_name = NULL ;
NTSTATUS map_status ;
if ( types [ i ] ! = SID_NAME_UNKNOWN ) {
map_status = normalize_name_map ( mem_ctx ,
domain ,
names [ i ] ,
& mapped_name ) ;
if ( NT_STATUS_IS_OK ( map_status ) | |
NT_STATUS_EQUAL ( map_status , NT_STATUS_FILE_RENAMED ) ) {
TALLOC_FREE ( names [ i ] ) ;
names [ i ] = talloc_strdup ( names , mapped_name ) ;
if ( names [ i ] = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
domain_name = domains [ i ] ;
}
}
* pdomain_name = domain_name ;
* ptypes = types ;
* pnames = names ;
return NT_STATUS_OK ;
}
2010-06-18 19:47:16 +04:00
2017-03-02 16:52:49 +03:00
/* Lookup groups a user is a member of. */
NTSTATUS rpc_lookup_usergroups ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * samr_pipe ,
struct policy_handle * samr_policy ,
const struct dom_sid * domain_sid ,
const struct dom_sid * user_sid ,
uint32_t * pnum_groups ,
struct dom_sid * * puser_grpsids )
{
struct policy_handle user_policy ;
struct samr_RidWithAttributeArray * rid_array = NULL ;
struct dom_sid * user_grpsids = NULL ;
uint32_t num_groups = 0 , i ;
uint32_t user_rid ;
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = samr_pipe - > binding_handle ;
if ( ! sid_peek_check_rid ( domain_sid , user_sid , & user_rid ) ) {
return NT_STATUS_UNSUCCESSFUL ;
}
/* Get user handle */
status = dcerpc_samr_OpenUser ( b ,
mem_ctx ,
samr_policy ,
SEC_FLAG_MAXIMUM_ALLOWED ,
user_rid ,
& user_policy ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
/* Query user rids */
status = dcerpc_samr_GetGroupsForUser ( b ,
mem_ctx ,
& user_policy ,
& rid_array ,
& result ) ;
{
NTSTATUS _result ;
dcerpc_samr_Close ( b , mem_ctx , & user_policy , & _result ) ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
num_groups = rid_array - > count ;
user_grpsids = talloc_array ( mem_ctx , struct dom_sid , num_groups ) ;
if ( user_grpsids = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
return status ;
}
for ( i = 0 ; i < num_groups ; i + + ) {
sid_compose ( & ( user_grpsids [ i ] ) , domain_sid ,
rid_array - > rids [ i ] . rid ) ;
}
* pnum_groups = num_groups ;
* puser_grpsids = user_grpsids ;
return NT_STATUS_OK ;
}
2010-06-18 21:07:43 +04:00
NTSTATUS rpc_lookup_useraliases ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * samr_pipe ,
struct policy_handle * samr_policy ,
uint32_t num_sids ,
const struct dom_sid * sids ,
uint32_t * pnum_aliases ,
uint32_t * * palias_rids )
{
# define MAX_SAM_ENTRIES_W2K 0x400 /* 1024 */
uint32_t num_query_sids = 0 ;
uint32_t num_queries = 1 ;
uint32_t num_aliases = 0 ;
uint32_t total_sids = 0 ;
uint32_t * alias_rids = NULL ;
uint32_t rangesize = MAX_SAM_ENTRIES_W2K ;
uint32_t i ;
struct samr_Ids alias_rids_query ;
2011-01-18 15:07:18 +03:00
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = samr_pipe - > binding_handle ;
2010-06-18 21:07:43 +04:00
do {
/* prepare query */
struct lsa_SidArray sid_array ;
ZERO_STRUCT ( sid_array ) ;
num_query_sids = MIN ( num_sids - total_sids , rangesize ) ;
DEBUG ( 10 , ( " rpc: lookup_useraliases: entering query %d for %d sids \n " ,
num_queries , num_query_sids ) ) ;
if ( num_query_sids ) {
2011-06-07 05:58:39 +04:00
sid_array . sids = talloc_zero_array ( mem_ctx , struct lsa_SidPtr , num_query_sids ) ;
2010-06-18 21:07:43 +04:00
if ( sid_array . sids = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
} else {
sid_array . sids = NULL ;
}
for ( i = 0 ; i < num_query_sids ; i + + ) {
2010-08-26 19:21:39 +04:00
sid_array . sids [ i ] . sid = dom_sid_dup ( mem_ctx , & sids [ total_sids + + ] ) ;
2010-06-18 21:07:43 +04:00
if ( sid_array . sids [ i ] . sid = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
sid_array . num_sids = num_query_sids ;
/* do request */
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_GetAliasMembership ( b ,
2010-06-18 21:07:43 +04:00
mem_ctx ,
samr_policy ,
& sid_array ,
2011-01-18 15:07:18 +03:00
& alias_rids_query ,
& result ) ;
2010-06-18 21:07:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2011-01-18 15:07:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
2010-06-18 21:07:43 +04:00
/* process output */
for ( i = 0 ; i < alias_rids_query . count ; i + + ) {
size_t na = num_aliases ;
if ( ! add_rid_to_array_unique ( mem_ctx ,
alias_rids_query . ids [ i ] ,
& alias_rids ,
& na ) ) {
return NT_STATUS_NO_MEMORY ;
}
num_aliases = na ;
}
num_queries + + ;
} while ( total_sids < num_sids ) ;
DEBUG ( 10 , ( " rpc: rpc_lookup_useraliases: got %d aliases in %d queries "
" (rangesize: %d) \n " , num_aliases , num_queries , rangesize ) ) ;
* pnum_aliases = num_aliases ;
* palias_rids = alias_rids ;
return NT_STATUS_OK ;
# undef MAX_SAM_ENTRIES_W2K
}
2010-06-21 12:28:21 +04:00
/* Lookup group membership given a rid. */
NTSTATUS rpc_lookup_groupmem ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * samr_pipe ,
struct policy_handle * samr_policy ,
const char * domain_name ,
const struct dom_sid * domain_sid ,
const struct dom_sid * group_sid ,
enum lsa_SidType type ,
uint32_t * pnum_names ,
struct dom_sid * * psid_mem ,
char * * * pnames ,
uint32_t * * pname_types )
{
struct policy_handle group_policy ;
uint32_t group_rid ;
uint32_t * rid_mem = NULL ;
uint32_t num_names = 0 ;
uint32_t total_names = 0 ;
struct dom_sid * sid_mem = NULL ;
char * * names = NULL ;
uint32_t * name_types = NULL ;
struct lsa_Strings tmp_names ;
struct samr_Ids tmp_types ;
uint32_t j , r ;
2011-01-18 15:07:18 +03:00
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = samr_pipe - > binding_handle ;
2010-06-21 12:28:21 +04:00
if ( ! sid_peek_check_rid ( domain_sid , group_sid , & group_rid ) ) {
return NT_STATUS_UNSUCCESSFUL ;
}
2010-07-06 16:56:50 +04:00
switch ( type ) {
case SID_NAME_DOM_GRP :
{
2010-10-07 15:01:29 +04:00
struct samr_RidAttrArray * rids = NULL ;
2010-07-06 16:56:50 +04:00
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_OpenGroup ( b ,
2010-07-06 16:56:50 +04:00
mem_ctx ,
samr_policy ,
SEC_FLAG_MAXIMUM_ALLOWED ,
group_rid ,
2011-01-18 15:07:18 +03:00
& group_policy ,
& result ) ;
2010-07-06 16:56:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2011-01-18 15:07:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
2010-06-21 12:28:21 +04:00
2010-07-06 16:56:50 +04:00
/*
* Step # 1 : Get a list of user rids that are the members of the group .
*/
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_QueryGroupMember ( b ,
2010-07-06 16:56:50 +04:00
mem_ctx ,
& group_policy ,
2011-01-18 15:07:18 +03:00
& rids ,
& result ) ;
{
NTSTATUS _result ;
dcerpc_samr_Close ( b , mem_ctx , & group_policy , & _result ) ;
}
2010-06-21 12:28:21 +04:00
2010-07-06 16:56:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2011-01-18 15:07:18 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
2010-07-06 16:56:50 +04:00
if ( rids = = NULL | | rids - > count = = 0 ) {
pnum_names = 0 ;
pnames = NULL ;
pname_types = NULL ;
psid_mem = NULL ;
return NT_STATUS_OK ;
}
2010-06-21 12:28:21 +04:00
2010-07-06 16:56:50 +04:00
num_names = rids - > count ;
rid_mem = rids - > rids ;
2010-06-21 12:28:21 +04:00
2010-07-06 16:56:50 +04:00
break ;
2010-06-21 12:28:21 +04:00
}
2010-07-06 16:56:50 +04:00
case SID_NAME_WKN_GRP :
case SID_NAME_ALIAS :
{
struct lsa_SidArray sid_array ;
struct lsa_SidPtr sid_ptr ;
struct samr_Ids rids_query ;
2010-08-26 19:21:39 +04:00
sid_ptr . sid = dom_sid_dup ( mem_ctx , group_sid ) ;
2010-07-06 16:56:50 +04:00
if ( sid_ptr . sid = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
sid_array . num_sids = 1 ;
sid_array . sids = & sid_ptr ;
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_GetAliasMembership ( b ,
2010-07-06 16:56:50 +04:00
mem_ctx ,
samr_policy ,
& sid_array ,
2011-01-18 15:07:18 +03:00
& rids_query ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
2010-07-06 16:56:50 +04:00
if ( rids_query . count = = 0 ) {
pnum_names = 0 ;
pnames = NULL ;
pname_types = NULL ;
psid_mem = NULL ;
return NT_STATUS_OK ;
}
2010-06-21 12:28:21 +04:00
2010-07-06 16:56:50 +04:00
num_names = rids_query . count ;
rid_mem = rids_query . ids ;
break ;
}
default :
return NT_STATUS_UNSUCCESSFUL ;
}
2010-06-21 12:28:21 +04:00
/*
* Step # 2 : Convert list of rids into list of usernames .
*/
if ( num_names > 0 ) {
2011-06-07 05:58:39 +04:00
names = talloc_zero_array ( mem_ctx , char * , num_names ) ;
name_types = talloc_zero_array ( mem_ctx , uint32_t , num_names ) ;
sid_mem = talloc_zero_array ( mem_ctx , struct dom_sid , num_names ) ;
2010-06-21 12:28:21 +04:00
if ( names = = NULL | | name_types = = NULL | | sid_mem = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
}
for ( j = 0 ; j < num_names ; j + + ) {
sid_compose ( & sid_mem [ j ] , domain_sid , rid_mem [ j ] ) ;
}
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_LookupRids ( b ,
2010-06-21 12:28:21 +04:00
mem_ctx ,
samr_policy ,
num_names ,
rid_mem ,
& tmp_names ,
2011-01-18 15:07:18 +03:00
& tmp_types ,
& result ) ;
2010-06-21 12:28:21 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-01-18 15:07:18 +03:00
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
if ( ! NT_STATUS_EQUAL ( result , STATUS_SOME_UNMAPPED ) ) {
return result ;
2010-06-21 12:28:21 +04:00
}
}
/* Copy result into array. The talloc system will take
care of freeing the temporary arrays later on . */
2013-11-08 10:41:22 +04:00
if ( tmp_names . count ! = num_names ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
if ( tmp_types . count ! = num_names ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
2010-06-21 12:28:21 +04:00
}
for ( r = 0 ; r < tmp_names . count ; r + + ) {
if ( tmp_types . ids [ r ] = = SID_NAME_UNKNOWN ) {
continue ;
}
2013-11-08 10:41:22 +04:00
if ( total_names > = num_names ) {
break ;
}
2010-06-21 12:28:21 +04:00
names [ total_names ] = fill_domain_username_talloc ( names ,
domain_name ,
tmp_names . names [ r ] . string ,
true ) ;
if ( names [ total_names ] = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
name_types [ total_names ] = tmp_types . ids [ r ] ;
total_names + + ;
}
* pnum_names = total_names ;
* pnames = names ;
* pname_types = name_types ;
* psid_mem = sid_mem ;
return NT_STATUS_OK ;
}
2010-06-21 12:47:22 +04:00
/* Find the sequence number for a domain */
NTSTATUS rpc_sequence_number ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * samr_pipe ,
struct policy_handle * samr_policy ,
const char * domain_name ,
uint32_t * pseq )
{
union samr_DomainInfo * info = NULL ;
bool got_seq_num = false ;
2011-01-18 15:07:18 +03:00
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = samr_pipe - > binding_handle ;
2010-06-21 12:47:22 +04:00
/* query domain info */
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_QueryDomainInfo ( b ,
2010-06-21 12:47:22 +04:00
mem_ctx ,
samr_policy ,
8 ,
2011-01-18 15:07:18 +03:00
& info ,
& result ) ;
if ( NT_STATUS_IS_OK ( status ) & & NT_STATUS_IS_OK ( result ) ) {
2010-06-21 12:47:22 +04:00
* pseq = info - > info8 . sequence_num ;
got_seq_num = true ;
goto seq_num ;
}
/* retry with info-level 2 in case the dc does not support info-level 8
* ( like all older samba2 and samba3 dc ' s ) - Guenther */
2011-01-18 15:07:18 +03:00
status = dcerpc_samr_QueryDomainInfo ( b ,
2010-06-21 12:47:22 +04:00
mem_ctx ,
samr_policy ,
2 ,
2011-01-18 15:07:18 +03:00
& info ,
& result ) ;
if ( NT_STATUS_IS_OK ( status ) & & NT_STATUS_IS_OK ( result ) ) {
2010-06-21 12:47:22 +04:00
* pseq = info - > general . sequence_num ;
got_seq_num = true ;
2011-01-18 15:07:18 +03:00
goto seq_num ;
2010-06-21 12:47:22 +04:00
}
2011-01-18 15:07:18 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto seq_num ;
}
status = result ;
2010-06-21 12:47:22 +04:00
seq_num :
if ( got_seq_num ) {
DEBUG ( 10 , ( " domain_sequence_number: for domain %s is %u \n " ,
domain_name , ( unsigned ) * pseq ) ) ;
} else {
DEBUG ( 10 , ( " domain_sequence_number: failed to get sequence "
" number (%u) for domain %s \n " ,
( unsigned ) * pseq , domain_name ) ) ;
status = NT_STATUS_OK ;
}
return status ;
}
2010-06-21 13:13:25 +04:00
/* Get a list of trusted domains */
NTSTATUS rpc_trusted_domains ( TALLOC_CTX * mem_ctx ,
struct rpc_pipe_client * lsa_pipe ,
struct policy_handle * lsa_policy ,
uint32_t * pnum_trusts ,
struct netr_DomainTrust * * ptrusts )
{
struct netr_DomainTrust * array = NULL ;
uint32_t enum_ctx = 0 ;
uint32_t count = 0 ;
2011-01-18 20:05:49 +03:00
NTSTATUS status , result ;
struct dcerpc_binding_handle * b = lsa_pipe - > binding_handle ;
2010-06-21 13:13:25 +04:00
do {
struct lsa_DomainList dom_list ;
2012-09-11 15:28:35 +04:00
struct lsa_DomainListEx dom_list_ex ;
bool has_ex = false ;
2010-06-21 13:13:25 +04:00
uint32_t i ;
/*
* We don ' t run into deadlocks here , cause winbind_off ( ) is
* called in the main function .
*/
2012-09-11 15:28:35 +04:00
status = dcerpc_lsa_EnumTrustedDomainsEx ( b ,
mem_ctx ,
lsa_policy ,
& enum_ctx ,
& dom_list_ex ,
( uint32_t ) - 1 ,
& result ) ;
2012-09-28 20:04:07 +04:00
if ( NT_STATUS_IS_OK ( status ) & & ! NT_STATUS_IS_ERR ( result ) & &
2012-09-11 15:28:35 +04:00
dom_list_ex . count > 0 ) {
count + = dom_list_ex . count ;
has_ex = true ;
} else {
status = dcerpc_lsa_EnumTrustDom ( b ,
mem_ctx ,
lsa_policy ,
& enum_ctx ,
& dom_list ,
( uint32_t ) - 1 ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! NT_STATUS_IS_OK ( result ) ) {
if ( ! NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) {
return result ;
}
2010-06-21 13:13:25 +04:00
}
2012-09-11 15:28:35 +04:00
count + = dom_list . count ;
}
2010-06-21 13:13:25 +04:00
array = talloc_realloc ( mem_ctx ,
array ,
struct netr_DomainTrust ,
count ) ;
if ( array = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2012-09-11 15:28:35 +04:00
for ( i = 0 ; i < count ; i + + ) {
2010-06-21 13:13:25 +04:00
struct netr_DomainTrust * trust = & array [ i ] ;
struct dom_sid * sid ;
ZERO_STRUCTP ( trust ) ;
sid = talloc ( array , struct dom_sid ) ;
if ( sid = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2012-09-11 15:28:35 +04:00
if ( has_ex ) {
trust - > netbios_name = talloc_move ( array ,
& dom_list_ex . domains [ i ] . netbios_name . string ) ;
trust - > dns_name = talloc_move ( array ,
& dom_list_ex . domains [ i ] . domain_name . string ) ;
2014-08-11 03:47:54 +04:00
if ( dom_list_ex . domains [ i ] . sid = = NULL ) {
DEBUG ( 0 , ( " Trusted Domain %s has no SID, aborting! \n " , trust - > dns_name ) ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2012-09-11 15:28:35 +04:00
sid_copy ( sid , dom_list_ex . domains [ i ] . sid ) ;
} else {
trust - > netbios_name = talloc_move ( array ,
& dom_list . domains [ i ] . name . string ) ;
trust - > dns_name = NULL ;
2014-08-11 03:47:54 +04:00
if ( dom_list . domains [ i ] . sid = = NULL ) {
DEBUG ( 0 , ( " Trusted Domain %s has no SID, aborting! \n " , trust - > netbios_name ) ) ;
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2012-09-11 15:28:35 +04:00
sid_copy ( sid , dom_list . domains [ i ] . sid ) ;
}
2010-06-21 13:13:25 +04:00
trust - > sid = sid ;
}
2011-01-18 20:05:49 +03:00
} while ( NT_STATUS_EQUAL ( result , STATUS_MORE_ENTRIES ) ) ;
2010-06-21 13:13:25 +04:00
* pnum_trusts = count ;
* ptrusts = array ;
return NT_STATUS_OK ;
}
2011-03-11 14:48:11 +03:00
static NTSTATUS rpc_try_lookup_sids3 ( TALLOC_CTX * mem_ctx ,
struct winbindd_domain * domain ,
2012-11-29 17:31:19 +04:00
struct rpc_pipe_client * cli ,
2011-03-11 14:48:11 +03:00
struct lsa_SidArray * sids ,
struct lsa_RefDomainList * * pdomains ,
struct lsa_TransNameArray * * pnames )
{
struct lsa_TransNameArray2 lsa_names2 ;
2013-11-08 09:40:55 +04:00
struct lsa_TransNameArray * names = * pnames ;
2015-07-16 07:57:50 +03:00
uint32_t i , count = 0 ;
2011-03-11 14:48:11 +03:00
NTSTATUS status , result ;
ZERO_STRUCT ( lsa_names2 ) ;
status = dcerpc_lsa_LookupSids3 ( cli - > binding_handle ,
mem_ctx ,
sids ,
pdomains ,
& lsa_names2 ,
LSA_LOOKUP_NAMES_ALL ,
& count ,
LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES ,
LSA_CLIENT_REVISION_2 ,
& result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( NT_STATUS_IS_ERR ( result ) ) {
return result ;
}
2013-11-08 08:38:01 +04:00
if ( sids - > num_sids ! = lsa_names2 . count ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2011-03-11 14:48:11 +03:00
names - > count = lsa_names2 . count ;
names - > names = talloc_array ( names , struct lsa_TranslatedName ,
names - > count ) ;
if ( names - > names = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < names - > count ; i + + ) {
names - > names [ i ] . sid_type = lsa_names2 . names [ i ] . sid_type ;
names - > names [ i ] . name . string = talloc_move (
names - > names , & lsa_names2 . names [ i ] . name . string ) ;
names - > names [ i ] . sid_index = lsa_names2 . names [ i ] . sid_index ;
2013-11-08 08:38:01 +04:00
if ( names - > names [ i ] . sid_index = = UINT32_MAX ) {
continue ;
}
if ( ( * pdomains ) = = NULL ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
if ( names - > names [ i ] . sid_index > = ( * pdomains ) - > count ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
2011-03-11 14:48:11 +03:00
}
return result ;
}
NTSTATUS rpc_lookup_sids ( TALLOC_CTX * mem_ctx ,
struct winbindd_domain * domain ,
struct lsa_SidArray * sids ,
struct lsa_RefDomainList * * pdomains ,
struct lsa_TransNameArray * * pnames )
{
2013-11-08 09:40:55 +04:00
struct lsa_TransNameArray * names = * pnames ;
2011-03-11 14:48:11 +03:00
struct rpc_pipe_client * cli = NULL ;
struct policy_handle lsa_policy ;
uint32_t count ;
2013-11-08 08:38:01 +04:00
uint32_t i ;
2011-03-11 14:48:11 +03:00
NTSTATUS status , result ;
2012-11-29 17:31:19 +04:00
status = cm_connect_lsat ( domain , mem_ctx , & cli , & lsa_policy ) ;
2011-03-11 14:48:11 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2012-11-29 17:31:19 +04:00
if ( cli - > transport - > transport = = NCACN_IP_TCP ) {
return rpc_try_lookup_sids3 ( mem_ctx , domain , cli , sids ,
pdomains , pnames ) ;
}
2011-03-11 14:48:11 +03:00
status = dcerpc_lsa_LookupSids ( cli - > binding_handle , mem_ctx ,
& lsa_policy , sids , pdomains ,
names , LSA_LOOKUP_NAMES_ALL ,
& count , & result ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( NT_STATUS_IS_ERR ( result ) ) {
return result ;
}
2013-11-08 08:38:01 +04:00
if ( sids - > num_sids ! = names - > count ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
for ( i = 0 ; i < names - > count ; i + + ) {
if ( names - > names [ i ] . sid_index = = UINT32_MAX ) {
continue ;
}
if ( ( * pdomains ) = = NULL ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
if ( names - > names [ i ] . sid_index > = ( * pdomains ) - > count ) {
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
}
2011-03-11 14:48:11 +03:00
return result ;
}