2007-08-28 19:01:23 +04:00
/*
Unix SMB / CIFS implementation .
2008-01-11 17:32:20 +03:00
dsgetdcname
2007-08-28 19:01:23 +04:00
Copyright ( C ) Gerald Carter 2006
2008-01-08 01:05:58 +03:00
Copyright ( C ) Guenther Deschner 2007 - 2008
2007-08-28 19:01:23 +04: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 23:34:00 +03:00
struct sockaddr_storage ss ;
2007-08-28 19:01:23 +04: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 17:32:20 +03:00
static char * dsgetdcname_cache_key ( TALLOC_CTX * mem_ctx , const char * domain )
2007-08-28 19:01:23 +04:00
{
if ( ! mem_ctx | | ! domain ) {
return NULL ;
}
2007-11-24 19:27:54 +03:00
return talloc_asprintf_strupper_m ( mem_ctx , DSGETDCNAME_FMT , domain ) ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 17:32:20 +03:00
static NTSTATUS dsgetdcname_cache_delete ( TALLOC_CTX * mem_ctx ,
2007-08-28 19:01:23 +04:00
const char * domain_name )
{
char * key ;
if ( ! gencache_init ( ) ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2008-01-11 17:32:20 +03:00
key = dsgetdcname_cache_key ( mem_ctx , domain_name ) ;
2007-08-28 19:01:23 +04:00
if ( ! key ) {
return NT_STATUS_NO_MEMORY ;
}
if ( ! gencache_del ( key ) ) {
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 17:32:20 +03:00
static NTSTATUS dsgetdcname_cache_store ( TALLOC_CTX * mem_ctx ,
2007-08-28 19:01:23 +04:00
const char * domain_name ,
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * info )
2007-08-28 19:01:23 +04:00
{
time_t expire_time ;
char * key ;
2008-01-11 17:32:20 +03:00
bool ret = false ;
2007-08-28 19:01:23 +04:00
DATA_BLOB blob ;
2008-03-28 15:36:31 +03:00
enum ndr_err_code ndr_err ;
2007-08-28 19:01:23 +04:00
if ( ! gencache_init ( ) ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2008-01-11 17:32:20 +03:00
key = dsgetdcname_cache_key ( mem_ctx , domain_name ) ;
2007-08-28 19:01:23 +04:00
if ( ! key ) {
return NT_STATUS_NO_MEMORY ;
}
expire_time = time ( NULL ) + DSGETDCNAME_CACHE_TTL ;
2008-03-28 15:36:31 +03: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 19:01:23 +04: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 17:32:20 +03:00
static NTSTATUS dsgetdcname_cache_refresh ( TALLOC_CTX * mem_ctx ,
2007-08-28 19:01:23 +04:00
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * info )
2007-08-28 19:01:23 +04:00
{
2008-05-07 17:49:09 +04:00
uint32_t nt_version = NETLOGON_VERSION_1 ;
2007-08-28 19:01:23 +04:00
/* check if matching entry is older then 15 minutes, if yes, send
* CLDAP / MAILSLOT ping again and store the cached data */
2008-04-21 21:47:13 +04:00
if ( ads_cldap_netlogon ( mem_ctx , info - > dc_unc ,
2008-05-07 17:49:09 +04:00
info - > domain_name , & nt_version , NULL ) ) {
2007-08-28 19:01:23 +04:00
2008-01-11 17:32:20 +03:00
dsgetdcname_cache_delete ( mem_ctx , domain_name ) ;
2007-08-28 19:01:23 +04:00
2008-01-11 17:32:20 +03:00
return dsgetdcname_cache_store ( mem_ctx ,
2007-08-28 19:01:23 +04:00
info - > domain_name ,
info ) ;
}
return NT_STATUS_INVALID_NETWORK_RESPONSE ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-05-07 18:49:39 +04:00
static uint32_t get_cldap_reply_server_flags ( union nbt_cldap_netlogon * r ,
uint32_t nt_version )
{
switch ( nt_version & 0x000000ff ) {
case 0 :
case 1 :
return 0 ;
case 2 :
case 3 :
return r - > logon3 . server_type ;
case 4 :
case 5 :
case 6 :
case 7 :
return r - > logon5 . server_type ;
case 8 :
case 9 :
case 10 :
case 11 :
case 12 :
case 13 :
case 14 :
case 15 :
return r - > logon13 . server_type ;
default :
return r - > logon29 . server_type ;
}
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 17:32:20 +03:00
# define RETURN_ON_FALSE(x) if (!x) return false;
2007-08-28 19:01:23 +04:00
2007-10-19 04:40:25 +04:00
static bool check_cldap_reply_required_flags ( uint32_t ret_flags ,
2007-08-28 19:01:23 +04:00
uint32_t req_flags )
{
2008-05-07 20:38:37 +04:00
if ( ret_flags = = 0 ) {
return true ;
}
2007-08-28 19:01:23 +04:00
if ( req_flags & DS_PDC_REQUIRED )
2008-04-21 21:59:27 +04:00
RETURN_ON_FALSE ( ret_flags & NBT_SERVER_PDC ) ;
2007-08-28 19:01:23 +04:00
if ( req_flags & DS_GC_SERVER_REQUIRED )
2008-04-21 21:59:27 +04:00
RETURN_ON_FALSE ( ret_flags & NBT_SERVER_GC ) ;
2007-08-28 19:01:23 +04:00
if ( req_flags & DS_ONLY_LDAP_NEEDED )
2008-04-21 21:59:27 +04:00
RETURN_ON_FALSE ( ret_flags & NBT_SERVER_LDAP ) ;
2007-08-28 19:01:23 +04:00
if ( ( req_flags & DS_DIRECTORY_SERVICE_REQUIRED ) | |
( req_flags & DS_DIRECTORY_SERVICE_PREFERRED ) )
2008-04-21 21:59:27 +04:00
RETURN_ON_FALSE ( ret_flags & NBT_SERVER_DS ) ;
2007-08-28 19:01:23 +04:00
if ( req_flags & DS_KDC_REQUIRED )
2008-04-21 21:59:27 +04:00
RETURN_ON_FALSE ( ret_flags & NBT_SERVER_KDC ) ;
2007-08-28 19:01:23 +04:00
if ( req_flags & DS_TIMESERV_REQUIRED )
2008-04-21 21:59:27 +04:00
RETURN_ON_FALSE ( ret_flags & NBT_SERVER_TIMESERV ) ;
2007-08-28 19:01:23 +04:00
if ( req_flags & DS_WRITABLE_REQUIRED )
2008-04-21 21:59:27 +04:00
RETURN_ON_FALSE ( ret_flags & NBT_SERVER_WRITABLE ) ;
2007-08-28 19:01:23 +04:00
2008-01-11 17:32:20 +03:00
return true ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 17:32:20 +03:00
static NTSTATUS dsgetdcname_cache_fetch ( TALLOC_CTX * mem_ctx ,
2007-08-28 19:01:23 +04:00
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
2008-03-28 15:36:31 +03:00
struct netr_DsRGetDCNameInfo * * info_p ,
2007-10-19 04:40:25 +04:00
bool * expired )
2007-08-28 19:01:23 +04:00
{
char * key ;
DATA_BLOB blob ;
2008-03-28 15:36:31 +03:00
enum ndr_err_code ndr_err ;
struct netr_DsRGetDCNameInfo * info ;
2007-08-28 19:01:23 +04:00
if ( ! gencache_init ( ) ) {
return NT_STATUS_INTERNAL_DB_ERROR ;
}
2008-01-11 17:32:20 +03:00
key = dsgetdcname_cache_key ( mem_ctx , domain_name ) ;
2007-08-28 19:01:23 +04: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 15:36:31 +03:00
info = TALLOC_ZERO_P ( mem_ctx , struct netr_DsRGetDCNameInfo ) ;
if ( ! info ) {
return NT_STATUS_NO_MEMORY ;
2007-08-28 19:01:23 +04:00
}
2008-03-28 15:36:31 +03:00
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , info ,
( ndr_pull_flags_fn_t ) ndr_pull_netr_DsRGetDCNameInfo ) ;
2007-08-28 19:01:23 +04:00
data_blob_free ( & blob ) ;
2008-03-28 15:36:31 +03: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 19:01:23 +04:00
/* check flags */
2008-03-28 15:36:31 +03:00
if ( ! check_cldap_reply_required_flags ( info - > dc_flags , flags ) ) {
2007-08-28 19:01:23 +04:00
DEBUG ( 10 , ( " invalid flags \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( ( flags & DS_IP_REQUIRED ) & &
2008-03-28 15:36:31 +03:00
( info - > dc_address_type ! = DS_ADDRESS_TYPE_INET ) ) {
2007-08-28 19:01:23 +04:00
return NT_STATUS_INVALID_PARAMETER_MIX ;
}
2008-03-28 15:36:31 +03:00
* info_p = info ;
2007-08-28 19:01:23 +04:00
return NT_STATUS_OK ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 17:32:20 +03:00
static NTSTATUS dsgetdcname_cached ( TALLOC_CTX * mem_ctx ,
2007-08-28 19:01:23 +04:00
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 19:01:23 +04:00
{
NTSTATUS status ;
2008-01-11 17:32:20 +03:00
bool expired = false ;
2007-08-28 19:01:23 +04:00
2008-01-11 17:32:20 +03:00
status = dsgetdcname_cache_fetch ( mem_ctx , domain_name , domain_guid ,
2007-08-28 19:01:23 +04:00
flags , site_name , info , & expired ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-01-11 17:32:20 +03:00
DEBUG ( 10 , ( " dsgetdcname_cached: cache fetch failed with: %s \n " ,
2007-08-28 19:01:23 +04:00
nt_errstr ( status ) ) ) ;
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
if ( flags & DS_BACKGROUND_ONLY ) {
return status ;
}
if ( expired ) {
2008-01-11 17:32:20 +03:00
status = dsgetdcname_cache_refresh ( mem_ctx , domain_name ,
2007-08-28 19:01:23 +04:00
domain_guid , flags ,
site_name , * info ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-19 04:40:25 +04:00
static bool check_allowed_required_flags ( uint32_t flags )
2007-08-28 19:01:23 +04: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 19:31:42 +04:00
debug_dsdcinfo_flags ( 10 , flags ) ;
2007-08-28 19:01:23 +04:00
if ( return_type = = ( DS_RETURN_FLAT_NAME | DS_RETURN_DNS_NAME ) ) {
2008-01-11 17:32:20 +03:00
return false ;
2007-08-28 19:01:23 +04:00
}
if ( offered_type = = ( DS_IS_DNS_NAME | DS_IS_FLAT_NAME ) ) {
2008-01-11 17:32:20 +03:00
return false ;
2007-08-28 19:01:23 +04:00
}
if ( query_type = = ( DS_BACKGROUND_ONLY | DS_FORCE_REDISCOVERY ) ) {
2008-01-11 17:32:20 +03:00
return false ;
2007-08-28 19:01:23 +04:00
}
#if 0
if ( ( flags & DS_RETURN_DNS_NAME ) & & ( ! ( flags & DS_IP_REQUIRED ) ) ) {
printf ( " gd: here5 \n " ) ;
2008-01-11 17:32:20 +03:00
return false ;
2007-08-28 19:01:23 +04:00
}
# endif
2008-01-11 17:32:20 +03:00
return true ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS discover_dc_netbios ( TALLOC_CTX * mem_ctx ,
const char * domain_name ,
uint32_t flags ,
struct ip_service_name * * returned_dclist ,
2008-04-22 02:04:25 +04:00
int * returned_count )
2007-08-28 19:01:23 +04:00
{
2008-04-22 02:04:25 +04:00
NTSTATUS status ;
enum nbt_name_type name_type = NBT_NAME_LOGON ;
struct ip_service * iplist ;
int i ;
struct ip_service_name * dclist = NULL ;
int count ;
* returned_dclist = NULL ;
* returned_count = 0 ;
2007-08-28 19:01:23 +04:00
if ( lp_disable_netbios ( ) ) {
return NT_STATUS_NOT_SUPPORTED ;
}
2008-04-22 02:04:25 +04:00
if ( flags & DS_PDC_REQUIRED ) {
name_type = NBT_NAME_PDC ;
}
2007-08-28 19:01:23 +04:00
2008-04-22 02:04:25 +04:00
status = internal_resolve_name ( domain_name , name_type , NULL ,
& iplist , & count ,
" lmhosts wins bcast " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " discover_dc_netbios: failed to find DC \n " ) ) ;
return status ;
}
dclist = TALLOC_ZERO_ARRAY ( mem_ctx , struct ip_service_name , count ) ;
if ( ! dclist ) {
return NT_STATUS_NO_MEMORY ;
}
for ( i = 0 ; i < count ; i + + ) {
char addr [ INET6_ADDRSTRLEN ] ;
struct ip_service_name * r = & dclist [ i ] ;
print_sockaddr ( addr , sizeof ( addr ) ,
& iplist [ i ] . ss ) ;
r - > ss = iplist [ i ] . ss ;
r - > port = iplist [ i ] . port ;
r - > hostname = talloc_strdup ( mem_ctx , addr ) ;
if ( ! r - > hostname ) {
return NT_STATUS_NO_MEMORY ;
}
}
* returned_dclist = dclist ;
* returned_count = count ;
return NT_STATUS_OK ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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-17 01:56:03 +04:00
struct ip_service_name * dclist = NULL ;
int count = 0 ;
2007-08-28 19:01:23 +04:00
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 {
2008-05-07 16:09:41 +04:00
status = ads_dns_query_dcs ( mem_ctx , domain_name , site_name ,
& dcs , & numdcs ) ;
2007-08-28 19:01:23 +04:00
}
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-17 01:56:03 +04:00
dclist = TALLOC_ZERO_ARRAY ( mem_ctx ,
struct ip_service_name ,
numaddrs ) ;
if ( ! dclist ) {
2007-08-28 19:01:23 +04:00
return NT_STATUS_NO_MEMORY ;
}
/* now unroll the list of IP addresses */
* return_count = 0 ;
i = 0 ;
j = 0 ;
2008-04-17 01:56:03 +04:00
while ( ( i < numdcs ) & & ( count < numaddrs ) ) {
struct ip_service_name * r = & dclist [ count ] ;
2007-08-28 19:01:23 +04:00
2008-04-22 02:05:05 +04:00
r - > port = dcs [ count ] . port ;
r - > hostname = dcs [ count ] . hostname ;
2007-08-28 19:01:23 +04:00
/* If we don't have an IP list for a name, lookup it up */
2007-10-29 23:34:00 +03:00
if ( ! dcs [ i ] . ss_s ) {
interpret_string_addr ( & r - > ss , dcs [ i ] . hostname , 0 ) ;
2007-08-28 19:01:23 +04: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 23:34:00 +03:00
r - > ss = dcs [ i ] . ss_s [ j ] ;
2007-08-28 19:01:23 +04: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 23:34:00 +03:00
if ( ! is_zero_addr ( & r - > ss ) ) {
2008-04-17 01:56:03 +04:00
count + + ;
2007-08-28 19:01:23 +04:00
continue ;
}
}
2008-04-17 01:56:03 +04:00
* returned_dclist = dclist ;
* return_count = count ;
if ( count > 0 ) {
return NT_STATUS_OK ;
}
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static NTSTATUS make_domain_controller_info ( TALLOC_CTX * mem_ctx ,
2008-02-28 14:30:18 +03:00
const char * dc_unc ,
const char * dc_address ,
uint32_t dc_address_type ,
2007-08-28 19:01:23 +04:00
const struct GUID * domain_guid ,
const char * domain_name ,
2008-02-28 14:30:18 +03:00
const char * forest_name ,
2007-08-28 19:01:23 +04:00
uint32_t flags ,
const char * dc_site_name ,
const char * client_site_name ,
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * * info_out )
2007-08-28 19:01:23 +04:00
{
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * info ;
2007-08-28 19:01:23 +04:00
2008-02-28 14:30:18 +03:00
info = TALLOC_ZERO_P ( mem_ctx , struct netr_DsRGetDCNameInfo ) ;
2007-08-28 19:01:23 +04:00
NT_STATUS_HAVE_NO_MEMORY ( info ) ;
2008-02-28 14:30:18 +03:00
if ( dc_unc ) {
info - > dc_unc = talloc_strdup ( mem_ctx , dc_unc ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > dc_unc ) ;
2007-08-28 19:01:23 +04:00
}
2008-02-28 14:30:18 +03:00
if ( dc_address ) {
2008-05-07 23:04:10 +04:00
if ( ! ( dc_address [ 0 ] = = ' \\ ' & & dc_address [ 1 ] = = ' \\ ' ) ) {
info - > dc_address = talloc_asprintf ( mem_ctx , " \\ \\ %s " ,
dc_address ) ;
} else {
info - > dc_address = talloc_strdup ( mem_ctx , dc_address ) ;
}
2008-02-28 14:30:18 +03:00
NT_STATUS_HAVE_NO_MEMORY ( info - > dc_address ) ;
2007-08-28 19:01:23 +04:00
}
2008-02-28 14:30:18 +03:00
info - > dc_address_type = dc_address_type ;
2007-08-28 19:01:23 +04:00
if ( domain_guid ) {
2008-02-28 14:30:18 +03:00
info - > domain_guid = * domain_guid ;
2007-08-28 19:01:23 +04:00
}
if ( domain_name ) {
info - > domain_name = talloc_strdup ( mem_ctx , domain_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > domain_name ) ;
}
2008-02-28 14:30:18 +03:00
if ( forest_name ) {
info - > forest_name = talloc_strdup ( mem_ctx , forest_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > forest_name ) ;
2008-05-07 20:36:03 +04:00
flags | = DS_DNS_FOREST ;
2007-08-28 19:01:23 +04:00
}
2008-02-28 14:30:18 +03:00
info - > dc_flags = flags ;
2007-08-28 19:01:23 +04: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 ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-05-07 20:36:03 +04:00
static NTSTATUS make_dc_info_from_cldap_reply ( TALLOC_CTX * mem_ctx ,
uint32_t flags ,
struct sockaddr_storage * ss ,
uint32_t nt_version ,
union nbt_cldap_netlogon * r ,
struct netr_DsRGetDCNameInfo * * info )
{
const char * dc_hostname , * dc_domain_name ;
const char * dc_address = NULL ;
const char * dc_forest = NULL ;
uint32_t dc_address_type = 0 ;
uint32_t dc_flags = 0 ;
struct GUID * dc_domain_guid = NULL ;
const char * dc_server_site = NULL ;
const char * dc_client_site = NULL ;
char addr [ INET6_ADDRSTRLEN ] ;
2008-05-07 23:04:10 +04:00
if ( ss ) {
print_sockaddr ( addr , sizeof ( addr ) , ss ) ;
dc_address = addr ;
dc_address_type = DS_ADDRESS_TYPE_INET ;
}
2008-05-07 20:36:03 +04:00
switch ( nt_version & 0x000000ff ) {
case 0 :
return NT_STATUS_INVALID_PARAMETER ;
case 1 :
2008-05-07 23:04:10 +04:00
if ( ! ss ) {
dc_address = r - > logon1 . pdc_name ;
dc_address_type = DS_ADDRESS_TYPE_NETBIOS ;
}
2008-05-07 20:36:03 +04:00
dc_hostname = r - > logon1 . pdc_name ;
dc_domain_name = r - > logon1 . domain_name ;
if ( flags & DS_PDC_REQUIRED ) {
dc_flags = NBT_SERVER_WRITABLE | NBT_SERVER_PDC ;
}
break ;
case 2 :
case 3 :
2008-05-07 23:04:10 +04:00
if ( ! ss ) {
dc_address = r - > logon3 . pdc_ip ;
dc_address_type = DS_ADDRESS_TYPE_INET ;
}
2008-05-07 20:36:03 +04:00
switch ( flags & 0xf0000000 ) {
case DS_RETURN_FLAT_NAME :
dc_hostname = r - > logon3 . pdc_name ;
dc_domain_name = r - > logon3 . domain_name ;
break ;
case DS_RETURN_DNS_NAME :
default :
dc_hostname = r - > logon3 . pdc_dns_name ;
dc_domain_name = r - > logon3 . dns_domain ;
dc_flags | = DS_DNS_DOMAIN | DS_DNS_CONTROLLER ;
break ;
}
dc_flags | = r - > logon3 . server_type ;
dc_forest = r - > logon3 . forest ;
dc_domain_guid = & r - > logon3 . domain_uuid ;
break ;
case 4 :
case 5 :
case 6 :
case 7 :
2008-05-07 23:04:10 +04:00
if ( ! ss ) {
dc_address = r - > logon5 . pdc_name ;
dc_address_type = DS_ADDRESS_TYPE_NETBIOS ;
}
2008-05-07 20:36:03 +04:00
switch ( flags & 0xf0000000 ) {
case DS_RETURN_FLAT_NAME :
dc_hostname = r - > logon5 . pdc_name ;
dc_domain_name = r - > logon5 . domain ;
break ;
case DS_RETURN_DNS_NAME :
default :
dc_hostname = r - > logon5 . pdc_dns_name ;
dc_domain_name = r - > logon5 . dns_domain ;
dc_flags | = DS_DNS_DOMAIN | DS_DNS_CONTROLLER ;
break ;
}
dc_flags | = r - > logon5 . server_type ;
dc_forest = r - > logon5 . forest ;
dc_domain_guid = & r - > logon5 . domain_uuid ;
dc_server_site = r - > logon5 . server_site ;
dc_client_site = r - > logon5 . client_site ;
break ;
case 8 :
case 9 :
case 10 :
case 11 :
case 12 :
case 13 :
case 14 :
case 15 :
2008-05-07 23:04:10 +04:00
if ( ! ss ) {
dc_address = r - > logon13 . dc_sock_addr . pdc_ip ;
dc_address_type = DS_ADDRESS_TYPE_INET ;
}
2008-05-07 20:36:03 +04:00
switch ( flags & 0xf0000000 ) {
case DS_RETURN_FLAT_NAME :
dc_hostname = r - > logon13 . pdc_name ;
dc_domain_name = r - > logon13 . domain ;
break ;
case DS_RETURN_DNS_NAME :
default :
dc_hostname = r - > logon13 . pdc_dns_name ;
dc_domain_name = r - > logon13 . dns_domain ;
dc_flags | = DS_DNS_DOMAIN | DS_DNS_CONTROLLER ;
break ;
}
dc_flags | = r - > logon13 . server_type ;
dc_forest = r - > logon13 . forest ;
dc_domain_guid = & r - > logon13 . domain_uuid ;
dc_server_site = r - > logon13 . server_site ;
dc_client_site = r - > logon13 . client_site ;
break ;
default :
2008-05-07 23:04:10 +04:00
if ( ! ss ) {
dc_address = r - > logon29 . dc_sock_addr . pdc_ip ;
dc_address_type = DS_ADDRESS_TYPE_INET ;
}
2008-05-07 20:36:03 +04:00
switch ( flags & 0xf0000000 ) {
case DS_RETURN_FLAT_NAME :
dc_hostname = r - > logon29 . pdc_name ;
dc_domain_name = r - > logon29 . domain ;
break ;
case DS_RETURN_DNS_NAME :
default :
dc_hostname = r - > logon29 . pdc_dns_name ;
dc_domain_name = r - > logon29 . dns_domain ;
dc_flags | = DS_DNS_DOMAIN | DS_DNS_CONTROLLER ;
break ;
}
dc_flags | = r - > logon29 . server_type ;
dc_forest = r - > logon29 . forest ;
dc_domain_guid = & r - > logon29 . domain_uuid ;
dc_server_site = r - > logon29 . server_site ;
dc_client_site = r - > logon29 . client_site ;
break ;
}
return make_domain_controller_info ( mem_ctx ,
dc_hostname ,
dc_address ,
dc_address_type ,
dc_domain_guid ,
dc_domain_name ,
dc_forest ,
dc_flags ,
dc_server_site ,
dc_client_site ,
info ) ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-05-07 16:38:35 +04:00
static uint32_t map_ds_flags_to_nt_version ( uint32_t flags )
{
uint32_t nt_version = 0 ;
if ( flags & DS_PDC_REQUIRED ) {
nt_version | = NETLOGON_VERSION_PDC ;
}
if ( flags & DS_GC_SERVER_REQUIRED ) {
nt_version | = NETLOGON_VERSION_GC ;
}
if ( flags & DS_TRY_NEXTCLOSEST_SITE ) {
nt_version | = NETLOGON_VERSION_WITH_CLOSEST_SITE ;
}
if ( flags & DS_IP_REQUIRED ) {
nt_version | = NETLOGON_VERSION_IP ;
}
return nt_version ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-28 19:01:23 +04:00
static NTSTATUS process_dc_dns ( TALLOC_CTX * mem_ctx ,
const char * domain_name ,
uint32_t flags ,
2008-04-17 01:56:03 +04:00
struct ip_service_name * dclist ,
2007-08-28 19:01:23 +04:00
int num_dcs ,
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 19:01:23 +04:00
{
int i = 0 ;
2008-01-11 17:32:20 +03:00
bool valid_dc = false ;
2008-05-07 20:38:37 +04:00
union nbt_cldap_netlogon * r = NULL ;
uint32_t nt_version = NETLOGON_VERSION_5 |
NETLOGON_VERSION_5EX ;
uint32_t ret_flags = 0 ;
2007-08-28 19:01:23 +04:00
2008-05-07 20:39:24 +04:00
nt_version | = map_ds_flags_to_nt_version ( flags ) ;
2007-08-28 19:01:23 +04:00
for ( i = 0 ; i < num_dcs ; i + + ) {
2008-04-17 01:56:03 +04:00
DEBUG ( 10 , ( " LDAP ping to %s \n " , dclist [ i ] . hostname ) ) ;
2008-05-07 20:38:37 +04:00
if ( ads_cldap_netlogon ( mem_ctx , dclist [ i ] . hostname ,
domain_name ,
& nt_version ,
& r ) )
{
ret_flags = get_cldap_reply_server_flags ( r , nt_version ) ;
if ( check_cldap_reply_required_flags ( ret_flags , flags ) ) {
valid_dc = true ;
break ;
}
2007-08-28 19:01:23 +04:00
}
continue ;
}
if ( ! valid_dc ) {
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
}
2008-05-07 20:38:37 +04:00
return make_dc_info_from_cldap_reply ( mem_ctx , flags , & dclist [ i ] . ss ,
nt_version , r , info ) ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-04-22 02:04:25 +04:00
static struct event_context * ev_context ( void )
{
static struct event_context * ctx ;
if ( ! ctx & & ! ( ctx = event_context_init ( NULL ) ) ) {
smb_panic ( " Could not init event context " ) ;
}
return ctx ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct messaging_context * msg_context ( TALLOC_CTX * mem_ctx )
{
static struct messaging_context * ctx ;
if ( ! ctx & & ! ( ctx = messaging_init ( mem_ctx , server_id_self ( ) ,
ev_context ( ) ) ) ) {
smb_panic ( " Could not init messaging context " ) ;
}
return ctx ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-28 19:01:23 +04:00
static NTSTATUS process_dc_netbios ( TALLOC_CTX * mem_ctx ,
const char * domain_name ,
uint32_t flags ,
2008-04-22 02:04:25 +04:00
struct ip_service_name * dclist ,
2007-08-28 19:01:23 +04:00
int num_dcs ,
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 19:01:23 +04:00
{
2008-04-22 02:04:25 +04:00
struct sockaddr_storage ss ;
struct ip_service ip_list ;
enum nbt_name_type name_type = NBT_NAME_LOGON ;
int i ;
const char * dc_name = NULL ;
fstring tmp_dc_name ;
struct messaging_context * msg_ctx = msg_context ( mem_ctx ) ;
2008-05-07 20:57:43 +04:00
union nbt_cldap_netlogon * reply = NULL ;
2008-05-05 20:04:41 +04:00
uint32_t nt_version = NETLOGON_VERSION_1 |
NETLOGON_VERSION_5 |
NETLOGON_VERSION_5EX_WITH_IP ;
2008-04-22 02:04:25 +04:00
if ( flags & DS_PDC_REQUIRED ) {
name_type = NBT_NAME_PDC ;
}
2008-05-07 16:38:35 +04:00
nt_version | = map_ds_flags_to_nt_version ( flags ) ;
2008-04-22 02:04:25 +04:00
DEBUG ( 10 , ( " process_dc_netbios \n " ) ) ;
for ( i = 0 ; i < num_dcs ; i + + ) {
ip_list . ss = dclist [ i ] . ss ;
ip_list . port = 0 ;
if ( ! interpret_string_addr ( & ss , dclist [ i ] . hostname , AI_NUMERICHOST ) ) {
return NT_STATUS_UNSUCCESSFUL ;
}
if ( send_getdc_request ( mem_ctx , msg_ctx ,
2008-04-24 23:28:03 +04:00
& dclist [ i ] . ss , domain_name ,
2008-05-05 20:04:41 +04:00
NULL , nt_version ) )
2008-04-22 02:04:25 +04:00
{
int k ;
2008-05-07 20:55:45 +04:00
smb_msleep ( 300 ) ;
2008-04-22 02:04:25 +04:00
for ( k = 0 ; k < 5 ; k + + ) {
if ( receive_getdc_response ( mem_ctx ,
& dclist [ i ] . ss ,
domain_name ,
2008-05-07 20:57:43 +04:00
& nt_version ,
2008-04-24 23:37:42 +04:00
& dc_name ,
& reply ) ) {
2008-04-22 02:04:25 +04:00
namecache_store ( dc_name , NBT_NAME_SERVER , 1 , & ip_list ) ;
goto make_reply ;
}
2008-05-07 20:55:45 +04:00
smb_msleep ( 1500 ) ;
2008-04-22 02:04:25 +04:00
}
}
if ( name_status_find ( domain_name ,
name_type ,
NBT_NAME_SERVER ,
& dclist [ i ] . ss ,
tmp_dc_name ) )
{
2008-05-07 20:57:43 +04:00
struct nbt_cldap_netlogon_1 logon1 ;
2008-04-22 02:04:25 +04:00
2008-05-07 20:57:43 +04:00
reply = TALLOC_ZERO_P ( mem_ctx , union nbt_cldap_netlogon ) ;
NT_STATUS_HAVE_NO_MEMORY ( reply ) ;
2008-04-22 02:04:25 +04:00
2008-05-07 20:57:43 +04:00
ZERO_STRUCT ( logon1 ) ;
2007-08-28 19:01:23 +04:00
2008-05-07 20:57:43 +04:00
nt_version = NETLOGON_VERSION_1 ;
2008-04-24 23:53:55 +04:00
2008-05-07 20:57:43 +04:00
logon1 . nt_version = nt_version ;
logon1 . pdc_name = tmp_dc_name ;
logon1 . domain_name = talloc_strdup_upper ( mem_ctx , domain_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( logon1 . domain_name ) ;
2008-04-24 23:53:55 +04:00
2008-05-07 20:57:43 +04:00
reply - > logon1 = logon1 ;
2008-04-24 23:53:55 +04:00
2008-05-07 20:57:43 +04:00
namecache_store ( tmp_dc_name , NBT_NAME_SERVER , 1 , & ip_list ) ;
2008-04-24 23:53:55 +04:00
2008-05-07 20:57:43 +04:00
goto make_reply ;
}
2008-04-22 02:04:25 +04:00
}
2008-05-07 20:57:43 +04:00
return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
2008-04-22 02:04:25 +04:00
2008-05-07 20:57:43 +04:00
make_reply :
2008-04-24 23:53:55 +04:00
2008-05-07 20:57:43 +04:00
return make_dc_info_from_cldap_reply ( mem_ctx , flags , & dclist [ i ] . ss ,
nt_version , reply , info ) ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 17:32:20 +03:00
static NTSTATUS dsgetdcname_rediscover ( TALLOC_CTX * mem_ctx ,
2007-08-28 19:01:23 +04:00
const char * domain_name ,
struct GUID * domain_guid ,
uint32_t flags ,
const char * site_name ,
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 19:01:23 +04:00
{
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
2008-04-22 02:04:25 +04:00
struct ip_service_name * dclist = NULL ;
2007-08-28 19:01:23 +04:00
int num_dcs ;
2008-01-11 17:32:20 +03:00
DEBUG ( 10 , ( " dsgetdcname_rediscover \n " ) ) ;
2007-08-28 19:01:23 +04: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 ,
2008-04-22 02:04:25 +04:00
dclist , num_dcs , info ) ;
2007-08-28 19:01:23 +04:00
}
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-17 01:56:03 +04:00
dclist , num_dcs , info ) ;
2007-08-28 19:01:23 +04: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-17 01:56:03 +04:00
status = process_dc_dns ( mem_ctx , domain_name , flags , dclist ,
2007-08-28 19:01:23 +04: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 ) ;
2008-04-22 02:04:25 +04:00
return process_dc_netbios ( mem_ctx , domain_name , flags , dclist ,
2007-08-28 19:01:23 +04:00
num_dcs , info ) ;
}
/********************************************************************
2008-01-26 03:39:33 +03:00
dsgetdcname .
2008-01-08 01:05:58 +03:00
2008-01-26 03:39:33 +03:00
This will be the only public function here .
2007-08-28 19:01:23 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-26 03:39:33 +03: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 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * * info )
2007-08-28 19:01:23 +04:00
{
NTSTATUS status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ;
2008-02-28 14:30:18 +03:00
struct netr_DsRGetDCNameInfo * myinfo = NULL ;
2007-08-28 19:01:23 +04:00
2008-01-26 03:39:33 +03: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 19:01:23 +04: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 17:32:20 +03:00
status = dsgetdcname_cached ( mem_ctx , domain_name , domain_guid ,
2007-08-28 19:01:23 +04: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 17:32:20 +03:00
status = dsgetdcname_rediscover ( mem_ctx , domain_name ,
2007-08-28 19:01:23 +04:00
domain_guid , flags , site_name ,
& myinfo ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2008-01-11 17:32:20 +03:00
dsgetdcname_cache_store ( mem_ctx , domain_name , myinfo ) ;
2007-08-28 19:01:23 +04:00
* info = myinfo ;
}
return status ;
}
2008-05-07 17:21:41 +04:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool pull_mailslot_cldap_reply ( TALLOC_CTX * mem_ctx ,
const DATA_BLOB * blob ,
union nbt_cldap_netlogon * r ,
uint32_t * nt_version )
{
enum ndr_err_code ndr_err ;
uint32_t nt_version_query = ( ( * nt_version ) & 0x000000ff ) ;
uint16_t command = 0 ;
ndr_err = ndr_pull_struct_blob ( blob , mem_ctx , & command ,
( ndr_pull_flags_fn_t ) ndr_pull_uint16 ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return false ;
}
switch ( command ) {
case 0x13 : /* 19 */
case 0x15 : /* 21 */
case 0x17 : /* 23 */
break ;
default :
DEBUG ( 1 , ( " got unexpected command: %d (0x%08x) \n " ,
command , command ) ) ;
return false ;
}
ndr_err = ndr_pull_union_blob_all ( blob , mem_ctx , r , nt_version_query ,
( ndr_pull_flags_fn_t ) ndr_pull_nbt_cldap_netlogon ) ;
if ( NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
goto done ;
}
/* when the caller requested just those nt_version bits that the server
* was able to reply to , we are fine and all done . otherwise we need to
* assume downgraded replies which are painfully parsed here - gd */
if ( nt_version_query & NETLOGON_VERSION_WITH_CLOSEST_SITE ) {
nt_version_query & = ~ NETLOGON_VERSION_WITH_CLOSEST_SITE ;
}
ndr_err = ndr_pull_union_blob_all ( blob , mem_ctx , r , nt_version_query ,
( ndr_pull_flags_fn_t ) ndr_pull_nbt_cldap_netlogon ) ;
if ( NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
goto done ;
}
if ( nt_version_query & NETLOGON_VERSION_5EX_WITH_IP ) {
nt_version_query & = ~ NETLOGON_VERSION_5EX_WITH_IP ;
}
ndr_err = ndr_pull_union_blob_all ( blob , mem_ctx , r , nt_version_query ,
( ndr_pull_flags_fn_t ) ndr_pull_nbt_cldap_netlogon ) ;
if ( NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
goto done ;
}
if ( nt_version_query & NETLOGON_VERSION_5EX ) {
nt_version_query & = ~ NETLOGON_VERSION_5EX ;
}
ndr_err = ndr_pull_union_blob_all ( blob , mem_ctx , r , nt_version_query ,
( ndr_pull_flags_fn_t ) ndr_pull_nbt_cldap_netlogon ) ;
if ( NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
goto done ;
}
if ( nt_version_query & NETLOGON_VERSION_5 ) {
nt_version_query & = ~ NETLOGON_VERSION_5 ;
}
ndr_err = ndr_pull_union_blob_all ( blob , mem_ctx , r , nt_version_query ,
( ndr_pull_flags_fn_t ) ndr_pull_nbt_cldap_netlogon ) ;
if ( NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
goto done ;
}
return false ;
done :
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_UNION_DEBUG ( nbt_cldap_netlogon , nt_version_query , r ) ;
}
* nt_version = nt_version_query ;
return true ;
}