2008-09-19 21:27:15 +04:00
/*
* idmap_adex : Domain search interface
*
* Copyright ( C ) Gerald ( Jerry ) Carter 2007 - 2008
*
* 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 2 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 , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "idmap_adex.h"
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_IDMAP
struct dc_info {
struct dc_info * prev , * next ;
char * dns_name ;
struct likewise_cell * domain_cell ;
} ;
static struct dc_info * _dc_server_list = NULL ;
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct dc_info * dc_list_head ( void )
{
return _dc_server_list ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS dc_add_domain ( const char * domain )
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL ;
struct dc_info * dc = NULL ;
2008-10-06 20:34:45 +04:00
if ( ! domain ) {
return NT_STATUS_INVALID_PARAMETER ;
}
DEBUG ( 10 , ( " dc_add_domain: Attempting to add domain %s \n " , domain ) ) ;
2008-09-19 21:27:15 +04:00
/* Check for duplicates */
dc = dc_list_head ( ) ;
while ( dc ) {
if ( strequal ( dc - > dns_name , domain ) )
break ;
dc = dc - > next ;
}
if ( dc ) {
DEBUG ( 10 , ( " dc_add_domain: %s already in list \n " , domain ) ) ;
return NT_STATUS_OK ;
}
dc = TALLOC_ZERO_P ( NULL , struct dc_info ) ;
BAIL_ON_PTR_ERROR ( dc , nt_status ) ;
dc - > dns_name = talloc_strdup ( dc , domain ) ;
BAIL_ON_PTR_ERROR ( dc - > dns_name , nt_status ) ;
DLIST_ADD_END ( _dc_server_list , dc , struct dc_info * ) ;
nt_status = NT_STATUS_OK ;
2008-10-06 20:34:45 +04:00
DEBUG ( 5 , ( " dc_add_domain: Successfully added %s \n " , domain ) ) ;
2008-09-19 21:27:15 +04:00
done :
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
talloc_destroy ( dc ) ;
DEBUG ( 0 , ( " LWI: Failed to add new DC connection for %s (%s) \n " ,
domain , nt_errstr ( nt_status ) ) ) ;
}
return nt_status ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void dc_server_list_destroy ( void )
{
struct dc_info * dc = dc_list_head ( ) ;
while ( dc ) {
struct dc_info * p = dc - > next ;
cell_destroy ( dc - > domain_cell ) ;
talloc_destroy ( dc ) ;
dc = p ;
}
return ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS domain_init_list ( void )
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL ;
struct winbindd_tdc_domain * domains = NULL ;
size_t num_domains = 0 ;
int i ;
if ( _dc_server_list ! = NULL ) {
dc_server_list_destroy ( ) ;
}
/* Add our domain */
nt_status = dc_add_domain ( lp_realm ( ) ) ;
BAIL_ON_NTSTATUS_ERROR ( nt_status ) ;
if ( ! wcache_tdc_fetch_list ( & domains , & num_domains ) ) {
nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
BAIL_ON_NTSTATUS_ERROR ( nt_status ) ;
}
/* Add all domains with an incoming trust path */
for ( i = 0 ; i < num_domains ; i + + ) {
uint32_t flags = ( NETR_TRUST_FLAG_INBOUND | NETR_TRUST_FLAG_IN_FOREST ) ;
/* We just require one of the flags to be set here */
if ( domains [ i ] . trust_flags & flags ) {
nt_status = dc_add_domain ( domains [ i ] . dns_name ) ;
BAIL_ON_NTSTATUS_ERROR ( nt_status ) ;
}
}
nt_status = NT_STATUS_OK ;
done :
if ( ! NT_STATUS_IS_OK ( nt_status ) ) {
DEBUG ( 2 , ( " LWI: Failed to initialize DC list (%s) \n " ,
nt_errstr ( nt_status ) ) ) ;
}
TALLOC_FREE ( domains ) ;
return nt_status ;
}
/********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS dc_do_search ( struct dc_info * dc ,
const char * search_base ,
int scope ,
const char * expr ,
const char * * attrs ,
LDAPMessage * * msg )
{
ADS_STATUS status = ADS_ERROR_NT ( NT_STATUS_UNSUCCESSFUL ) ;
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL ;
status = cell_do_search ( dc - > domain_cell , search_base ,
scope , expr , attrs , msg ) ;
nt_status = ads_ntstatus ( status ) ;
return nt_status ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct dc_info * dc_find_domain ( const char * dns_domain )
{
struct dc_info * dc = dc_list_head ( ) ;
if ( ! dc )
return NULL ;
while ( dc ) {
if ( strequal ( dc - > dns_name , dns_domain ) ) {
return dc ;
}
dc = dc - > next ;
}
return NULL ;
}
/**********************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS dc_search_domains ( struct likewise_cell * * cell ,
LDAPMessage * * msg ,
const char * dn ,
const DOM_SID * sid )
{
NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL ;
TALLOC_CTX * frame = talloc_stackframe ( ) ;
char * dns_domain ;
const char * attrs [ ] = { " * " , NULL } ;
struct dc_info * dc = NULL ;
const char * base = NULL ;
if ( ! dn | | ! * dn ) {
nt_status = NT_STATUS_INVALID_PARAMETER ;
BAIL_ON_NTSTATUS_ERROR ( nt_status ) ;
}
dns_domain = cell_dn_to_dns ( dn ) ;
BAIL_ON_PTR_ERROR ( dns_domain , nt_status ) ;
if ( ( dc = dc_find_domain ( dns_domain ) ) = = NULL ) {
nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE ;
BAIL_ON_NTSTATUS_ERROR ( nt_status ) ;
}
/* Reparse the cell settings for the domain if necessary */
if ( ! dc - > domain_cell ) {
char * base_dn ;
base_dn = ads_build_dn ( dc - > dns_name ) ;
BAIL_ON_PTR_ERROR ( base_dn , nt_status ) ;
nt_status = cell_connect_dn ( & dc - > domain_cell , base_dn ) ;
SAFE_FREE ( base_dn ) ;
BAIL_ON_NTSTATUS_ERROR ( nt_status ) ;
nt_status = cell_lookup_settings ( dc - > domain_cell ) ;
BAIL_ON_NTSTATUS_ERROR ( nt_status ) ;
/* By definition this is already part of a larger
forest - wide search scope */
cell_set_flags ( dc - > domain_cell , LWCELL_FLAG_SEARCH_FOREST ) ;
}
/* Check whether we are operating in non-schema or RFC2307
mode */
if ( cell_flags ( dc - > domain_cell ) & LWCELL_FLAG_USE_RFC2307_ATTRS ) {
nt_status = dc_do_search ( dc , dn , LDAP_SCOPE_BASE ,
" (objectclass=*) " , attrs , msg ) ;
} else {
const char * sid_str = NULL ;
char * filter = NULL ;
sid_str = sid_string_talloc ( frame , sid ) ;
BAIL_ON_PTR_ERROR ( sid_str , nt_status ) ;
filter = talloc_asprintf ( frame , " (keywords=backLink=%s) " ,
sid_str ) ;
BAIL_ON_PTR_ERROR ( filter , nt_status ) ;
base = cell_search_base ( dc - > domain_cell ) ;
BAIL_ON_PTR_ERROR ( base , nt_status ) ;
nt_status = dc_do_search ( dc , base , LDAP_SCOPE_SUBTREE ,
filter , attrs , msg ) ;
}
BAIL_ON_NTSTATUS_ERROR ( nt_status ) ;
* cell = dc - > domain_cell ;
done :
talloc_destroy ( CONST_DISCARD ( char * , base ) ) ;
talloc_destroy ( frame ) ;
return nt_status ;
}