2007-08-28 15:01:23 +00:00
/*
Unix SMB / CIFS implementation .
2008-01-11 15:32:20 +01:00
dsgetdcname
2007-08-28 15:01:23 +00:00
Copyright ( C ) Gerald Carter 2006
2008-01-07 23:05:58 +01:00
Copyright ( C ) Guenther Deschner 2007 - 2008
2007-08-28 15:01:23 +00: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
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"
# define DSGETDCNAME_FMT "DSGETDCNAME / DOMAIN / %s"
/* 15 minutes */
# define DSGETDCNAME_CACHE_TTL 60*15
struct ip_service_name {
2007-10-29 13:34:00 -07:00
struct sockaddr_storage ss ;
2007-08-28 15:01:23 +00:00
unsigned port ;
const char * hostname ;
} ;
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void debug_dsdcinfo_flags ( int lvl , uint32_t flags )
{
DEBUG ( lvl , ( " debug_dsdcinfo_flags: 0x%08x \n \t " , flags ) ) ;
if ( flags & DS_FORCE_REDISCOVERY )
DEBUGADD ( lvl , ( " DS_FORCE_REDISCOVERY " ) ) ;
if ( flags & 0x000000002 )
DEBUGADD ( lvl , ( " 0x00000002 " ) ) ;
if ( flags & 0x000000004 )
DEBUGADD ( lvl , ( " 0x00000004 " ) ) ;
if ( flags & 0x000000008 )
DEBUGADD ( lvl , ( " 0x00000008 " ) ) ;
if ( flags & DS_DIRECTORY_SERVICE_REQUIRED )
DEBUGADD ( lvl , ( " DS_DIRECTORY_SERVICE_REQUIRED " ) ) ;
if ( flags & DS_DIRECTORY_SERVICE_PREFERRED )
DEBUGADD ( lvl , ( " DS_DIRECTORY_SERVICE_PREFERRED " ) ) ;
if ( flags & DS_GC_SERVER_REQUIRED )
DEBUGADD ( lvl , ( " DS_GC_SERVER_REQUIRED " ) ) ;
if ( flags & DS_PDC_REQUIRED )
DEBUGADD ( lvl , ( " DS_PDC_REQUIRED " ) ) ;
if ( flags & DS_BACKGROUND_ONLY )
DEBUGADD ( lvl , ( " DS_BACKGROUND_ONLY " ) ) ;
if ( flags & DS_IP_REQUIRED )
DEBUGADD ( lvl , ( " DS_IP_REQUIRED " ) ) ;
if ( flags & DS_KDC_REQUIRED )
DEBUGADD ( lvl , ( " DS_KDC_REQUIRED " ) ) ;
if ( flags & DS_TIMESERV_REQUIRED )
DEBUGADD ( lvl , ( " DS_TIMESERV_REQUIRED " ) ) ;
if ( flags & DS_WRITABLE_REQUIRED )
DEBUGADD ( lvl , ( " DS_WRITABLE_REQUIRED " ) ) ;
if ( flags & DS_GOOD_TIMESERV_PREFERRED )
DEBUGADD ( lvl , ( " DS_GOOD_TIMESERV_PREFERRED " ) ) ;
if ( flags & DS_AVOID_SELF )
DEBUGADD ( lvl , ( " DS_AVOID_SELF " ) ) ;
if ( flags & DS_ONLY_LDAP_NEEDED )
DEBUGADD ( lvl , ( " DS_ONLY_LDAP_NEEDED " ) ) ;
if ( flags & DS_IS_FLAT_NAME )
DEBUGADD ( lvl , ( " DS_IS_FLAT_NAME " ) ) ;
if ( flags & DS_IS_DNS_NAME )
DEBUGADD ( lvl , ( " DS_IS_DNS_NAME " ) ) ;
if ( flags & 0x00040000 )
DEBUGADD ( lvl , ( " 0x00040000 " ) ) ;
if ( flags & 0x00080000 )
DEBUGADD ( lvl , ( " 0x00080000 " ) ) ;
if ( flags & 0x00100000 )
DEBUGADD ( lvl , ( " 0x00100000 " ) ) ;
if ( flags & 0x00200000 )
DEBUGADD ( lvl , ( " 0x00200000 " ) ) ;
if ( flags & 0x00400000 )
DEBUGADD ( lvl , ( " 0x00400000 " ) ) ;
if ( flags & 0x00800000 )
DEBUGADD ( lvl , ( " 0x00800000 " ) ) ;
if ( flags & 0x01000000 )
DEBUGADD ( lvl , ( " 0x01000000 " ) ) ;
if ( flags & 0x02000000 )
DEBUGADD ( lvl , ( " 0x02000000 " ) ) ;
if ( flags & 0x04000000 )
DEBUGADD ( lvl , ( " 0x04000000 " ) ) ;
if ( flags & 0x08000000 )
DEBUGADD ( lvl , ( " 0x08000000 " ) ) ;
if ( flags & 0x10000000 )
DEBUGADD ( lvl , ( " 0x10000000 " ) ) ;
if ( flags & 0x20000000 )
DEBUGADD ( lvl , ( " 0x20000000 " ) ) ;
if ( flags & DS_RETURN_DNS_NAME )
DEBUGADD ( lvl , ( " DS_RETURN_DNS_NAME " ) ) ;
if ( flags & DS_RETURN_FLAT_NAME )
DEBUGADD ( lvl , ( " DS_RETURN_FLAT_NAME " ) ) ;
if ( flags )
DEBUGADD ( lvl , ( " \n " ) ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 15:32:20 +01:00
static char * dsgetdcname_cache_key ( TALLOC_CTX * mem_ctx , const char * domain )
2007-08-28 15:01:23 +00:00
{
if ( ! mem_ctx | | ! domain ) {
return NULL ;
}
2007-11-24 17:27:54 +01:00
return talloc_asprintf_strupper_m ( mem_ctx , DSGETDCNAME_FMT , domain ) ;
2007-08-28 15:01:23 +00:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 15:32:20 +01:00
static NTSTATUS dsgetdcname_cache_delete ( TALLOC_CTX * mem_ctx ,
2007-08-28 15:01:23 +00:00
const char * domain_name )
{
char * key ;
if ( ! gencache_init ( ) ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2008-01-11 15:32:20 +01:00
key = dsgetdcname_cache_key ( mem_ctx , domain_name ) ;
2007-08-28 15:01:23 +00:00
if ( ! key ) {
return NT_STATUS_NO_MEMORY ;
}
if ( ! gencache_del ( key ) ) {
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 15:32:20 +01:00
static NTSTATUS dsgetdcname_cache_store ( TALLOC_CTX * mem_ctx ,
2007-08-28 15:01:23 +00:00
const char * domain_name ,
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * info )
2007-08-28 15:01:23 +00:00
{
time_t expire_time ;
char * key ;
2008-01-11 15:32:20 +01:00
bool ret = false ;
2007-08-28 15:01:23 +00:00
DATA_BLOB blob ;
2008-03-28 13:36:31 +01:00
enum ndr_err_code ndr_err ;
2007-08-28 15:01:23 +00:00
if ( ! gencache_init ( ) ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2008-01-11 15:32:20 +01:00
key = dsgetdcname_cache_key ( mem_ctx , domain_name ) ;
2007-08-28 15:01:23 +00:00
if ( ! key ) {
return NT_STATUS_NO_MEMORY ;
}
expire_time = time ( NULL ) + DSGETDCNAME_CACHE_TTL ;
2008-03-28 13:36:31 +01:00
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , info ,
( ndr_push_flags_fn_t ) ndr_push_netr_DsRGetDCNameInfo ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return ndr_map_error2ntstatus ( ndr_err ) ;
2007-08-28 15:01:23 +00:00
}
if ( gencache_lock_entry ( key ) ! = 0 ) {
data_blob_free ( & blob ) ;
return NT_STATUS_LOCK_NOT_GRANTED ;
}
ret = gencache_set_data_blob ( key , & blob , expire_time ) ;
data_blob_free ( & blob ) ;
gencache_unlock_entry ( key ) ;
return ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 15:32:20 +01:00
static NTSTATUS dsgetdcname_cache_refresh ( TALLOC_CTX * mem_ctx ,
2007-08-28 15:01:23 +00:00
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * info )
2007-08-28 15:01:23 +00:00
{
struct cldap_netlogon_reply r ;
/* check if matching entry is older then 15 minutes, if yes, send
* CLDAP / MAILSLOT ping again and store the cached data */
ZERO_STRUCT ( r ) ;
2008-02-28 12:30:18 +01:00
if ( ads_cldap_netlogon ( info - > dc_unc ,
2007-08-28 15:01:23 +00:00
info - > domain_name , & r ) ) {
2008-01-11 15:32:20 +01:00
dsgetdcname_cache_delete ( mem_ctx , domain_name ) ;
2007-08-28 15:01:23 +00:00
2008-01-11 15:32:20 +01:00
return dsgetdcname_cache_store ( mem_ctx ,
2007-08-28 15:01:23 +00:00
info - > domain_name ,
info ) ;
}
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 15:32:20 +01:00
# define RETURN_ON_FALSE(x) if (!x) return false;
2007-08-28 15:01:23 +00:00
2007-10-18 17:40:25 -07:00
static bool check_cldap_reply_required_flags ( uint32_t ret_flags ,
2007-08-28 15:01:23 +00:00
uint32_t req_flags )
{
if ( req_flags & DS_PDC_REQUIRED )
RETURN_ON_FALSE ( ret_flags & ADS_PDC ) ;
if ( req_flags & DS_GC_SERVER_REQUIRED )
RETURN_ON_FALSE ( ret_flags & ADS_GC ) ;
if ( req_flags & DS_ONLY_LDAP_NEEDED )
RETURN_ON_FALSE ( ret_flags & ADS_LDAP ) ;
if ( ( req_flags & DS_DIRECTORY_SERVICE_REQUIRED ) | |
( req_flags & DS_DIRECTORY_SERVICE_PREFERRED ) )
RETURN_ON_FALSE ( ret_flags & ADS_DS ) ;
if ( req_flags & DS_KDC_REQUIRED )
RETURN_ON_FALSE ( ret_flags & ADS_KDC ) ;
if ( req_flags & DS_TIMESERV_REQUIRED )
RETURN_ON_FALSE ( ret_flags & ADS_TIMESERV ) ;
if ( req_flags & DS_WRITABLE_REQUIRED )
RETURN_ON_FALSE ( ret_flags & ADS_WRITABLE ) ;
2008-01-11 15:32:20 +01:00
return true ;
2007-08-28 15:01:23 +00:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 15:32:20 +01:00
static NTSTATUS dsgetdcname_cache_fetch ( TALLOC_CTX * mem_ctx ,
2007-08-28 15:01:23 +00:00
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
2008-03-28 13:36:31 +01:00
struct netr_DsRGetDCNameInfo * * info_p ,
2007-10-18 17:40:25 -07:00
bool * expired )
2007-08-28 15:01:23 +00:00
{
char * key ;
DATA_BLOB blob ;
2008-03-28 13:36:31 +01:00
enum ndr_err_code ndr_err ;
struct netr_DsRGetDCNameInfo * info ;
2007-08-28 15:01:23 +00:00
if ( ! gencache_init ( ) ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2008-01-11 15:32:20 +01:00
key = dsgetdcname_cache_key ( mem_ctx , domain_name ) ;
2007-08-28 15:01:23 +00:00
if ( ! key ) {
return NT_STATUS_NO_MEMORY ;
}
if ( ! gencache_get_data_blob ( key , & blob , expired ) ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2008-03-28 13:36:31 +01:00
info = TALLOC_ZERO_P ( mem_ctx , struct netr_DsRGetDCNameInfo ) ;
if ( ! info ) {
return NT_STATUS_NO_MEMORY ;
2007-08-28 15:01:23 +00:00
}
2008-03-28 13:36:31 +01:00
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , info ,
( ndr_pull_flags_fn_t ) ndr_pull_netr_DsRGetDCNameInfo ) ;
2007-08-28 15:01:23 +00:00
data_blob_free ( & blob ) ;
2008-03-28 13:36:31 +01:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
dsgetdcname_cache_delete ( mem_ctx , domain_name ) ;
return ndr_map_error2ntstatus ( ndr_err ) ;
}
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( netr_DsRGetDCNameInfo , info ) ;
}
2007-08-28 15:01:23 +00:00
/* check flags */
2008-03-28 13:36:31 +01:00
if ( ! check_cldap_reply_required_flags ( info - > dc_flags , flags ) ) {
2007-08-28 15:01:23 +00:00
DEBUG ( 10 , ( " invalid flags \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( ( flags & DS_IP_REQUIRED ) & &
2008-03-28 13:36:31 +01:00
( info - > dc_address_type ! = DS_ADDRESS_TYPE_INET ) ) {
2007-08-28 15:01:23 +00:00
return NT_STATUS_INVALID_PARAMETER_MIX ;
}
2008-03-28 13:36:31 +01:00
* info_p = info ;
2007-08-28 15:01:23 +00:00
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 15:32:20 +01:00
static NTSTATUS dsgetdcname_cached ( TALLOC_CTX * mem_ctx ,
2007-08-28 15:01:23 +00:00
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 15:01:23 +00:00
{
NTSTATUS status ;
2008-01-11 15:32:20 +01:00
bool expired = false ;
2007-08-28 15:01:23 +00:00
2008-01-11 15:32:20 +01:00
status = dsgetdcname_cache_fetch ( mem_ctx , domain_name , domain_guid ,
2007-08-28 15:01:23 +00:00
flags , site_name , info , & expired ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-11 15:32:20 +01:00
DEBUG ( 10 , ( " dsgetdcname_cached: cache fetch failed with: %s \n " ,
2007-08-28 15:01:23 +00:00
nt_errstr ( status ) ) ) ;
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
if ( flags & DS_BACKGROUND_ONLY ) {
return status ;
}
if ( expired ) {
2008-01-11 15:32:20 +01:00
status = dsgetdcname_cache_refresh ( mem_ctx , domain_name ,
2007-08-28 15:01:23 +00:00
domain_guid , flags ,
site_name , * info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-18 17:40:25 -07:00
static bool check_allowed_required_flags ( uint32_t flags )
2007-08-28 15:01:23 +00:00
{
uint32_t return_type = flags & ( DS_RETURN_FLAT_NAME | DS_RETURN_DNS_NAME ) ;
uint32_t offered_type = flags & ( DS_IS_FLAT_NAME | DS_IS_DNS_NAME ) ;
uint32_t query_type = flags & ( DS_BACKGROUND_ONLY | DS_FORCE_REDISCOVERY ) ;
/* FIXME: check for DSGETDC_VALID_FLAGS and check for excluse bits
* ( DS_PDC_REQUIRED , DS_KDC_REQUIRED , DS_GC_SERVER_REQUIRED ) */
2007-08-28 15:31:42 +00:00
debug_dsdcinfo_flags ( 10 , flags ) ;
2007-08-28 15:01:23 +00:00
if ( return_type = = ( DS_RETURN_FLAT_NAME | DS_RETURN_DNS_NAME ) ) {
2008-01-11 15:32:20 +01:00
return false ;
2007-08-28 15:01:23 +00:00
}
if ( offered_type = = ( DS_IS_DNS_NAME | DS_IS_FLAT_NAME ) ) {
2008-01-11 15:32:20 +01:00
return false ;
2007-08-28 15:01:23 +00:00
}
if ( query_type = = ( DS_BACKGROUND_ONLY | DS_FORCE_REDISCOVERY ) ) {
2008-01-11 15:32:20 +01:00
return false ;
2007-08-28 15:01:23 +00:00
}
#if 0
if ( ( flags & DS_RETURN_DNS_NAME ) & & ( ! ( flags & DS_IP_REQUIRED ) ) ) {
printf ( " gd: here5 \n " ) ;
2008-01-11 15:32:20 +01:00
return false ;
2007-08-28 15:01:23 +00:00
}
# endif
2008-01-11 15:32:20 +01:00
return true ;
2007-08-28 15:01:23 +00:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS discover_dc_netbios ( TALLOC_CTX * mem_ctx ,
const char * domain_name ,
uint32_t flags ,
struct ip_service_name * * returned_dclist ,
int * return_count )
{
if ( lp_disable_netbios ( ) ) {
return NT_STATUS_NOT_SUPPORTED ;
}
/* FIXME: code here */
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS discover_dc_dns ( TALLOC_CTX * mem_ctx ,
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
struct ip_service_name * * returned_dclist ,
int * return_count )
{
int i , j ;
NTSTATUS status ;
struct dns_rr_srv * dcs = NULL ;
int numdcs = 0 ;
int numaddrs = 0 ;
2008-04-16 23:56:03 +02:00
struct ip_service_name * dclist = NULL ;
int count = 0 ;
2007-08-28 15:01:23 +00:00
if ( ( ! ( flags & DS_DIRECTORY_SERVICE_REQUIRED ) ) & &
( ! ( flags & DS_KDC_REQUIRED ) ) & &
( ! ( flags & DS_GC_SERVER_REQUIRED ) ) & &
( ! ( flags & DS_PDC_REQUIRED ) ) ) {
DEBUG ( 1 , ( " discover_dc_dns: invalid flags \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( flags & DS_PDC_REQUIRED ) {
status = ads_dns_query_pdc ( mem_ctx , domain_name ,
& dcs , & numdcs ) ;
} else if ( flags & DS_GC_SERVER_REQUIRED ) {
status = ads_dns_query_gcs ( mem_ctx , domain_name , site_name ,
& dcs , & numdcs ) ;
} else if ( flags & DS_KDC_REQUIRED ) {
status = ads_dns_query_kdcs ( mem_ctx , domain_name , site_name ,
& dcs , & numdcs ) ;
} else if ( flags & DS_DIRECTORY_SERVICE_REQUIRED ) {
status = ads_dns_query_dcs ( mem_ctx , domain_name , site_name ,
& dcs , & numdcs ) ;
} else if ( domain_guid ) {
status = ads_dns_query_dcs_guid ( mem_ctx , domain_name ,
domain_guid , & dcs , & numdcs ) ;
} else {
/* FIXME: ? */
DEBUG ( 1 , ( " discover_dc_dns: not enough input \n " ) ) ;
status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( numdcs = = 0 ) {
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
for ( i = 0 ; i < numdcs ; i + + ) {
numaddrs + = MAX ( dcs [ i ] . num_ips , 1 ) ;
}
2008-04-16 23:56:03 +02:00
dclist = TALLOC_ZERO_ARRAY ( mem_ctx ,
struct ip_service_name ,
numaddrs ) ;
if ( ! dclist ) {
2007-08-28 15:01:23 +00:00
return NT_STATUS_NO_MEMORY ;
}
/* now unroll the list of IP addresses */
* return_count = 0 ;
i = 0 ;
j = 0 ;
2008-04-16 23:56:03 +02:00
while ( ( i < numdcs ) & & ( count < numaddrs ) ) {
struct ip_service_name * r = & dclist [ count ] ;
2007-08-28 15:01:23 +00:00
r - > port = dcs [ i ] . port ;
r - > hostname = dcs [ i ] . hostname ;
if ( ! ( flags & DS_IP_REQUIRED ) ) {
2008-04-16 23:56:03 +02:00
count + + ;
2007-08-28 15:01:23 +00:00
continue ;
}
/* If we don't have an IP list for a name, lookup it up */
2007-10-29 13:34:00 -07:00
if ( ! dcs [ i ] . ss_s ) {
interpret_string_addr ( & r - > ss , dcs [ i ] . hostname , 0 ) ;
2007-08-28 15:01:23 +00:00
i + + ;
j = 0 ;
} else {
/* use the IP addresses from the SRV sresponse */
if ( j > = dcs [ i ] . num_ips ) {
i + + ;
j = 0 ;
continue ;
}
2007-10-29 13:34:00 -07:00
r - > ss = dcs [ i ] . ss_s [ j ] ;
2007-08-28 15:01:23 +00:00
j + + ;
}
/* make sure it is a valid IP. I considered checking the
* negative connection cache , but this is the wrong place for
* it . Maybe only as a hac . After think about it , if all of
* the IP addresses retuend from DNS are dead , what hope does a
* netbios name lookup have ? The standard reason for falling
* back to netbios lookups is that our DNS server doesn ' t know
* anything about the DC ' s - - jerry */
2007-10-29 13:34:00 -07:00
if ( ! is_zero_addr ( & r - > ss ) ) {
2008-04-16 23:56:03 +02:00
count + + ;
2007-08-28 15:01:23 +00:00
continue ;
}
}
2008-04-16 23:56:03 +02:00
* returned_dclist = dclist ;
* return_count = count ;
if ( count > 0 ) {
return NT_STATUS_OK ;
}
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
2007-08-28 15:01:23 +00:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS make_domain_controller_info ( TALLOC_CTX * mem_ctx ,
2008-02-28 12:30:18 +01:00
const char * dc_unc ,
const char * dc_address ,
uint32_t dc_address_type ,
2007-08-28 15:01:23 +00:00
const struct GUID * domain_guid ,
const char * domain_name ,
2008-02-28 12:30:18 +01:00
const char * forest_name ,
2007-08-28 15:01:23 +00:00
uint32_t flags ,
const char * dc_site_name ,
const char * client_site_name ,
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * * info_out )
2007-08-28 15:01:23 +00:00
{
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * info ;
2007-08-28 15:01:23 +00:00
2008-02-28 12:30:18 +01:00
info = TALLOC_ZERO_P ( mem_ctx , struct netr_DsRGetDCNameInfo ) ;
2007-08-28 15:01:23 +00:00
NT_STATUS_HAVE_NO_MEMORY ( info ) ;
2008-02-28 12:30:18 +01:00
if ( dc_unc ) {
info - > dc_unc = talloc_strdup ( mem_ctx , dc_unc ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > dc_unc ) ;
2007-08-28 15:01:23 +00:00
}
2008-02-28 12:30:18 +01:00
if ( dc_address ) {
info - > dc_address = talloc_strdup ( mem_ctx , dc_address ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > dc_address ) ;
2007-08-28 15:01:23 +00:00
}
2008-02-28 12:30:18 +01:00
info - > dc_address_type = dc_address_type ;
2007-08-28 15:01:23 +00:00
if ( domain_guid ) {
2008-02-28 12:30:18 +01:00
info - > domain_guid = * domain_guid ;
2007-08-28 15:01:23 +00:00
}
if ( domain_name ) {
info - > domain_name = talloc_strdup ( mem_ctx , domain_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > domain_name ) ;
}
2008-02-28 12:30:18 +01:00
if ( forest_name ) {
info - > forest_name = talloc_strdup ( mem_ctx , forest_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > forest_name ) ;
2007-08-28 15:01:23 +00:00
}
2008-02-28 12:30:18 +01:00
info - > dc_flags = flags ;
2007-08-28 15:01:23 +00:00
if ( dc_site_name ) {
info - > dc_site_name = talloc_strdup ( mem_ctx , dc_site_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > dc_site_name ) ;
}
if ( client_site_name ) {
info - > client_site_name = talloc_strdup ( mem_ctx ,
client_site_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > client_site_name ) ;
}
* info_out = info ;
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS process_dc_dns ( TALLOC_CTX * mem_ctx ,
const char * domain_name ,
uint32_t flags ,
2008-04-16 23:56:03 +02:00
struct ip_service_name * dclist ,
2007-08-28 15:01:23 +00:00
int num_dcs ,
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 15:01:23 +00:00
{
int i = 0 ;
2008-01-11 15:32:20 +01:00
bool valid_dc = false ;
2007-08-28 15:01:23 +00:00
struct cldap_netlogon_reply r ;
const char * dc_hostname , * dc_domain_name ;
const char * dc_address ;
uint32_t dc_address_type ;
uint32_t dc_flags ;
struct GUID dc_guid ;
for ( i = 0 ; i < num_dcs ; i + + ) {
ZERO_STRUCT ( r ) ;
2008-04-16 23:56:03 +02:00
DEBUG ( 10 , ( " LDAP ping to %s \n " , dclist [ i ] . hostname ) ) ;
if ( ( ads_cldap_netlogon ( dclist [ i ] . hostname ,
2007-08-28 15:01:23 +00:00
domain_name , & r ) ) & &
( check_cldap_reply_required_flags ( r . flags , flags ) ) ) {
2008-01-11 15:32:20 +01:00
valid_dc = true ;
2007-08-28 15:01:23 +00:00
break ;
}
continue ;
}
if ( ! valid_dc ) {
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
dc_flags = r . flags ;
if ( flags & DS_RETURN_FLAT_NAME ) {
if ( ! strlen ( r . netbios_hostname ) | | ! strlen ( r . netbios_domain ) ) {
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
dc_hostname = r . netbios_hostname ;
dc_domain_name = r . netbios_domain ;
} else if ( flags & DS_RETURN_DNS_NAME ) {
if ( ! strlen ( r . hostname ) | | ! strlen ( r . domain ) ) {
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
dc_hostname = r . hostname ;
dc_domain_name = r . domain ;
2008-02-28 12:30:18 +01:00
dc_flags | = DS_DNS_DOMAIN | DS_DNS_CONTROLLER ;
2007-08-28 15:01:23 +00:00
} else {
/* FIXME */
dc_hostname = r . hostname ;
dc_domain_name = r . domain ;
2008-02-28 12:30:18 +01:00
dc_flags | = DS_DNS_DOMAIN | DS_DNS_CONTROLLER ;
2007-08-28 15:01:23 +00:00
}
if ( flags & DS_IP_REQUIRED ) {
2007-10-29 13:34:00 -07:00
char addr [ INET6_ADDRSTRLEN ] ;
2008-04-16 23:56:03 +02:00
print_sockaddr ( addr , sizeof ( addr ) , & dclist [ i ] . ss ) ;
2007-08-28 15:01:23 +00:00
dc_address = talloc_asprintf ( mem_ctx , " \\ \\ %s " ,
2007-10-29 13:34:00 -07:00
addr ) ;
2008-02-28 12:30:18 +01:00
dc_address_type = DS_ADDRESS_TYPE_INET ;
2007-08-28 15:01:23 +00:00
} else {
dc_address = talloc_asprintf ( mem_ctx , " \\ \\ %s " ,
r . netbios_hostname ) ;
2008-02-28 12:30:18 +01:00
dc_address_type = DS_ADDRESS_TYPE_NETBIOS ;
2007-08-28 15:01:23 +00:00
}
NT_STATUS_HAVE_NO_MEMORY ( dc_address ) ;
2007-11-25 10:10:52 +01:00
smb_uuid_unpack ( r . guid , & dc_guid ) ;
2007-08-28 15:01:23 +00:00
if ( r . forest ) {
2008-02-28 12:30:18 +01:00
dc_flags | = DS_DNS_FOREST ;
2007-08-28 15:01:23 +00:00
}
return make_domain_controller_info ( mem_ctx ,
dc_hostname ,
dc_address ,
dc_address_type ,
& dc_guid ,
dc_domain_name ,
r . forest ,
dc_flags ,
r . server_site_name ,
r . client_site_name ,
info ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS process_dc_netbios ( TALLOC_CTX * mem_ctx ,
const char * domain_name ,
uint32_t flags ,
struct ip_service_name * * dclist ,
int num_dcs ,
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 15:01:23 +00:00
{
/* FIXME: code here */
return NT_STATUS_NOT_SUPPORTED ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 15:32:20 +01:00
static NTSTATUS dsgetdcname_rediscover ( TALLOC_CTX * mem_ctx ,
2007-08-28 15:01:23 +00:00
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 15:01:23 +00:00
{
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
struct ip_service_name * dclist ;
int num_dcs ;
2008-01-11 15:32:20 +01:00
DEBUG ( 10 , ( " dsgetdcname_rediscover \n " ) ) ;
2007-08-28 15:01:23 +00:00
if ( flags & DS_IS_FLAT_NAME ) {
status = discover_dc_netbios ( mem_ctx , domain_name , flags ,
& dclist , & num_dcs ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return process_dc_netbios ( mem_ctx , domain_name , flags ,
& dclist , num_dcs , info ) ;
}
if ( flags & DS_IS_DNS_NAME ) {
status = discover_dc_dns ( mem_ctx , domain_name , domain_guid ,
flags , site_name , & dclist , & num_dcs ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return process_dc_dns ( mem_ctx , domain_name , flags ,
2008-04-16 23:56:03 +02:00
dclist , num_dcs , info ) ;
2007-08-28 15:01:23 +00:00
}
status = discover_dc_dns ( mem_ctx , domain_name , domain_guid , flags ,
site_name , & dclist , & num_dcs ) ;
if ( NT_STATUS_IS_OK ( status ) & & num_dcs ! = 0 ) {
2008-04-16 23:56:03 +02:00
status = process_dc_dns ( mem_ctx , domain_name , flags , dclist ,
2007-08-28 15:01:23 +00:00
num_dcs , info ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
status = discover_dc_netbios ( mem_ctx , domain_name , flags , & dclist ,
& num_dcs ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
return process_dc_netbios ( mem_ctx , domain_name , flags , & dclist ,
num_dcs , info ) ;
}
/********************************************************************
2008-01-26 01:39:33 +01:00
dsgetdcname .
2008-01-07 23:05:58 +01:00
2008-01-26 01:39:33 +01:00
This will be the only public function here .
2007-08-28 15:01:23 +00:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-26 01:39:33 +01:00
NTSTATUS dsgetdcname ( TALLOC_CTX * mem_ctx ,
const char * domain_name ,
struct GUID * domain_guid ,
const char * site_name ,
uint32_t flags ,
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 15:01:23 +00:00
{
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
2008-02-28 12:30:18 +01:00
struct netr_DsRGetDCNameInfo * myinfo = NULL ;
2007-08-28 15:01:23 +00:00
2008-01-26 01:39:33 +01:00
DEBUG ( 10 , ( " dsgetdcname: domain_name: %s, "
" domain_guid: %s, site_name: %s, flags: 0x%08x \n " ,
domain_name ,
domain_guid ? GUID_string ( mem_ctx , domain_guid ) : " (null) " ,
site_name , flags ) ) ;
2007-08-28 15:01:23 +00:00
* info = NULL ;
if ( ! check_allowed_required_flags ( flags ) ) {
DEBUG ( 0 , ( " invalid flags specified \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( flags & DS_FORCE_REDISCOVERY ) {
goto rediscover ;
}
2008-01-11 15:32:20 +01:00
status = dsgetdcname_cached ( mem_ctx , domain_name , domain_guid ,
2007-08-28 15:01:23 +00:00
flags , site_name , & myinfo ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
* info = myinfo ;
return status ;
}
if ( flags & DS_BACKGROUND_ONLY ) {
return status ;
}
rediscover :
2008-01-11 15:32:20 +01:00
status = dsgetdcname_rediscover ( mem_ctx , domain_name ,
2007-08-28 15:01:23 +00:00
domain_guid , flags , site_name ,
& myinfo ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2008-01-11 15:32:20 +01:00
dsgetdcname_cache_store ( mem_ctx , domain_name , myinfo ) ;
2007-08-28 15:01:23 +00:00
* info = myinfo ;
}
return status ;
}