2005-10-18 07:24:00 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-12-03 09:04:18 +03:00
Winbind ADS backend functions
Copyright ( C ) Andrew Tridgell 2001
2003-04-23 15:54:56 +04:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2003
2004-03-23 01:49:40 +03:00
Copyright ( C ) Gerald ( Jerry ) Carter 2004
2009-08-03 00:28:49 +04:00
2001-12-03 09:04:18 +03:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2001-12-03 09:04:18 +03:00
( at your option ) any later version .
2009-08-03 00:28:49 +04:00
2001-12-03 09:04:18 +03:00
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 .
2009-08-03 00:28:49 +04:00
2001-12-03 09:04:18 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-12-03 09:04:18 +03:00
*/
2003-11-12 04:51:10 +03:00
# include "includes.h"
2001-12-03 09:04:18 +03:00
# include "winbindd.h"
2017-05-11 22:38:50 +03:00
# include "winbindd_ads.h"
2018-03-10 17:31:11 +03:00
# include "libsmb/namequery.h"
2011-04-13 16:32:16 +04:00
# include "rpc_client/rpc_client.h"
2011-01-12 13:55:34 +03:00
# include "../librpc/gen_ndr/ndr_netlogon_c.h"
2010-07-01 01:38:57 +04:00
# include "../libds/common/flags.h"
2010-07-02 02:32:52 +04:00
# include "ads.h"
2010-09-17 06:33:44 +04:00
# include "../libcli/ldap/ldap_ndr.h"
2010-10-12 08:27:50 +04:00
# include "../libcli/security/security.h"
2011-02-26 02:17:33 +03:00
# include "../libds/common/flag_mapping.h"
2016-11-29 18:41:27 +03:00
# include "libsmb/samlogon_cache.h"
2011-03-22 18:50:02 +03:00
# include "passdb.h"
2001-12-03 09:04:18 +03:00
# ifdef HAVE_ADS
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_WINBIND
2006-12-12 20:38:42 +03:00
extern struct winbindd_methods reconnect_methods ;
2016-01-06 00:42:09 +03:00
extern struct winbindd_methods msrpc_methods ;
2006-12-12 20:38:42 +03:00
2013-02-21 23:31:41 +04:00
# define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
2013-02-21 23:31:28 +04:00
/**
* Check if cached connection can be reused . If the connection cannot
* be reused the ADS_STRUCT is freed and the pointer is set to NULL .
*/
2013-02-21 23:31:41 +04:00
static void ads_cached_connection_reuse ( ADS_STRUCT * * adsp )
2001-12-05 10:05:53 +03:00
{
2013-02-21 23:31:28 +04:00
ADS_STRUCT * ads = * adsp ;
2007-02-08 20:02:39 +03:00
2013-02-21 23:31:28 +04:00
if ( ads ! = NULL ) {
2007-02-08 20:02:39 +03:00
time_t expire ;
time_t now = time ( NULL ) ;
2004-03-23 01:49:40 +03:00
2007-02-08 20:02:39 +03:00
expire = MIN ( ads - > auth . tgt_expire , ads - > auth . tgs_expire ) ;
2013-02-21 23:31:28 +04:00
DEBUG ( 7 , ( " Current tickets expire in %d seconds (at %d, time "
2015-04-24 05:04:23 +03:00
" is now %d) \n " , ( uint32_t ) expire - ( uint32_t ) now ,
( uint32_t ) expire , ( uint32_t ) now ) ) ;
2007-02-08 20:02:39 +03:00
if ( ads - > config . realm & & ( expire > now ) ) {
2013-02-21 23:31:28 +04:00
return ;
2007-02-08 20:02:39 +03:00
} else {
2004-03-23 01:49:40 +03:00
/* we own this ADS_STRUCT so make sure it goes away */
2007-02-08 20:02:39 +03:00
DEBUG ( 7 , ( " Deleting expired krb5 credential cache \n " ) ) ;
2004-03-23 01:49:40 +03:00
ads - > is_mine = True ;
ads_destroy ( & ads ) ;
2013-02-21 23:31:28 +04:00
ads_kdestroy ( WINBIND_CCACHE_NAME ) ;
* adsp = NULL ;
2007-10-25 01:16:54 +04:00
}
2001-12-05 10:05:53 +03:00
}
2013-02-21 23:31:28 +04:00
}
2014-08-29 01:50:39 +04:00
/**
* @ brief Establish a connection to a DC
*
* @ param [ out ] adsp ADS_STRUCT that will be created
* @ param [ in ] target_realm Realm of domain to connect to
* @ param [ in ] target_dom_name ' workgroup ' name of domain to connect to
* @ param [ in ] ldap_server DNS name of server to connect to
* @ param [ in ] password Our machine acount secret
* @ param [ in ] auth_realm Realm of local domain for creating krb token
* @ param [ in ] renewable Renewable ticket time
*
* @ return ADS_STATUS
*/
2013-02-21 23:31:41 +04:00
static ADS_STATUS ads_cached_connection_connect ( ADS_STRUCT * * adsp ,
2014-08-29 01:44:59 +04:00
const char * target_realm ,
const char * target_dom_name ,
2013-02-21 23:31:41 +04:00
const char * ldap_server ,
char * password ,
2014-08-29 01:44:59 +04:00
char * auth_realm ,
2013-02-21 23:31:41 +04:00
time_t renewable )
2013-02-21 23:31:37 +04:00
{
ADS_STRUCT * ads ;
ADS_STATUS status ;
struct sockaddr_storage dc_ss ;
fstring dc_name ;
2014-08-29 01:44:59 +04:00
if ( auth_realm = = NULL ) {
2013-08-29 18:38:08 +04:00
return ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
}
2013-02-21 23:31:37 +04:00
/* we don't want this to affect the users ccache */
setenv ( " KRB5CCNAME " , WINBIND_CCACHE_NAME , 1 ) ;
2019-08-13 18:41:40 +03:00
ads = ads_init ( target_realm ,
target_dom_name ,
ldap_server ,
ADS_SASL_SEAL ) ;
2013-02-21 23:31:37 +04:00
if ( ! ads ) {
2014-08-29 01:44:59 +04:00
DEBUG ( 1 , ( " ads_init for domain %s failed \n " , target_dom_name ) ) ;
2013-02-21 23:31:37 +04:00
return ADS_ERROR ( LDAP_NO_MEMORY ) ;
}
SAFE_FREE ( ads - > auth . password ) ;
SAFE_FREE ( ads - > auth . realm ) ;
ads - > auth . renewable = renewable ;
ads - > auth . password = password ;
2017-02-22 23:18:32 +03:00
ads - > auth . flags | = ADS_AUTH_ALLOW_NTLMSSP ;
2014-08-29 01:44:59 +04:00
ads - > auth . realm = SMB_STRDUP ( auth_realm ) ;
2013-02-21 23:31:37 +04:00
if ( ! strupper_m ( ads - > auth . realm ) ) {
ads_destroy ( & ads ) ;
return ADS_ERROR_NT ( NT_STATUS_INTERNAL_ERROR ) ;
}
/* Setup the server affinity cache. We don't reaally care
about the name . Just setup affinity and the KRB5_CONFIG
file . */
get_dc_name ( ads - > server . workgroup , ads - > server . realm , dc_name , & dc_ss ) ;
status = ads_connect ( ads ) ;
if ( ! ADS_ERR_OK ( status ) ) {
DEBUG ( 1 , ( " ads_connect for domain %s failed: %s \n " ,
2014-08-29 01:44:59 +04:00
target_dom_name , ads_errstr ( status ) ) ) ;
2013-02-21 23:31:37 +04:00
ads_destroy ( & ads ) ;
return status ;
}
/* set the flag that says we don't own the memory even
though we do so that ads_destroy ( ) won ' t destroy the
structure we pass back by reference */
ads - > is_mine = False ;
* adsp = ads ;
return status ;
}
2013-02-21 23:31:41 +04:00
ADS_STATUS ads_idmap_cached_connection ( ADS_STRUCT * * adsp , const char * dom_name )
{
char * ldap_server , * realm , * password ;
struct winbindd_domain * wb_dom ;
2013-08-23 16:56:17 +04:00
ADS_STATUS status ;
2013-02-21 23:31:41 +04:00
2018-02-02 18:55:01 +03:00
if ( IS_AD_DC ) {
/*
* Make sure we never try to use LDAP against
* a trusted domain as AD DC .
*/
return ADS_ERROR_NT ( NT_STATUS_REQUEST_NOT_ACCEPTED ) ;
}
2013-02-21 23:31:41 +04:00
ads_cached_connection_reuse ( adsp ) ;
if ( * adsp ! = NULL ) {
return ADS_SUCCESS ;
}
/*
* At this point we only have the NetBIOS domain name .
* Check if we can get server nam and realm from SAF cache
* and the domain list .
*/
2013-09-05 00:39:31 +04:00
ldap_server = saf_fetch ( talloc_tos ( ) , dom_name ) ;
2013-02-21 23:31:41 +04:00
DEBUG ( 10 , ( " ldap_server from saf cache: '%s' \n " ,
ldap_server ? ldap_server : " " ) ) ;
2013-08-28 17:00:06 +04:00
wb_dom = find_domain_from_name ( dom_name ) ;
2013-02-21 23:31:41 +04:00
if ( wb_dom = = NULL ) {
DEBUG ( 10 , ( " could not find domain '%s' \n " , dom_name ) ) ;
2013-08-23 16:56:17 +04:00
return ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
}
DEBUG ( 10 , ( " find_domain_from_name found realm '%s' for "
2013-02-21 23:31:41 +04:00
" domain '%s' \n " , wb_dom - > alt_name , dom_name ) ) ;
2013-08-23 16:56:17 +04:00
if ( ! get_trust_pw_clear ( dom_name , & password , NULL , NULL ) ) {
2013-09-05 00:39:31 +04:00
TALLOC_FREE ( ldap_server ) ;
2013-08-23 16:56:17 +04:00
return ADS_ERROR_NT ( NT_STATUS_CANT_ACCESS_DOMAIN_INFO ) ;
2013-02-21 23:31:41 +04:00
}
2013-08-23 16:56:17 +04:00
if ( IS_DC ) {
2014-07-16 23:41:55 +04:00
SMB_ASSERT ( wb_dom - > alt_name ! = NULL ) ;
2013-08-23 16:56:17 +04:00
realm = SMB_STRDUP ( wb_dom - > alt_name ) ;
} else {
struct winbindd_domain * our_domain = wb_dom ;
/* always give preference to the alt_name in our
primary domain if possible */
2013-02-21 23:31:41 +04:00
2013-08-23 16:56:17 +04:00
if ( ! wb_dom - > primary ) {
our_domain = find_our_domain ( ) ;
}
if ( our_domain - > alt_name ! = NULL ) {
realm = SMB_STRDUP ( our_domain - > alt_name ) ;
} else {
realm = SMB_STRDUP ( lp_realm ( ) ) ;
}
}
2014-08-22 20:15:59 +04:00
status = ads_cached_connection_connect (
adsp , /* Returns ads struct. */
wb_dom - > alt_name , /* realm to connect to. */
dom_name , /* 'workgroup' name for ads_init */
ldap_server , /* DNS name to connect to. */
password , /* password for auth realm. */
realm , /* realm used for krb5 ticket. */
0 ) ; /* renewable ticket time. */
2013-08-23 16:56:17 +04:00
SAFE_FREE ( realm ) ;
2013-09-05 00:39:31 +04:00
TALLOC_FREE ( ldap_server ) ;
2013-08-23 16:56:17 +04:00
return status ;
2013-02-21 23:31:41 +04:00
}
2013-02-21 23:31:28 +04:00
/*
return our ads connections structure for a domain . We keep the connection
open to make things faster
*/
static ADS_STRUCT * ads_cached_connection ( struct winbindd_domain * domain )
{
ADS_STATUS status ;
2013-02-21 23:31:37 +04:00
char * password , * realm ;
2013-02-21 23:31:28 +04:00
2018-02-02 18:55:01 +03:00
if ( IS_AD_DC ) {
/*
* Make sure we never try to use LDAP against
* a trusted domain as AD DC .
*/
return NULL ;
}
2013-02-21 23:31:28 +04:00
DEBUG ( 10 , ( " ads_cached_connection \n " ) ) ;
ads_cached_connection_reuse ( ( ADS_STRUCT * * ) & domain - > private_data ) ;
if ( domain - > private_data ) {
return ( ADS_STRUCT * ) domain - > private_data ;
}
2001-12-05 10:05:53 +03:00
2001-12-08 14:18:56 +03:00
/* the machine acct password might have change - fetch it every time */
2002-08-17 21:00:51 +04:00
2013-08-28 16:53:08 +04:00
if ( ! get_trust_pw_clear ( domain - > name , & password , NULL , NULL ) ) {
return NULL ;
}
2005-11-10 22:50:09 +03:00
if ( IS_DC ) {
2014-07-16 23:41:55 +04:00
SMB_ASSERT ( domain - > alt_name ! = NULL ) ;
2013-08-22 18:36:27 +04:00
realm = SMB_STRDUP ( domain - > alt_name ) ;
2005-11-10 22:50:09 +03:00
}
else {
struct winbindd_domain * our_domain = domain ;
2007-10-25 01:16:54 +04:00
/* always give preference to the alt_name in our
2005-11-10 22:50:09 +03:00
primary domain if possible */
if ( ! domain - > primary )
our_domain = find_our_domain ( ) ;
2013-02-25 12:31:12 +04:00
if ( our_domain - > alt_name ! = NULL ) {
2013-02-21 23:31:37 +04:00
realm = SMB_STRDUP ( our_domain - > alt_name ) ;
2005-11-10 22:50:09 +03:00
}
else
2013-02-21 23:31:37 +04:00
realm = SMB_STRDUP ( lp_realm ( ) ) ;
2005-11-10 22:50:09 +03:00
}
2001-12-08 14:18:56 +03:00
2013-02-21 23:31:37 +04:00
status = ads_cached_connection_connect (
( ADS_STRUCT * * ) & domain - > private_data ,
domain - > alt_name ,
domain - > name , NULL ,
password , realm ,
WINBINDD_PAM_AUTH_KRB5_RENEW_TIME ) ;
2013-08-23 14:33:53 +04:00
SAFE_FREE ( realm ) ;
2001-12-19 15:38:52 +03:00
2013-02-21 23:31:37 +04:00
if ( ! ADS_ERR_OK ( status ) ) {
2001-12-19 15:38:52 +03:00
/* if we get ECONNREFUSED then it might be a NT4
server , fall back to MSRPC */
2004-01-12 17:26:50 +03:00
if ( status . error_type = = ENUM_ADS_ERROR_SYSTEM & &
2002-09-25 19:19:00 +04:00
status . err . rc = = ECONNREFUSED ) {
2006-12-05 09:15:23 +03:00
/* 'reconnect_methods' is the MS-RPC backend. */
2001-12-19 15:38:52 +03:00
DEBUG ( 1 , ( " Trying MSRPC methods \n " ) ) ;
2006-12-05 09:15:23 +03:00
domain - > backend = & reconnect_methods ;
2001-12-19 15:38:52 +03:00
}
2001-12-05 10:05:53 +03:00
return NULL ;
}
2013-02-21 23:31:37 +04:00
return ( ADS_STRUCT * ) domain - > private_data ;
2001-12-05 10:05:53 +03:00
}
2001-12-03 09:04:18 +03:00
/* Query display info for a realm. This is the basic user list fn */
2001-12-03 14:32:55 +03:00
static NTSTATUS query_user_list ( struct winbindd_domain * domain ,
2001-12-03 09:04:18 +03:00
TALLOC_CTX * mem_ctx ,
2017-01-03 15:11:30 +03:00
uint32_t * * prids )
2001-12-03 09:04:18 +03:00
{
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2017-01-03 15:11:30 +03:00
const char * attrs [ ] = { " sAMAccountType " , " objectSid " , NULL } ;
int count ;
2017-01-11 22:52:44 +03:00
uint32_t * rids = NULL ;
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
2006-09-04 01:07:16 +04:00
LDAPMessage * res = NULL ;
LDAPMessage * msg = NULL ;
2001-12-05 09:16:33 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2003-09-06 22:02:19 +04:00
2001-12-03 14:32:55 +03:00
DEBUG ( 3 , ( " ads: query_user_list \n " ) ) ;
2001-12-03 09:04:18 +03:00
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " query_user_list: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_OK ;
}
2003-09-06 22:02:19 +04:00
ads = ads_cached_connection ( domain ) ;
2009-08-03 00:28:49 +04:00
2003-09-06 22:02:19 +04:00
if ( ! ads ) {
domain - > last_status = NT_STATUS_SERVER_DISABLED ;
goto done ;
}
2001-12-03 09:04:18 +03:00
2006-05-05 19:44:00 +04:00
rc = ads_search_retry ( ads , & res , " (objectCategory=user) " , attrs ) ;
2012-05-18 11:40:59 +04:00
if ( ! ADS_ERR_OK ( rc ) ) {
2003-09-06 22:02:19 +04:00
DEBUG ( 1 , ( " query_user_list ads_search: %s \n " , ads_errstr ( rc ) ) ) ;
2012-05-18 11:40:59 +04:00
status = ads_ntstatus ( rc ) ;
2014-02-20 14:21:37 +04:00
goto done ;
2012-05-18 11:40:59 +04:00
} else if ( ! res ) {
DEBUG ( 1 , ( " query_user_list ads_search returned NULL res \n " ) ) ;
2003-09-05 08:46:44 +04:00
goto done ;
2003-09-06 22:02:19 +04:00
}
2001-12-03 09:04:18 +03:00
count = ads_count_replies ( ads , res ) ;
if ( count = = 0 ) {
2001-12-03 14:32:55 +03:00
DEBUG ( 1 , ( " query_user_list: No users found \n " ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-03 09:04:18 +03:00
}
2017-01-03 15:11:30 +03:00
rids = talloc_zero_array ( mem_ctx , uint32_t , count ) ;
if ( rids = = NULL ) {
2001-12-05 09:16:33 +03:00
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2001-12-03 09:04:18 +03:00
2010-07-06 13:54:31 +04:00
count = 0 ;
2001-12-03 09:04:18 +03:00
for ( msg = ads_first_entry ( ads , res ) ; msg ; msg = ads_next_entry ( ads , msg ) ) {
2017-01-03 15:11:30 +03:00
struct dom_sid user_sid ;
2015-04-24 05:04:23 +03:00
uint32_t atype ;
2016-05-31 19:52:12 +03:00
bool ok ;
2001-12-03 09:04:18 +03:00
2016-05-31 19:52:12 +03:00
ok = ads_pull_uint32 ( ads , msg , " sAMAccountType " , & atype ) ;
if ( ! ok ) {
DBG_INFO ( " Object lacks sAMAccountType attribute \n " ) ;
continue ;
}
if ( ds_atype_map ( atype ) ! = SID_NAME_USER ) {
DBG_INFO ( " Not a user account? atype=0x%x \n " , atype ) ;
2001-12-09 09:10:02 +03:00
continue ;
}
2001-12-03 09:04:18 +03:00
2017-01-03 15:11:30 +03:00
if ( ! ads_pull_sid ( ads , msg , " objectSid " , & user_sid ) ) {
2017-01-10 16:28:41 +03:00
char * dn = ads_get_dn ( ads , talloc_tos ( ) , msg ) ;
DBG_INFO ( " No sid for %s !? \n " , dn ) ;
TALLOC_FREE ( dn ) ;
2001-12-03 09:04:18 +03:00
continue ;
}
2010-07-06 13:54:31 +04:00
2017-01-03 15:11:30 +03:00
if ( ! dom_sid_in_domain ( & domain - > sid , & user_sid ) ) {
2018-12-06 21:14:20 +03:00
struct dom_sid_buf sidstr , domstr ;
2017-01-03 15:11:30 +03:00
DBG_WARNING ( " Got sid %s in domain %s \n " ,
2018-12-06 21:14:20 +03:00
dom_sid_str_buf ( & user_sid , & sidstr ) ,
dom_sid_str_buf ( & domain - > sid , & domstr ) ) ;
2010-07-06 13:54:31 +04:00
continue ;
}
2017-01-03 15:11:30 +03:00
sid_split_rid ( & user_sid , & rids [ count ] ) ;
2010-07-06 13:54:31 +04:00
count + = 1 ;
}
2017-01-03 15:11:30 +03:00
rids = talloc_realloc ( mem_ctx , rids , uint32_t , count ) ;
2017-01-11 22:52:44 +03:00
if ( prids ! = NULL ) {
* prids = rids ;
}
2001-12-03 09:04:18 +03:00
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
2001-12-03 09:04:18 +03:00
2017-01-03 15:11:30 +03:00
DBG_NOTICE ( " ads query_user_list gave %d entries \n " , count ) ;
2001-12-09 09:10:02 +03:00
2001-12-05 09:16:33 +03:00
done :
2020-05-20 13:31:53 +03:00
ads_msgfree ( ads , res ) ;
2001-12-05 09:16:33 +03:00
return status ;
2001-12-03 09:04:18 +03:00
}
/* list all domain groups */
static NTSTATUS enum_dom_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2015-04-24 05:04:23 +03:00
uint32_t * num_entries ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info * * info )
2001-12-03 09:04:18 +03:00
{
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2002-07-15 14:35:28 +04:00
const char * attrs [ ] = { " userPrincipalName " , " sAMAccountName " ,
2005-10-21 16:50:39 +04:00
" name " , " objectSid " , NULL } ;
2001-12-19 15:21:12 +03:00
int i , count ;
ADS_STATUS rc ;
2006-09-04 01:07:16 +04:00
LDAPMessage * res = NULL ;
LDAPMessage * msg = NULL ;
2001-12-05 09:16:33 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2005-10-21 16:50:39 +04:00
const char * filter ;
2007-10-19 04:40:25 +04:00
bool enum_dom_local_groups = False ;
2001-12-03 09:04:18 +03:00
2001-12-11 01:10:16 +03:00
* num_entries = 0 ;
2001-12-03 09:04:18 +03:00
DEBUG ( 3 , ( " ads: enum_dom_groups \n " ) ) ;
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " enum_dom_groups: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_OK ;
}
2005-10-21 16:50:39 +04:00
/* only grab domain local groups for our domain */
2007-05-06 23:39:41 +04:00
if ( domain - > active_directory & & strequal ( lp_realm ( ) , domain - > alt_name ) ) {
2005-10-21 16:50:39 +04:00
enum_dom_local_groups = True ;
}
/* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
* rollup - fixes :
*
* According to Section 5.1 ( 4 ) of RFC 2251 if a value of a type is it ' s
* default value , it MUST be absent . In case of extensible matching the
* " dnattr " boolean defaults to FALSE and so it must be only be present
* when set to TRUE .
*
* When it is set to FALSE and the OpenLDAP lib ( correctly ) encodes a
* filter using bitwise matching rule then the buggy AD fails to decode
* the extensible match . As a workaround set it to TRUE and thereby add
* the dnAttributes " dn " field to cope with those older AD versions .
* It should not harm and won ' t put any additional load on the AD since
* none of the dn components have a bitmask - attribute .
*
* Thanks to Ralf Haferkamp for input and testing - Guenther */
filter = talloc_asprintf ( mem_ctx , " (&(objectCategory=group)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d)))) " ,
ADS_LDAP_MATCHING_RULE_BIT_AND , GROUP_TYPE_SECURITY_ENABLED ,
ADS_LDAP_MATCHING_RULE_BIT_AND ,
enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP ) ;
if ( filter = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2003-09-06 22:02:19 +04:00
ads = ads_cached_connection ( domain ) ;
2003-06-23 09:10:07 +04:00
2003-09-06 22:02:19 +04:00
if ( ! ads ) {
domain - > last_status = NT_STATUS_SERVER_DISABLED ;
goto done ;
}
2001-12-03 09:04:18 +03:00
2005-10-21 16:50:39 +04:00
rc = ads_search_retry ( ads , & res , filter , attrs ) ;
2012-05-18 11:40:59 +04:00
if ( ! ADS_ERR_OK ( rc ) ) {
status = ads_ntstatus ( rc ) ;
2003-09-06 22:02:19 +04:00
DEBUG ( 1 , ( " enum_dom_groups ads_search: %s \n " , ads_errstr ( rc ) ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2012-05-18 11:40:59 +04:00
} else if ( ! res ) {
DEBUG ( 1 , ( " enum_dom_groups ads_search returned NULL res \n " ) ) ;
goto done ;
2003-09-06 22:02:19 +04:00
}
2001-12-03 09:04:18 +03:00
count = ads_count_replies ( ads , res ) ;
if ( count = = 0 ) {
2002-07-15 14:35:28 +04:00
DEBUG ( 1 , ( " enum_dom_groups: No groups found \n " ) ) ;
2001-12-05 09:16:33 +03:00
goto done ;
2001-12-03 09:04:18 +03:00
}
2011-06-07 05:58:39 +04:00
( * info ) = talloc_zero_array ( mem_ctx , struct wb_acct_info , count ) ;
2001-12-05 09:16:33 +03:00
if ( ! * info ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2001-12-03 09:04:18 +03:00
i = 0 ;
2009-08-03 00:28:49 +04:00
2001-12-03 09:04:18 +03:00
for ( msg = ads_first_entry ( ads , res ) ; msg ; msg = ads_next_entry ( ads , msg ) ) {
char * name , * gecos ;
2010-05-21 05:25:01 +04:00
struct dom_sid sid ;
2015-04-24 05:04:23 +03:00
uint32_t rid ;
2001-12-03 09:04:18 +03:00
2018-10-30 20:47:16 +03:00
name = ads_pull_username ( ads , ( * info ) , msg ) ;
gecos = ads_pull_string ( ads , ( * info ) , msg , " name " ) ;
2001-12-03 09:04:18 +03:00
if ( ! ads_pull_sid ( ads , msg , " objectSid " , & sid ) ) {
DEBUG ( 1 , ( " No sid for %s !? \n " , name ) ) ;
continue ;
}
2002-07-15 14:35:28 +04:00
if ( ! sid_peek_check_rid ( & domain - > sid , & sid , & rid ) ) {
2001-12-03 09:04:18 +03:00
DEBUG ( 1 , ( " No rid for %s !? \n " , name ) ) ;
continue ;
}
2018-10-30 20:47:16 +03:00
( * info ) [ i ] . acct_name = name ;
( * info ) [ i ] . acct_desc = gecos ;
2001-12-03 09:04:18 +03:00
( * info ) [ i ] . rid = rid ;
i + + ;
}
( * num_entries ) = i ;
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
2001-12-09 09:10:02 +03:00
DEBUG ( 3 , ( " ads enum_dom_groups gave %d entries \n " , ( * num_entries ) ) ) ;
2001-12-05 09:16:33 +03:00
done :
2003-09-05 08:46:44 +04:00
if ( res )
ads_msgfree ( ads , res ) ;
2001-12-03 09:04:18 +03:00
2001-12-05 09:16:33 +03:00
return status ;
2001-12-03 09:04:18 +03:00
}
2002-11-15 20:57:21 +03:00
/* list all domain local groups */
static NTSTATUS enum_local_groups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2015-04-24 05:04:23 +03:00
uint32_t * num_entries ,
2011-03-22 19:43:39 +03:00
struct wb_acct_info * * info )
2002-11-15 20:57:21 +03:00
{
/*
* This is a stub function only as we returned the domain
2003-06-23 09:10:07 +04:00
* local groups in enum_dom_groups ( ) if the domain - > native field
2002-11-15 20:57:21 +03:00
* was true . This is a simple performance optimization when
* using LDAP .
*
* if we ever need to enumerate domain local groups separately ,
2008-05-22 07:16:33 +04:00
* then this optimization in enum_dom_groups ( ) will need
2002-11-15 20:57:21 +03:00
* to be split out
*/
* num_entries = 0 ;
2009-08-03 00:28:49 +04:00
2002-11-15 20:57:21 +03:00
return NT_STATUS_OK ;
}
2008-11-21 04:26:50 +03:00
/* convert a single name to a sid in a domain - use rpc methods */
static NTSTATUS name_to_sid ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const char * domain_name ,
const char * name ,
2009-08-02 12:43:05 +04:00
uint32_t flags ,
2019-03-12 02:11:01 +03:00
const char * * pdom_name ,
2010-05-21 05:25:01 +04:00
struct dom_sid * sid ,
2008-11-21 04:26:50 +03:00
enum lsa_SidType * type )
{
2016-01-06 00:42:09 +03:00
return msrpc_methods . name_to_sid ( domain , mem_ctx , domain_name , name ,
2019-03-12 02:11:01 +03:00
flags , pdom_name , sid , type ) ;
2008-11-21 04:26:50 +03:00
}
/* convert a domain SID to a user or group name - use rpc methods */
static NTSTATUS sid_to_name ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid ,
2008-11-21 04:26:50 +03:00
char * * domain_name ,
char * * name ,
enum lsa_SidType * type )
{
2016-01-06 00:42:09 +03:00
return msrpc_methods . sid_to_name ( domain , mem_ctx , sid ,
domain_name , name , type ) ;
2008-11-21 04:26:50 +03:00
}
/* convert a list of rids to names - use rpc methods */
static NTSTATUS rids_to_names ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * sid ,
2015-04-24 05:04:23 +03:00
uint32_t * rids ,
2008-11-21 04:26:50 +03:00
size_t num_rids ,
char * * domain_name ,
char * * * names ,
enum lsa_SidType * * types )
{
2016-01-06 00:42:09 +03:00
return msrpc_methods . rids_to_names ( domain , mem_ctx , sid ,
rids , num_rids ,
domain_name , names , types ) ;
2008-11-21 04:26:50 +03:00
}
2017-03-02 16:53:47 +03:00
/* Lookup groups a user is a member of - alternate method, for when
tokenGroups are not available . */
static NTSTATUS lookup_usergroups_member ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const char * user_dn ,
struct dom_sid * primary_group ,
uint32_t * p_num_groups , struct dom_sid * * user_sids )
{
ADS_STATUS rc ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
int count ;
LDAPMessage * res = NULL ;
LDAPMessage * msg = NULL ;
char * ldap_exp ;
ADS_STRUCT * ads ;
const char * group_attrs [ ] = { " objectSid " , NULL } ;
char * escaped_dn ;
uint32_t num_groups = 0 ;
DEBUG ( 3 , ( " ads: lookup_usergroups_member \n " ) ) ;
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " lookup_usergroups_members: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
return NT_STATUS_OK ;
}
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) {
domain - > last_status = NT_STATUS_SERVER_DISABLED ;
goto done ;
}
if ( ! ( escaped_dn = escape_ldap_string ( talloc_tos ( ) , user_dn ) ) ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
ldap_exp = talloc_asprintf ( mem_ctx ,
" (&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d)) " ,
escaped_dn ,
ADS_LDAP_MATCHING_RULE_BIT_AND ,
GROUP_TYPE_SECURITY_ENABLED ) ;
if ( ! ldap_exp ) {
DEBUG ( 1 , ( " lookup_usergroups(dn=%s) asprintf failed! \n " , user_dn ) ) ;
TALLOC_FREE ( escaped_dn ) ;
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
TALLOC_FREE ( escaped_dn ) ;
rc = ads_search_retry ( ads , & res , ldap_exp , group_attrs ) ;
if ( ! ADS_ERR_OK ( rc ) ) {
DEBUG ( 1 , ( " lookup_usergroups ads_search member=%s: %s \n " , user_dn , ads_errstr ( rc ) ) ) ;
return ads_ntstatus ( rc ) ;
} else if ( ! res ) {
DEBUG ( 1 , ( " lookup_usergroups ads_search returned NULL res \n " ) ) ;
return NT_STATUS_INTERNAL_ERROR ;
}
count = ads_count_replies ( ads , res ) ;
* user_sids = NULL ;
num_groups = 0 ;
/* always add the primary group to the sid array */
status = add_sid_to_array ( mem_ctx , primary_group , user_sids ,
& num_groups ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
if ( count > 0 ) {
for ( msg = ads_first_entry ( ads , res ) ; msg ;
msg = ads_next_entry ( ads , msg ) ) {
struct dom_sid group_sid ;
if ( ! ads_pull_sid ( ads , msg , " objectSid " , & group_sid ) ) {
DEBUG ( 1 , ( " No sid for this group ?!? \n " ) ) ;
continue ;
}
/* ignore Builtin groups from ADS - Guenther */
if ( sid_check_is_in_builtin ( & group_sid ) ) {
continue ;
}
status = add_sid_to_array ( mem_ctx , & group_sid ,
user_sids , & num_groups ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
}
}
* p_num_groups = num_groups ;
status = ( user_sids ! = NULL ) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY ;
DEBUG ( 3 , ( " ads lookup_usergroups (member) succeeded for dn=%s \n " , user_dn ) ) ;
done :
if ( res )
ads_msgfree ( ads , res ) ;
return status ;
}
/* Lookup groups a user is a member of - alternate method, for when
tokenGroups are not available . */
static NTSTATUS lookup_usergroups_memberof ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const char * user_dn ,
struct dom_sid * primary_group ,
uint32_t * p_num_groups ,
struct dom_sid * * user_sids )
{
ADS_STATUS rc ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
ADS_STRUCT * ads ;
const char * attrs [ ] = { " memberOf " , NULL } ;
uint32_t num_groups = 0 ;
struct dom_sid * group_sids = NULL ;
2018-11-09 23:17:57 +03:00
size_t i ;
2017-03-02 16:53:47 +03:00
char * * strings = NULL ;
size_t num_strings = 0 , num_sids = 0 ;
DEBUG ( 3 , ( " ads: lookup_usergroups_memberof \n " ) ) ;
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " lookup_usergroups_memberof: No incoming trust for "
" domain %s \n " , domain - > name ) ) ;
return NT_STATUS_OK ;
}
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) {
domain - > last_status = NT_STATUS_SERVER_DISABLED ;
return NT_STATUS_UNSUCCESSFUL ;
}
rc = ads_search_retry_extended_dn_ranged ( ads , mem_ctx , user_dn , attrs ,
ADS_EXTENDED_DN_HEX_STRING ,
& strings , & num_strings ) ;
if ( ! ADS_ERR_OK ( rc ) ) {
DEBUG ( 1 , ( " lookup_usergroups_memberof ads_search "
" member=%s: %s \n " , user_dn , ads_errstr ( rc ) ) ) ;
return ads_ntstatus ( rc ) ;
}
* user_sids = NULL ;
num_groups = 0 ;
/* always add the primary group to the sid array */
status = add_sid_to_array ( mem_ctx , primary_group , user_sids ,
& num_groups ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
group_sids = talloc_zero_array ( mem_ctx , struct dom_sid , num_strings + 1 ) ;
if ( ! group_sids ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
for ( i = 0 ; i < num_strings ; i + + ) {
rc = ads_get_sid_from_extended_dn ( mem_ctx , strings [ i ] ,
ADS_EXTENDED_DN_HEX_STRING ,
& ( group_sids ) [ i ] ) ;
if ( ! ADS_ERR_OK ( rc ) ) {
/* ignore members without SIDs */
if ( NT_STATUS_EQUAL ( ads_ntstatus ( rc ) ,
NT_STATUS_NOT_FOUND ) ) {
continue ;
}
else {
status = ads_ntstatus ( rc ) ;
goto done ;
}
}
num_sids + + ;
}
if ( i = = 0 ) {
DEBUG ( 1 , ( " No memberOf for this user?!? \n " ) ) ;
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
for ( i = 0 ; i < num_sids ; i + + ) {
/* ignore Builtin groups from ADS - Guenther */
if ( sid_check_is_in_builtin ( & group_sids [ i ] ) ) {
continue ;
}
status = add_sid_to_array ( mem_ctx , & group_sids [ i ] , user_sids ,
& num_groups ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
}
* p_num_groups = num_groups ;
status = ( * user_sids ! = NULL ) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY ;
DEBUG ( 3 , ( " ads lookup_usergroups (memberof) succeeded for dn=%s \n " ,
user_dn ) ) ;
done :
TALLOC_FREE ( strings ) ;
TALLOC_FREE ( group_sids ) ;
return status ;
}
/* Lookup groups a user is a member of. */
static NTSTATUS lookup_usergroups ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
const struct dom_sid * sid ,
uint32_t * p_num_groups , struct dom_sid * * user_sids )
{
ADS_STRUCT * ads = NULL ;
const char * attrs [ ] = { " tokenGroups " , " primaryGroupID " , NULL } ;
ADS_STATUS rc ;
int count ;
LDAPMessage * msg = NULL ;
char * user_dn = NULL ;
struct dom_sid * sids ;
int i ;
struct dom_sid primary_group ;
uint32_t primary_group_rid ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
uint32_t num_groups = 0 ;
2018-12-14 23:09:51 +03:00
struct dom_sid_buf buf ;
2017-03-02 16:53:47 +03:00
DEBUG ( 3 , ( " ads: lookup_usergroups \n " ) ) ;
* p_num_groups = 0 ;
status = lookup_usergroups_cached ( mem_ctx , sid ,
p_num_groups , user_sids ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
return NT_STATUS_OK ;
}
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " lookup_usergroups: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
/* Tell the cache manager not to remember this one */
return NT_STATUS_SYNCHRONIZATION_REQUIRED ;
}
ads = ads_cached_connection ( domain ) ;
if ( ! ads ) {
domain - > last_status = NT_STATUS_SERVER_DISABLED ;
status = NT_STATUS_SERVER_DISABLED ;
goto done ;
}
rc = ads_search_retry_sid ( ads , & msg , sid , attrs ) ;
if ( ! ADS_ERR_OK ( rc ) ) {
status = ads_ntstatus ( rc ) ;
DEBUG ( 1 , ( " lookup_usergroups(sid=%s) ads_search tokenGroups: "
2018-12-14 23:09:51 +03:00
" %s \n " ,
dom_sid_str_buf ( sid , & buf ) ,
ads_errstr ( rc ) ) ) ;
2017-03-02 16:53:47 +03:00
goto done ;
}
count = ads_count_replies ( ads , msg ) ;
if ( count ! = 1 ) {
status = NT_STATUS_UNSUCCESSFUL ;
DEBUG ( 1 , ( " lookup_usergroups(sid=%s) ads_search tokenGroups: "
" invalid number of results (count=%d) \n " ,
2018-12-14 23:09:51 +03:00
dom_sid_str_buf ( sid , & buf ) ,
count ) ) ;
2017-03-02 16:53:47 +03:00
goto done ;
}
if ( ! msg ) {
DEBUG ( 1 , ( " lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg \n " ,
2018-12-14 23:09:51 +03:00
dom_sid_str_buf ( sid , & buf ) ) ) ;
2017-03-02 16:53:47 +03:00
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
user_dn = ads_get_dn ( ads , mem_ctx , msg ) ;
if ( user_dn = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
if ( ! ads_pull_uint32 ( ads , msg , " primaryGroupID " , & primary_group_rid ) ) {
DEBUG ( 1 , ( " %s: No primary group for sid=%s !? \n " ,
2018-12-14 23:09:51 +03:00
domain - > name ,
dom_sid_str_buf ( sid , & buf ) ) ) ;
2017-03-02 16:53:47 +03:00
goto done ;
}
sid_compose ( & primary_group , & domain - > sid , primary_group_rid ) ;
count = ads_pull_sids ( ads , mem_ctx , msg , " tokenGroups " , & sids ) ;
/* there must always be at least one group in the token,
unless we are talking to a buggy Win2k server */
/* actually this only happens when the machine account has no read
* permissions on the tokenGroup attribute - gd */
if ( count = = 0 ) {
/* no tokenGroups */
/* lookup what groups this user is a member of by DN search on
* " memberOf " */
status = lookup_usergroups_memberof ( domain , mem_ctx , user_dn ,
& primary_group ,
& num_groups , user_sids ) ;
* p_num_groups = num_groups ;
if ( NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
/* lookup what groups this user is a member of by DN search on
* " member " */
status = lookup_usergroups_member ( domain , mem_ctx , user_dn ,
& primary_group ,
& num_groups , user_sids ) ;
* p_num_groups = num_groups ;
goto done ;
}
* user_sids = NULL ;
num_groups = 0 ;
status = add_sid_to_array ( mem_ctx , & primary_group , user_sids ,
& num_groups ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
for ( i = 0 ; i < count ; i + + ) {
/* ignore Builtin groups from ADS - Guenther */
if ( sid_check_is_in_builtin ( & sids [ i ] ) ) {
continue ;
}
status = add_sid_to_array_unique ( mem_ctx , & sids [ i ] ,
user_sids , & num_groups ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
}
* p_num_groups = ( uint32_t ) num_groups ;
status = ( * user_sids ! = NULL ) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY ;
DEBUG ( 3 , ( " ads lookup_usergroups (tokenGroups) succeeded for sid=%s \n " ,
2018-12-14 23:09:51 +03:00
dom_sid_str_buf ( sid , & buf ) ) ) ;
2017-03-02 16:53:47 +03:00
done :
TALLOC_FREE ( user_dn ) ;
ads_msgfree ( ads , msg ) ;
return status ;
}
2008-11-21 04:26:50 +03:00
/* Lookup aliases a user is member of - use rpc methods */
static NTSTATUS lookup_useraliases ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2015-04-24 05:04:23 +03:00
uint32_t num_sids , const struct dom_sid * sids ,
uint32_t * num_aliases , uint32_t * * alias_rids )
2008-11-21 04:26:50 +03:00
{
2016-01-06 00:42:09 +03:00
return msrpc_methods . lookup_useraliases ( domain , mem_ctx , num_sids , sids ,
num_aliases , alias_rids ) ;
2008-11-21 04:26:50 +03:00
}
2015-06-05 14:02:10 +03:00
static NTSTATUS add_primary_group_members (
ADS_STRUCT * ads , TALLOC_CTX * mem_ctx , uint32_t rid ,
char * * * all_members , size_t * num_all_members )
{
char * filter ;
NTSTATUS status = NT_STATUS_NO_MEMORY ;
ADS_STATUS rc ;
const char * attrs [ ] = { " dn " , NULL } ;
LDAPMessage * res = NULL ;
LDAPMessage * msg ;
char * * members ;
size_t num_members ;
ads_control args ;
filter = talloc_asprintf (
mem_ctx , " (&(objectCategory=user)(primaryGroupID=%u)) " ,
( unsigned ) rid ) ;
if ( filter = = NULL ) {
goto done ;
}
args . control = ADS_EXTENDED_DN_OID ;
args . val = ADS_EXTENDED_DN_HEX_STRING ;
args . critical = True ;
rc = ads_do_search_all_args ( ads , ads - > config . bind_path ,
LDAP_SCOPE_SUBTREE , filter , attrs , & args ,
& res ) ;
if ( ! ADS_ERR_OK ( rc ) ) {
status = ads_ntstatus ( rc ) ;
DEBUG ( 1 , ( " %s: ads_search: %s \n " , __func__ , ads_errstr ( rc ) ) ) ;
goto done ;
}
if ( res = = NULL ) {
DEBUG ( 1 , ( " %s: ads_search returned NULL res \n " , __func__ ) ) ;
goto done ;
}
num_members = ads_count_replies ( ads , res ) ;
DEBUG ( 10 , ( " %s: Got %ju primary group members \n " , __func__ ,
( uintmax_t ) num_members ) ) ;
if ( num_members = = 0 ) {
status = NT_STATUS_OK ;
goto done ;
}
members = talloc_realloc ( mem_ctx , * all_members , char * ,
* num_all_members + num_members ) ;
if ( members = = NULL ) {
DEBUG ( 1 , ( " %s: talloc_realloc failed \n " , __func__ ) ) ;
goto done ;
}
* all_members = members ;
for ( msg = ads_first_entry ( ads , res ) ; msg ! = NULL ;
msg = ads_next_entry ( ads , msg ) ) {
char * dn ;
dn = ads_get_dn ( ads , members , msg ) ;
if ( dn = = NULL ) {
DEBUG ( 1 , ( " %s: ads_get_dn failed \n " , __func__ ) ) ;
continue ;
}
members [ * num_all_members ] = dn ;
* num_all_members + = 1 ;
}
status = NT_STATUS_OK ;
done :
if ( res ! = NULL ) {
ads_msgfree ( ads , res ) ;
}
TALLOC_FREE ( filter ) ;
return status ;
}
2002-07-15 14:35:28 +04:00
/*
find the members of a group , given a group rid and domain
*/
2001-12-05 07:48:51 +03:00
static NTSTATUS lookup_groupmem ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2010-05-21 05:25:01 +04:00
const struct dom_sid * group_sid ,
2009-08-28 16:25:11 +04:00
enum lsa_SidType type ,
2015-04-24 05:04:23 +03:00
uint32_t * num_names ,
2010-05-21 05:25:01 +04:00
struct dom_sid * * sid_mem , char * * * names ,
2015-04-24 05:04:23 +03:00
uint32_t * * name_types )
2001-12-05 07:48:51 +03:00
{
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
2001-12-05 09:16:33 +03:00
ADS_STRUCT * ads = NULL ;
2003-06-30 09:44:05 +04:00
char * ldap_exp ;
2001-12-05 09:16:33 +03:00
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
2007-06-01 16:24:57 +04:00
char * sidbinstr ;
2007-05-22 16:49:41 +04:00
char * * members = NULL ;
2018-11-09 23:17:57 +03:00
size_t i ;
2007-05-22 16:49:41 +04:00
size_t num_members = 0 ;
2007-04-22 19:25:54 +04:00
ads_control args ;
2010-05-21 05:25:01 +04:00
struct dom_sid * sid_mem_nocache = NULL ;
2007-05-31 02:04:42 +04:00
char * * names_nocache = NULL ;
2007-08-11 20:18:11 +04:00
enum lsa_SidType * name_types_nocache = NULL ;
2007-05-31 02:04:42 +04:00
char * * domains_nocache = NULL ; /* only needed for rpccli_lsa_lookup_sids */
2015-04-24 05:04:23 +03:00
uint32_t num_nocache = 0 ;
2007-06-01 03:55:37 +04:00
TALLOC_CTX * tmp_ctx = NULL ;
2015-06-05 14:02:10 +03:00
uint32_t rid ;
2018-12-14 23:09:51 +03:00
struct dom_sid_buf buf ;
2007-05-22 16:49:41 +04:00
2008-11-15 06:16:12 +03:00
DEBUG ( 10 , ( " ads: lookup_groupmem %s sid=%s \n " , domain - > name ,
2018-12-14 23:09:51 +03:00
dom_sid_str_buf ( group_sid , & buf ) ) ) ;
2003-06-10 04:55:37 +04:00
2001-12-05 08:35:45 +03:00
* num_names = 0 ;
2007-06-01 03:55:37 +04:00
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( ! tmp_ctx ) {
DEBUG ( 1 , ( " ads: lookup_groupmem: talloc failed \n " ) ) ;
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2015-06-05 14:02:10 +03:00
if ( ! sid_peek_rid ( group_sid , & rid ) ) {
DEBUG ( 1 , ( " %s: sid_peek_rid failed \n " , __func__ ) ) ;
status = NT_STATUS_INVALID_PARAMETER ;
goto done ;
}
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " lookup_groupmem: No incoming trust for domain %s \n " ,
2008-11-15 06:16:12 +03:00
domain - > name ) ) ;
2007-05-07 00:16:12 +04:00
return NT_STATUS_OK ;
}
2003-09-06 22:02:19 +04:00
ads = ads_cached_connection ( domain ) ;
2008-11-15 06:16:12 +03:00
2003-09-06 22:02:19 +04:00
if ( ! ads ) {
domain - > last_status = NT_STATUS_SERVER_DISABLED ;
goto done ;
}
2002-07-15 14:35:28 +04:00
2010-09-17 06:33:44 +04:00
if ( ( sidbinstr = ldap_encode_ndr_dom_sid ( talloc_tos ( ) , group_sid ) ) = = NULL ) {
2007-06-01 16:24:57 +04:00
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2003-09-06 22:02:19 +04:00
/* search for all members of the group */
2009-05-28 13:18:22 +04:00
ldap_exp = talloc_asprintf ( tmp_ctx , " (objectSid=%s) " , sidbinstr ) ;
TALLOC_FREE ( sidbinstr ) ;
if ( ldap_exp = = NULL ) {
2007-06-01 02:02:49 +04:00
DEBUG ( 1 , ( " ads: lookup_groupmem: talloc_asprintf for ldap_exp failed! \n " ) ) ;
2004-01-05 04:48:21 +03:00
status = NT_STATUS_NO_MEMORY ;
2004-01-02 00:10:35 +03:00
goto done ;
}
2004-01-01 23:30:50 +03:00
2007-04-22 19:25:54 +04:00
args . control = ADS_EXTENDED_DN_OID ;
args . val = ADS_EXTENDED_DN_HEX_STRING ;
args . critical = True ;
2004-01-05 04:48:21 +03:00
2008-11-15 06:16:12 +03:00
rc = ads_ranged_search ( ads , tmp_ctx , LDAP_SCOPE_SUBTREE , ads - > config . bind_path ,
2007-04-22 19:25:54 +04:00
ldap_exp , & args , " member " , & members , & num_members ) ;
2004-01-05 04:48:21 +03:00
2007-04-22 19:25:54 +04:00
if ( ! ADS_ERR_OK ( rc ) ) {
DEBUG ( 0 , ( " ads_ranged_search failed with: %s \n " , ads_errstr ( rc ) ) ) ;
status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
2008-11-15 06:16:12 +03:00
}
2007-06-05 14:49:05 +04:00
DEBUG ( 10 , ( " ads lookup_groupmem: got %d sids via extended dn call \n " , ( int ) num_members ) ) ;
2008-11-15 06:16:12 +03:00
2015-06-05 14:02:10 +03:00
status = add_primary_group_members ( ads , mem_ctx , rid ,
& members , & num_members ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " %s: add_primary_group_members failed: %s \n " ,
__func__ , nt_errstr ( status ) ) ) ;
goto done ;
}
DEBUG ( 10 , ( " %s: Got %d sids after adding primary group members \n " ,
__func__ , ( int ) num_members ) ) ;
2007-05-31 02:04:42 +04:00
/* Now that we have a list of sids, we need to get the
2007-05-22 16:49:41 +04:00
* lists of names and name_types belonging to these sids .
2008-11-15 06:16:12 +03:00
* even though conceptually not quite clean , we use the
* RPC call lsa_lookup_sids for this since it can handle a
2007-05-31 02:04:42 +04:00
* list of sids . ldap calls can just resolve one sid at a time .
*
* At this stage , the sids are still hidden in the exetended dn
* member output format . We actually do a little better than
* stated above : In extracting the sids from the member strings ,
* we try to resolve as many sids as possible from the
* cache . Only the rest is passed to the lsa_lookup_sids call . */
2008-11-15 06:16:12 +03:00
2007-06-01 03:58:56 +04:00
if ( num_members ) {
2011-06-07 05:58:39 +04:00
( * sid_mem ) = talloc_zero_array ( mem_ctx , struct dom_sid , num_members ) ;
( * names ) = talloc_zero_array ( mem_ctx , char * , num_members ) ;
2015-05-03 07:07:06 +03:00
( * name_types ) = talloc_zero_array ( mem_ctx , uint32_t , num_members ) ;
2011-06-07 05:58:39 +04:00
( sid_mem_nocache ) = talloc_zero_array ( tmp_ctx , struct dom_sid , num_members ) ;
2007-05-31 02:04:42 +04:00
if ( ( members = = NULL ) | | ( * sid_mem = = NULL ) | |
( * names = = NULL ) | | ( * name_types = = NULL ) | |
( sid_mem_nocache = = NULL ) )
{
2007-06-01 03:55:37 +04:00
DEBUG ( 1 , ( " ads: lookup_groupmem: talloc failed \n " ) ) ;
2007-05-31 02:04:42 +04:00
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
2007-05-22 16:49:41 +04:00
}
2007-05-31 02:04:42 +04:00
else {
( * sid_mem ) = NULL ;
( * names ) = NULL ;
( * name_types ) = NULL ;
2007-05-22 16:49:41 +04:00
}
2007-05-31 02:04:42 +04:00
for ( i = 0 ; i < num_members ; i + + ) {
2007-08-11 20:15:39 +04:00
enum lsa_SidType name_type ;
2007-05-31 02:04:42 +04:00
char * name , * domain_name ;
2010-05-21 05:25:01 +04:00
struct dom_sid sid ;
2007-05-31 02:04:42 +04:00
2008-11-16 00:07:15 +03:00
rc = ads_get_sid_from_extended_dn ( tmp_ctx , members [ i ] , args . val ,
& sid ) ;
if ( ! ADS_ERR_OK ( rc ) ) {
if ( NT_STATUS_EQUAL ( ads_ntstatus ( rc ) ,
NT_STATUS_NOT_FOUND ) ) {
/* Group members can be objects, like Exchange
* Public Folders , that don ' t have a SID . Skip
* them . */
continue ;
}
else {
status = ads_ntstatus ( rc ) ;
goto done ;
}
2007-05-31 02:04:42 +04:00
}
2008-11-15 06:16:12 +03:00
if ( lookup_cached_sid ( mem_ctx , & sid , & domain_name , & name ,
& name_type ) ) {
2007-12-15 23:11:36 +03:00
DEBUG ( 10 , ( " ads: lookup_groupmem: got sid %s from "
2018-12-14 23:09:51 +03:00
" cache \n " ,
dom_sid_str_buf ( & sid , & buf ) ) ) ;
2007-05-31 02:04:42 +04:00
sid_copy ( & ( * sid_mem ) [ * num_names ] , & sid ) ;
2008-09-22 12:39:37 +04:00
( * names ) [ * num_names ] = fill_domain_username_talloc (
* names ,
domain_name ,
name ,
true ) ;
2007-07-05 23:55:40 +04:00
2007-05-31 02:04:42 +04:00
( * name_types ) [ * num_names ] = name_type ;
2007-04-22 19:25:54 +04:00
( * num_names ) + + ;
2001-12-05 08:35:45 +03:00
}
2007-05-31 02:04:42 +04:00
else {
2007-12-15 23:11:36 +03:00
DEBUG ( 10 , ( " ads: lookup_groupmem: sid %s not found in "
2018-12-14 23:09:51 +03:00
" cache \n " ,
dom_sid_str_buf ( & sid , & buf ) ) ) ;
2007-05-31 02:04:42 +04:00
sid_copy ( & ( sid_mem_nocache ) [ num_nocache ] , & sid ) ;
num_nocache + + ;
}
2007-05-22 16:49:41 +04:00
}
2007-05-31 02:40:26 +04:00
DEBUG ( 10 , ( " ads: lookup_groupmem: %d sids found in cache, "
" %d left for lsa_lookupsids \n " , * num_names , num_nocache ) ) ;
2007-05-31 02:04:42 +04:00
/* handle sids not resolved from cache by lsa_lookup_sids */
if ( num_nocache > 0 ) {
2009-09-17 09:59:25 +04:00
status = winbindd_lookup_sids ( tmp_ctx ,
domain ,
num_nocache ,
sid_mem_nocache ,
& domains_nocache ,
& names_nocache ,
& name_types_nocache ) ;
2009-08-11 15:50:16 +04:00
2008-11-20 18:57:44 +03:00
if ( ! ( NT_STATUS_IS_OK ( status ) | |
NT_STATUS_EQUAL ( status , STATUS_SOME_UNMAPPED ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_NONE_MAPPED ) ) )
{
DEBUG ( 1 , ( " lsa_lookupsids call failed with %s "
" - retrying... \n " , nt_errstr ( status ) ) ) ;
2009-09-17 09:59:25 +04:00
status = winbindd_lookup_sids ( tmp_ctx ,
domain ,
num_nocache ,
sid_mem_nocache ,
& domains_nocache ,
& names_nocache ,
& name_types_nocache ) ;
2008-11-20 18:57:44 +03:00
}
2007-05-31 02:04:42 +04:00
if ( NT_STATUS_IS_OK ( status ) | |
2008-11-15 06:16:12 +03:00
NT_STATUS_EQUAL ( status , STATUS_SOME_UNMAPPED ) )
2007-05-31 02:04:42 +04:00
{
2008-11-15 06:16:12 +03:00
/* Copy the entries over from the "_nocache" arrays
* to the result arrays , skipping the gaps the
2007-05-31 02:04:42 +04:00
* lookup_sids call left . */
for ( i = 0 ; i < num_nocache ; i + + ) {
2008-11-15 06:16:12 +03:00
if ( ( ( names_nocache ) [ i ] ! = NULL ) & &
( ( name_types_nocache ) [ i ] ! = SID_NAME_UNKNOWN ) )
2007-05-31 02:04:42 +04:00
{
sid_copy ( & ( * sid_mem ) [ * num_names ] ,
& sid_mem_nocache [ i ] ) ;
2008-09-22 12:39:37 +04:00
( * names ) [ * num_names ] =
fill_domain_username_talloc (
* names ,
domains_nocache [ i ] ,
names_nocache [ i ] ,
true ) ;
2007-05-31 02:04:42 +04:00
( * name_types ) [ * num_names ] = name_types_nocache [ i ] ;
( * num_names ) + + ;
}
}
}
else if ( NT_STATUS_EQUAL ( status , NT_STATUS_NONE_MAPPED ) ) {
DEBUG ( 10 , ( " lookup_groupmem: lsa_lookup_sids could "
" not map any SIDs at all. \n " ) ) ;
/* Don't handle this as an error here.
* There is nothing left to do with respect to the
* overall result . . . */
}
else if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " lookup_groupmem: Error looking up %d "
" sids via rpc_lsa_lookup_sids: %s \n " ,
2007-06-05 14:49:05 +04:00
( int ) num_members , nt_errstr ( status ) ) ) ;
2007-05-31 02:04:42 +04:00
goto done ;
}
}
2001-12-05 09:16:33 +03:00
status = NT_STATUS_OK ;
2007-05-22 16:49:41 +04:00
DEBUG ( 3 , ( " ads lookup_groupmem for sid=%s succeeded \n " ,
2018-12-14 23:09:51 +03:00
dom_sid_str_buf ( group_sid , & buf ) ) ) ;
2007-05-22 16:49:41 +04:00
2001-12-05 09:16:33 +03:00
done :
2004-01-05 04:48:21 +03:00
2007-06-01 03:55:37 +04:00
TALLOC_FREE ( tmp_ctx ) ;
2007-05-31 02:04:42 +04:00
2001-12-05 09:16:33 +03:00
return status ;
2001-12-05 07:48:51 +03:00
}
2001-12-05 10:52:44 +03:00
/* find the sequence number for a domain */
2015-04-24 05:04:23 +03:00
static NTSTATUS sequence_number ( struct winbindd_domain * domain , uint32_t * seq )
2001-12-05 10:52:44 +03:00
{
ADS_STRUCT * ads = NULL ;
2001-12-19 15:21:12 +03:00
ADS_STATUS rc ;
2001-12-05 10:52:44 +03:00
2003-06-10 04:55:37 +04:00
DEBUG ( 3 , ( " ads: fetch sequence_number for %s \n " , domain - > name ) ) ;
2007-05-07 00:16:12 +04:00
if ( ! winbindd_can_contact_domain ( domain ) ) {
DEBUG ( 10 , ( " sequence: No incoming trust for domain %s \n " ,
domain - > name ) ) ;
* seq = time ( NULL ) ;
return NT_STATUS_OK ;
}
2018-02-02 18:55:01 +03:00
if ( IS_AD_DC ) {
DEBUG ( 10 , ( " sequence: Avoid LDAP connection for domain %s \n " ,
domain - > name ) ) ;
* seq = time ( NULL ) ;
return NT_STATUS_OK ;
}
2001-12-10 02:59:42 +03:00
* seq = DOM_SEQUENCE_NONE ;
2003-09-06 22:02:19 +04:00
ads = ads_cached_connection ( domain ) ;
2009-08-03 00:28:49 +04:00
2003-09-06 22:02:19 +04:00
if ( ! ads ) {
domain - > last_status = NT_STATUS_SERVER_DISABLED ;
return NT_STATUS_UNSUCCESSFUL ;
}
2001-12-05 10:52:44 +03:00
2003-09-06 22:02:19 +04:00
rc = ads_USN ( ads , seq ) ;
2009-08-03 00:28:49 +04:00
2003-09-06 22:02:19 +04:00
if ( ! ADS_ERR_OK ( rc ) ) {
2009-08-03 00:28:49 +04:00
2007-02-08 20:02:39 +03:00
/* its a dead connection, destroy it */
if ( domain - > private_data ) {
ads = ( ADS_STRUCT * ) domain - > private_data ;
ads - > is_mine = True ;
ads_destroy ( & ads ) ;
2013-02-21 23:31:28 +04:00
ads_kdestroy ( WINBIND_CCACHE_NAME ) ;
2007-02-08 20:02:39 +03:00
domain - > private_data = NULL ;
}
2003-09-06 22:02:19 +04:00
}
2001-12-19 15:21:12 +03:00
return ads_ntstatus ( rc ) ;
2001-12-05 10:52:44 +03:00
}
2008-11-21 04:26:50 +03:00
/* find the lockout policy of a domain - use rpc methods */
static NTSTATUS lockout_policy ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
struct samr_DomInfo12 * policy )
{
2016-01-06 00:42:09 +03:00
return msrpc_methods . lockout_policy ( domain , mem_ctx , policy ) ;
2008-11-21 04:26:50 +03:00
}
/* find the password policy of a domain - use rpc methods */
static NTSTATUS password_policy ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
struct samr_DomInfo1 * policy )
{
2016-01-06 00:42:09 +03:00
return msrpc_methods . password_policy ( domain , mem_ctx , policy ) ;
2008-11-21 04:26:50 +03:00
}
2001-12-10 05:25:19 +03:00
/* get a list of trusted domains */
static NTSTATUS trusted_domains ( struct winbindd_domain * domain ,
TALLOC_CTX * mem_ctx ,
2009-12-28 17:51:36 +03:00
struct netr_DomainTrustList * trusts )
2001-12-10 05:25:19 +03:00
{
2003-07-31 09:43:47 +04:00
NTSTATUS result = NT_STATUS_UNSUCCESSFUL ;
2011-01-12 13:55:34 +03:00
WERROR werr ;
2018-11-09 23:17:57 +03:00
uint32_t i ;
2015-05-03 07:07:06 +03:00
uint32_t flags ;
2005-06-09 02:10:34 +04:00
struct rpc_pipe_client * cli ;
2007-05-06 23:17:30 +04:00
int ret_count ;
2011-01-12 13:55:34 +03:00
struct dcerpc_binding_handle * b ;
2009-08-03 00:28:49 +04:00
2003-06-10 04:55:37 +04:00
DEBUG ( 3 , ( " ads: trusted_domains \n " ) ) ;
2009-12-28 17:51:36 +03:00
ZERO_STRUCTP ( trusts ) ;
2005-06-09 02:10:34 +04:00
2007-05-06 23:17:30 +04:00
/* If this is our primary domain or a root in our forest,
query for all trusts . If not , then just look for domain
trusts in the target forest */
2009-12-30 12:25:41 +03:00
if ( domain - > primary | | domain_is_forest_root ( domain ) ) {
2008-01-29 19:49:38 +03:00
flags = NETR_TRUST_FLAG_OUTBOUND |
NETR_TRUST_FLAG_INBOUND |
NETR_TRUST_FLAG_IN_FOREST ;
2007-05-06 23:17:30 +04:00
} else {
2008-01-29 19:49:38 +03:00
flags = NETR_TRUST_FLAG_IN_FOREST ;
2007-05-06 23:17:30 +04:00
}
2005-09-30 21:13:37 +04:00
result = cm_connect_netlogon ( domain , & cli ) ;
2005-06-09 02:10:34 +04:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
DEBUG ( 5 , ( " trusted_domains: Could not open a connection to %s "
" for PIPE_NETLOGON (%s) \n " ,
2004-01-05 05:04:37 +03:00
domain - > name , nt_errstr ( result ) ) ) ;
2003-07-31 09:43:47 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2008-01-29 16:59:20 +03:00
2011-01-12 13:55:34 +03:00
b = cli - > binding_handle ;
result = dcerpc_netr_DsrEnumerateDomainTrusts ( b , mem_ctx ,
2008-04-19 23:56:43 +04:00
cli - > desthost ,
2008-01-29 16:59:20 +03:00
flags ,
2009-12-28 17:51:36 +03:00
trusts ,
2011-01-12 13:55:34 +03:00
& werr ) ;
2009-12-28 17:27:42 +03:00
if ( ! NT_STATUS_IS_OK ( result ) ) {
return result ;
}
2011-01-12 13:55:34 +03:00
if ( ! W_ERROR_IS_OK ( werr ) ) {
return werror_to_ntstatus ( werr ) ;
}
2009-12-28 17:51:36 +03:00
if ( trusts - > count = = 0 ) {
2009-12-28 17:27:42 +03:00
return NT_STATUS_OK ;
}
2003-06-23 09:10:07 +04:00
2009-12-28 17:27:42 +03:00
/* Copy across names and sids */
2009-08-03 00:28:49 +04:00
2009-12-28 17:27:42 +03:00
ret_count = 0 ;
2009-12-28 17:51:36 +03:00
for ( i = 0 ; i < trusts - > count ; i + + ) {
struct netr_DomainTrust * trust = & trusts - > array [ i ] ;
2009-12-28 17:27:42 +03:00
struct winbindd_domain d ;
2008-09-05 02:13:12 +04:00
2009-12-28 17:27:42 +03:00
ZERO_STRUCT ( d ) ;
2007-05-06 23:17:30 +04:00
2009-12-28 17:27:42 +03:00
/*
* drop external trusts if this is not our primary
* domain . This means that the returned number of
* domains may be less that the ones actually trusted
* by the DC .
*/
2009-08-03 00:28:49 +04:00
2009-12-28 17:51:36 +03:00
if ( ( trust - > trust_attributes
2019-09-12 17:39:10 +03:00
& LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN ) & &
2009-12-28 17:27:42 +03:00
! domain - > primary )
{
DEBUG ( 10 , ( " trusted_domains: Skipping external trusted "
" domain %s because it is outside of our "
" primary domain \n " ,
2009-12-28 17:51:36 +03:00
trust - > netbios_name ) ) ;
2009-12-28 17:27:42 +03:00
continue ;
}
2009-07-30 03:13:44 +04:00
2009-12-28 17:27:42 +03:00
/* add to the trusted domain cache */
2007-05-06 23:17:30 +04:00
2013-02-18 19:36:22 +04:00
d . name = discard_const_p ( char , trust - > netbios_name ) ;
d . alt_name = discard_const_p ( char , trust - > dns_name ) ;
2009-12-28 17:51:36 +03:00
if ( trust - > sid ) {
sid_copy ( & d . sid , trust - > sid ) ;
2009-12-28 17:27:42 +03:00
} else {
sid_copy ( & d . sid , & global_sid_NULL ) ;
}
2007-05-06 23:17:30 +04:00
2009-12-28 17:27:42 +03:00
if ( domain - > primary ) {
DEBUG ( 10 , ( " trusted_domains(ads): Searching "
" trusted domain list of %s and storing "
" trust flags for domain %s \n " ,
domain - > name , d . alt_name ) ) ;
2009-12-28 17:51:36 +03:00
d . domain_flags = trust - > trust_flags ;
d . domain_type = trust - > trust_type ;
d . domain_trust_attribs = trust - > trust_attributes ;
2009-12-28 17:27:42 +03:00
wcache_tdc_add_domain ( & d ) ;
ret_count + + ;
2009-12-30 12:25:41 +03:00
} else if ( domain_is_forest_root ( domain ) ) {
2009-12-28 17:27:42 +03:00
/* Check if we already have this record. If
* we are following our forest root that is not
* our primary domain , we want to keep trust
* flags from the perspective of our primary
* domain not our forest root . */
struct winbindd_tdc_domain * exist = NULL ;
exist = wcache_tdc_fetch_domain (
2009-12-28 17:51:36 +03:00
talloc_tos ( ) , trust - > netbios_name ) ;
2009-12-28 17:27:42 +03:00
if ( ! exist ) {
2008-03-26 02:50:58 +03:00
DEBUG ( 10 , ( " trusted_domains(ads): Searching "
2009-12-28 17:27:42 +03:00
" trusted domain list of %s and "
" storing trust flags for domain "
" %s \n " , domain - > name , d . alt_name ) ) ;
2009-12-28 17:51:36 +03:00
d . domain_flags = trust - > trust_flags ;
d . domain_type = trust - > trust_type ;
2009-12-28 17:27:42 +03:00
d . domain_trust_attribs =
2009-12-28 17:51:36 +03:00
trust - > trust_attributes ;
2008-01-04 22:35:41 +03:00
2008-03-26 02:50:58 +03:00
wcache_tdc_add_domain ( & d ) ;
ret_count + + ;
2009-12-28 17:27:42 +03:00
}
TALLOC_FREE ( exist ) ;
} else {
/* This gets a little tricky. If we are
following a transitive forest trust , then
innerit the flags , type , and attribs from
the domain we queried to make sure we don ' t
record the view of the trust from the wrong
side . Always view it from the side of our
primary domain . - - jerry */
struct winbindd_tdc_domain * parent = NULL ;
DEBUG ( 10 , ( " trusted_domains(ads): Searching "
" trusted domain list of %s and inheriting "
" trust flags for domain %s \n " ,
domain - > name , d . alt_name ) ) ;
2009-12-28 17:51:36 +03:00
parent = wcache_tdc_fetch_domain ( talloc_tos ( ) ,
domain - > name ) ;
2009-12-28 17:27:42 +03:00
if ( parent ) {
d . domain_flags = parent - > trust_flags ;
d . domain_type = parent - > trust_type ;
d . domain_trust_attribs = parent - > trust_attribs ;
2008-03-26 02:50:58 +03:00
} else {
2009-12-28 17:27:42 +03:00
d . domain_flags = domain - > domain_flags ;
d . domain_type = domain - > domain_type ;
d . domain_trust_attribs =
domain - > domain_trust_attribs ;
2008-01-04 22:35:41 +03:00
}
2009-12-28 17:27:42 +03:00
TALLOC_FREE ( parent ) ;
2003-07-31 09:43:47 +04:00
2017-03-02 10:13:57 +03:00
/*
* We need to pass the modified properties
* to the caller .
*/
trust - > trust_flags = d . domain_flags ;
trust - > trust_type = d . domain_type ;
trust - > trust_attributes = d . domain_trust_attribs ;
2009-12-28 17:27:42 +03:00
wcache_tdc_add_domain ( & d ) ;
ret_count + + ;
}
2003-06-23 09:10:07 +04:00
}
2003-07-31 09:43:47 +04:00
return result ;
2001-12-10 05:25:19 +03:00
}
2001-12-03 14:11:14 +03:00
/* the ADS backend methods are exposed via this structure */
2001-12-03 09:04:18 +03:00
struct winbindd_methods ads_methods = {
2001-12-10 09:05:21 +03:00
True ,
2001-12-03 14:32:55 +03:00
query_user_list ,
2001-12-03 11:17:46 +03:00
enum_dom_groups ,
2002-11-15 20:57:21 +03:00
enum_local_groups ,
2008-11-21 04:26:50 +03:00
name_to_sid ,
sid_to_name ,
rids_to_names ,
2017-03-02 16:53:47 +03:00
lookup_usergroups ,
2008-11-21 04:26:50 +03:00
lookup_useraliases ,
2001-12-05 10:52:44 +03:00
lookup_groupmem ,
2001-12-10 05:25:19 +03:00
sequence_number ,
2008-11-21 04:26:50 +03:00
lockout_policy ,
password_policy ,
2001-12-10 05:25:19 +03:00
trusted_domains ,
2001-12-03 09:04:18 +03:00
} ;
# endif