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"
2010-02-23 19:11:37 +03:00
# include "libads/sitename_cache.h"
2010-05-05 03:39:16 +04:00
# include "../librpc/gen_ndr/ndr_netlogon.h"
2010-05-18 21:40:31 +04:00
# include "libads/cldap.h"
2012-05-05 00:47:27 +04:00
# include "../lib/addns/dnsquery.h"
2010-05-18 21:40:31 +04:00
# include "libsmb/clidgram.h"
2007-08-28 19:01:23 +04:00
/* 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
const char * hostname ;
} ;
2008-05-07 23:25:05 +04:00
static NTSTATUS make_dc_info_from_cldap_reply ( TALLOC_CTX * mem_ctx ,
uint32_t flags ,
struct sockaddr_storage * ss ,
2008-09-24 13:06:39 +04:00
struct NETLOGON_SAM_LOGON_RESPONSE_EX * r ,
2008-05-07 23:25:05 +04:00
struct netr_DsRGetDCNameInfo * * info ) ;
2007-08-28 19:01:23 +04:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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
{
2008-06-17 18:18:50 +04:00
if ( ! domain ) {
2007-08-28 19:01:23 +04:00
return NULL ;
}
2010-11-16 21:46:12 +03:00
return talloc_asprintf_strupper_m ( mem_ctx , " DSGETDCNAME/DOMAIN/%s " ,
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 ;
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-05-07 23:25:05 +04:00
const DATA_BLOB * blob )
2007-08-28 19:01:23 +04:00
{
time_t expire_time ;
char * key ;
2008-07-11 19:44:09 +04:00
bool ret = false ;
2007-08-28 19:01:23 +04:00
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-07-11 19:44:09 +04:00
ret = gencache_set_data_blob ( key , blob , expire_time ) ;
return ret ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-05-07 23:25:05 +04:00
static NTSTATUS store_cldap_reply ( TALLOC_CTX * mem_ctx ,
uint32_t flags ,
struct sockaddr_storage * ss ,
uint32_t nt_version ,
2008-09-24 00:21:52 +04:00
struct NETLOGON_SAM_LOGON_RESPONSE_EX * r )
2008-05-07 23:25:05 +04:00
{
DATA_BLOB blob ;
enum ndr_err_code ndr_err ;
NTSTATUS status ;
2008-09-24 00:21:52 +04:00
char addr [ INET6_ADDRSTRLEN ] ;
2008-05-07 23:25:05 +04:00
2008-09-24 00:21:52 +04:00
print_sockaddr ( addr , sizeof ( addr ) , ss ) ;
/* FIXME */
r - > sockaddr_size = 0x10 ; /* the w32 winsock addr size */
2008-10-02 05:37:52 +04:00
r - > sockaddr . sockaddr_family = 2 ; /* AF_INET */
2008-09-24 00:21:52 +04:00
r - > sockaddr . pdc_ip = talloc_strdup ( mem_ctx , addr ) ;
2008-05-07 23:25:05 +04:00
2010-05-10 02:42:06 +04:00
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , r ,
2008-09-24 00:21:52 +04:00
( ndr_push_flags_fn_t ) ndr_push_NETLOGON_SAM_LOGON_RESPONSE_EX ) ;
2008-05-07 23:25:05 +04:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
return ndr_map_error2ntstatus ( ndr_err ) ;
}
2010-04-27 18:56:36 +04:00
if ( r - > domain_name ) {
status = dsgetdcname_cache_store ( mem_ctx , r - > domain_name , & blob ) ;
2008-05-07 23:25:05 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-09-24 00:21:52 +04:00
if ( r - > client_site ) {
2010-04-27 18:56:36 +04:00
sitename_store ( r - > domain_name , r - > client_site ) ;
2008-05-15 19:47:07 +04:00
}
2008-05-07 23:25:05 +04:00
}
2008-09-24 00:21:52 +04:00
if ( r - > dns_domain ) {
status = dsgetdcname_cache_store ( mem_ctx , r - > dns_domain , & blob ) ;
2008-05-07 23:25:05 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto done ;
}
2008-09-24 00:21:52 +04:00
if ( r - > client_site ) {
sitename_store ( r - > dns_domain , r - > client_site ) ;
2008-05-15 19:47:07 +04:00
}
2008-05-07 23:25:05 +04:00
}
2008-10-05 12:55:30 +04:00
status = NT_STATUS_OK ;
2008-05-07 23:25:05 +04:00
done :
data_blob_free ( & blob ) ;
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-09-24 00:21:52 +04:00
static uint32_t get_cldap_reply_server_flags ( struct netlogon_samlogon_response * r ,
2008-05-07 18:49:39 +04:00
uint32_t nt_version )
{
2008-05-09 19:41:50 +04:00
switch ( nt_version & 0x0000001f ) {
2008-05-07 18:49:39 +04:00
case 0 :
case 1 :
2008-05-09 19:41:50 +04:00
case 16 :
case 17 :
2008-05-07 18:49:39 +04:00
return 0 ;
case 2 :
case 3 :
2008-05-09 19:41:50 +04:00
case 18 :
case 19 :
2008-10-02 10:09:25 +04:00
return r - > data . nt5 . server_type ;
2008-05-07 18:49:39 +04:00
case 4 :
case 5 :
case 6 :
case 7 :
2008-10-02 10:09:25 +04:00
return r - > data . nt5_ex . server_type ;
2008-05-07 18:49:39 +04:00
case 8 :
case 9 :
case 10 :
case 11 :
case 12 :
case 13 :
case 14 :
case 15 :
2008-10-02 10:09:25 +04:00
return r - > data . nt5_ex . server_type ;
2008-05-09 19:41:50 +04:00
case 20 :
case 21 :
case 22 :
case 23 :
case 24 :
case 25 :
case 26 :
case 27 :
case 28 :
2008-10-02 10:09:25 +04:00
return r - > data . nt5_ex . server_type ;
2008-05-09 19:41:50 +04:00
case 29 :
case 30 :
case 31 :
2008-10-02 10:09:25 +04:00
return r - > data . nt5_ex . server_type ;
2008-05-09 19:41:50 +04:00
default :
return 0 ;
2008-05-07 18:49:39 +04:00
}
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-23 14:26:03 +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 ,
2009-08-25 19:03:26 +04:00
const struct GUID * domain_guid ,
2007-08-28 19:01:23 +04:00
uint32_t flags ,
2009-07-14 13:33:04 +04:00
struct netr_DsRGetDCNameInfo * * info_p )
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 ;
2008-09-24 00:21:52 +04:00
struct NETLOGON_SAM_LOGON_RESPONSE_EX r ;
2008-05-07 23:25:05 +04:00
NTSTATUS status ;
2007-08-28 19:01:23 +04:00
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 ;
}
2013-09-04 10:22:43 +04:00
if ( ! gencache_get_data_blob ( key , NULL , & blob , NULL , NULL ) ) {
2009-07-14 13:33:04 +04:00
return NT_STATUS_NOT_FOUND ;
2007-08-28 19:01:23 +04:00
}
2011-06-07 05:44:43 +04:00
info = talloc_zero ( mem_ctx , struct netr_DsRGetDCNameInfo ) ;
2008-03-28 15:36:31 +03:00
if ( ! info ) {
2013-09-04 10:22:43 +04:00
data_blob_free ( & blob ) ;
2008-03-28 15:36:31 +03:00
return NT_STATUS_NO_MEMORY ;
2007-08-28 19:01:23 +04:00
}
2010-05-10 02:42:06 +04:00
ndr_err = ndr_pull_struct_blob ( & blob , mem_ctx , & r ,
2008-09-24 00:21:52 +04:00
( ndr_pull_flags_fn_t ) ndr_pull_NETLOGON_SAM_LOGON_RESPONSE_EX ) ;
2008-03-28 15:36:31 +03:00
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 ) ;
}
2008-05-07 23:25:05 +04:00
status = make_dc_info_from_cldap_reply ( mem_ctx , flags , NULL ,
2008-09-24 13:06:39 +04:00
& r , & info ) ;
2008-05-07 23:25:05 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2008-03-28 15:36:31 +03:00
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 ,
2008-05-08 20:32:22 +04:00
struct messaging_context * msg_ctx ,
2007-08-28 19:01:23 +04:00
const char * domain_name ,
2009-08-25 19:03:26 +04:00
const struct GUID * domain_guid ,
2007-08-28 19:01:23 +04:00
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
status = dsgetdcname_cache_fetch ( mem_ctx , domain_name , domain_guid ,
2013-09-03 23:13:45 +04:00
flags , info ) ;
2009-07-14 13:33:04 +04:00
if ( ! NT_STATUS_IS_OK ( status )
& & ! NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
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 ;
}
2009-07-14 13:33:04 +04:00
if ( NT_STATUS_EQUAL ( status , NT_STATUS_NOT_FOUND ) ) {
2009-08-19 16:19:22 +04:00
struct netr_DsRGetDCNameInfo * dc_info ;
status = dsgetdcname ( mem_ctx , msg_ctx , domain_name ,
domain_guid , site_name ,
flags | DS_FORCE_REDISCOVERY ,
& dc_info ) ;
2007-08-28 19:01:23 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2009-08-19 16:22:09 +04:00
* info = dc_info ;
2007-08-28 19:01:23 +04:00
}
return status ;
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-05-15 18:41:18 +04:00
static bool check_allowed_required_flags ( uint32_t flags ,
const char * site_name )
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
2008-05-15 18:41:18 +04:00
if ( ( flags & DS_TRY_NEXTCLOSEST_SITE ) & & site_name ) {
return false ;
}
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 ;
2012-07-18 09:19:15 +04:00
static const char * resolve_order [ ] = { " lmhosts " , " wins " , " bcast " , NULL } ;
2008-04-22 02:04:25 +04:00
* 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 ,
2012-07-18 09:19:15 +04:00
resolve_order ) ;
2008-04-22 02:04:25 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 10 , ( " discover_dc_netbios: failed to find DC \n " ) ) ;
return status ;
}
2011-06-07 05:58:39 +04:00
dclist = talloc_zero_array ( mem_ctx , struct ip_service_name , count ) ;
2008-04-22 02:04:25 +04:00
if ( ! dclist ) {
2010-04-17 22:09:45 +04:00
SAFE_FREE ( iplist ) ;
2008-04-22 02:04:25 +04:00
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 - > hostname = talloc_strdup ( mem_ctx , addr ) ;
if ( ! r - > hostname ) {
2010-04-17 22:09:45 +04:00
SAFE_FREE ( iplist ) ;
2008-04-22 02:04:25 +04:00
return NT_STATUS_NO_MEMORY ;
}
}
* returned_dclist = dclist ;
* returned_count = count ;
2010-04-17 22:09:45 +04:00
SAFE_FREE ( iplist ) ;
2008-04-22 02:04:25 +04:00
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 ,
2009-08-25 19:03:26 +04:00
const struct GUID * domain_guid ,
2007-08-28 19:01:23 +04:00
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 ;
2012-05-05 01:27:36 +04:00
const char * dns_hosts_file ;
2012-05-05 06:32:47 +04:00
char * guid_string ;
2007-08-28 19:01:23 +04:00
2012-05-05 01:27:36 +04:00
dns_hosts_file = lp_parm_const_string ( - 1 , " resolv " , " host file " , NULL ) ;
2007-08-28 19:01:23 +04:00
if ( flags & DS_PDC_REQUIRED ) {
2012-05-05 01:27:36 +04:00
status = ads_dns_query_pdc ( mem_ctx , dns_hosts_file ,
domain_name , & dcs , & numdcs ) ;
2007-08-28 19:01:23 +04:00
} else if ( flags & DS_GC_SERVER_REQUIRED ) {
2012-05-05 01:27:36 +04:00
status = ads_dns_query_gcs ( mem_ctx , dns_hosts_file ,
domain_name , site_name ,
2007-08-28 19:01:23 +04:00
& dcs , & numdcs ) ;
} else if ( flags & DS_KDC_REQUIRED ) {
2012-05-05 01:27:36 +04:00
status = ads_dns_query_kdcs ( mem_ctx , dns_hosts_file ,
domain_name , site_name ,
2007-08-28 19:01:23 +04:00
& dcs , & numdcs ) ;
} else if ( flags & DS_DIRECTORY_SERVICE_REQUIRED ) {
2012-05-05 01:27:36 +04:00
status = ads_dns_query_dcs ( mem_ctx , dns_hosts_file ,
domain_name , site_name ,
2007-08-28 19:01:23 +04:00
& dcs , & numdcs ) ;
} else if ( domain_guid ) {
2012-05-05 06:32:47 +04:00
guid_string = GUID_string ( mem_ctx , domain_guid ) ;
if ( ! guid_string ) {
return NT_STATUS_NO_MEMORY ;
}
2012-05-05 01:27:36 +04:00
status = ads_dns_query_dcs_guid ( mem_ctx , dns_hosts_file ,
2012-05-05 06:32:47 +04:00
domain_name , guid_string ,
2012-05-05 01:27:36 +04:00
& dcs , & numdcs ) ;
2012-05-05 06:32:47 +04:00
TALLOC_FREE ( guid_string ) ;
2007-08-28 19:01:23 +04:00
} else {
2012-05-05 01:27:36 +04:00
status = ads_dns_query_dcs ( mem_ctx , dns_hosts_file ,
domain_name , site_name ,
2008-05-07 16:09:41 +04:00
& 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 ) ;
}
2011-06-07 05:58:39 +04:00
dclist = talloc_zero_array ( mem_ctx ,
2008-04-17 01:56:03 +04:00
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
2009-05-29 13:27:38 +04:00
r - > hostname = dcs [ i ] . 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 ) {
2009-07-29 05:02:10 +04:00
interpret_string_addr_prefer_ipv4 ( & r - > ss ,
dcs [ i ] . hostname , 0 ) ;
2007-08-28 19:01:23 +04:00
i + + ;
j = 0 ;
} else {
2011-04-25 13:25:02 +04:00
/* use the IP addresses from the SRV response */
2007-08-28 19:01:23 +04:00
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
2011-04-25 13:25:02 +04:00
* it . Maybe only as a hack . After think about it , if all of
* the IP addresses returned from DNS are dead , what hope does a
2007-08-28 19:01:23 +04:00
* 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 */
2011-02-27 11:57:18 +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
2011-06-07 05:44:43 +04:00
info = talloc_zero ( 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-05-08 16:24:46 +04:00
if ( forest_name & & * forest_name ) {
2008-02-28 14:30:18 +03:00
info - > forest_name = talloc_strdup ( mem_ctx , forest_name ) ;
NT_STATUS_HAVE_NO_MEMORY ( info - > forest_name ) ;
2009-10-02 06:02:00 +04:00
flags | = DS_DNS_FOREST_ROOT ;
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-08 14:16:04 +04:00
static void map_dc_and_domain_names ( uint32_t flags ,
const char * dc_name ,
const char * domain_name ,
const char * dns_dc_name ,
const char * dns_domain_name ,
uint32_t * dc_flags ,
const char * * hostname_p ,
const char * * domain_p )
{
switch ( flags & 0xf0000000 ) {
case DS_RETURN_FLAT_NAME :
if ( dc_name & & domain_name & &
* dc_name & & * domain_name ) {
* hostname_p = dc_name ;
* domain_p = domain_name ;
break ;
}
case DS_RETURN_DNS_NAME :
default :
if ( dns_dc_name & & dns_domain_name & &
* dns_dc_name & & * dns_domain_name ) {
* hostname_p = dns_dc_name ;
* domain_p = dns_domain_name ;
* dc_flags | = DS_DNS_DOMAIN | DS_DNS_CONTROLLER ;
break ;
}
if ( dc_name & & domain_name & &
* dc_name & & * domain_name ) {
* hostname_p = dc_name ;
* domain_p = domain_name ;
break ;
}
}
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
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 ,
2008-09-24 13:06:39 +04:00
struct NETLOGON_SAM_LOGON_RESPONSE_EX * r ,
2008-05-07 20:36:03 +04:00
struct netr_DsRGetDCNameInfo * * info )
{
2008-05-25 15:44:59 +04:00
const char * dc_hostname = NULL ;
const char * dc_domain_name = NULL ;
2008-05-07 20:36:03 +04:00
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
2008-09-24 13:06:39 +04:00
if ( ! ss & & r - > sockaddr . pdc_ip ) {
dc_address = r - > sockaddr . pdc_ip ;
dc_address_type = DS_ADDRESS_TYPE_INET ;
} else {
dc_address = r - > pdc_name ;
dc_address_type = DS_ADDRESS_TYPE_NETBIOS ;
}
2008-05-09 19:41:50 +04:00
2008-09-24 13:06:39 +04:00
map_dc_and_domain_names ( flags ,
r - > pdc_name ,
2010-04-27 18:56:36 +04:00
r - > domain_name ,
2008-09-24 13:06:39 +04:00
r - > pdc_dns_name ,
r - > dns_domain ,
& dc_flags ,
& dc_hostname ,
& dc_domain_name ) ;
2008-05-07 23:04:10 +04:00
2008-09-24 13:06:39 +04:00
dc_flags | = r - > server_type ;
dc_forest = r - > forest ;
dc_domain_guid = & r - > domain_uuid ;
dc_server_site = r - > server_site ;
dc_client_site = r - > client_site ;
2008-05-07 20:36:03 +04:00
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 ) {
2008-09-23 23:08:25 +04:00
nt_version | = NETLOGON_NT_VERSION_PDC ;
2008-05-07 16:38:35 +04:00
}
if ( flags & DS_GC_SERVER_REQUIRED ) {
2008-09-23 23:08:25 +04:00
nt_version | = NETLOGON_NT_VERSION_GC ;
2008-05-07 16:38:35 +04:00
}
if ( flags & DS_TRY_NEXTCLOSEST_SITE ) {
2008-09-23 23:08:25 +04:00
nt_version | = NETLOGON_NT_VERSION_WITH_CLOSEST_SITE ;
2008-05-07 16:38:35 +04:00
}
if ( flags & DS_IP_REQUIRED ) {
2008-09-23 23:08:25 +04:00
nt_version | = NETLOGON_NT_VERSION_IP ;
2008-05-07 16:38:35 +04:00
}
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-09-24 00:21:52 +04:00
struct netlogon_samlogon_response * r = NULL ;
2008-09-23 23:08:25 +04:00
uint32_t nt_version = NETLOGON_NT_VERSION_5 |
NETLOGON_NT_VERSION_5EX ;
2008-05-07 20:38:37 +04:00
uint32_t ret_flags = 0 ;
2008-05-07 23:25:05 +04:00
NTSTATUS status ;
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 + + ) {
2011-04-26 11:03:32 +04:00
2008-04-17 01:56:03 +04:00
DEBUG ( 10 , ( " LDAP ping to %s \n " , dclist [ i ] . hostname ) ) ;
2011-04-26 11:03:32 +04:00
if ( ads_cldap_netlogon ( mem_ctx , & dclist [ i ] . ss ,
2008-05-07 20:38:37 +04:00
domain_name ,
2008-09-24 00:21:52 +04:00
nt_version ,
2008-05-07 20:38:37 +04:00
& r ) )
{
2008-09-24 00:21:52 +04:00
nt_version = r - > ntver ;
2008-05-07 20:38:37 +04:00
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 23:25:05 +04:00
status = make_dc_info_from_cldap_reply ( mem_ctx , flags , & dclist [ i ] . ss ,
2008-10-02 10:09:25 +04:00
& r - > data . nt5_ex , info ) ;
2008-05-07 23:25:05 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
return store_cldap_reply ( mem_ctx , flags , & dclist [ i ] . ss ,
2008-10-02 10:09:25 +04:00
nt_version , & r - > data . nt5_ex ) ;
2008-05-07 23:25:05 +04:00
}
return status ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-04-22 02:04:25 +04:00
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-08-28 19:01:23 +04:00
static NTSTATUS process_dc_netbios ( TALLOC_CTX * mem_ctx ,
2008-05-08 20:32:22 +04:00
struct messaging_context * msg_ctx ,
2007-08-28 19:01:23 +04:00
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 ;
2008-05-07 23:25:05 +04:00
NTSTATUS status ;
2008-04-22 02:04:25 +04:00
int i ;
const char * dc_name = NULL ;
fstring tmp_dc_name ;
2008-09-24 00:21:52 +04:00
struct netlogon_samlogon_response * r = NULL ;
2008-05-14 11:42:23 +04:00
bool store_cache = false ;
2008-09-23 23:08:25 +04:00
uint32_t nt_version = NETLOGON_NT_VERSION_1 |
NETLOGON_NT_VERSION_5 |
NETLOGON_NT_VERSION_5EX_WITH_IP ;
2008-04-22 02:04:25 +04:00
2010-09-22 07:56:23 +04:00
if ( msg_ctx = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
2008-05-08 20:32:22 +04:00
}
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 + + ) {
2010-11-14 07:32:36 +03:00
uint16_t val ;
generate_random_buffer ( ( uint8_t * ) & val , 2 ) ;
2008-04-22 02:04:25 +04:00
ip_list . ss = dclist [ i ] . ss ;
ip_list . port = 0 ;
2009-07-29 05:02:10 +04:00
if ( ! interpret_string_addr_prefer_ipv4 ( & ss , dclist [ i ] . hostname , AI_NUMERICHOST ) ) {
2008-04-22 02:04:25 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2012-05-23 03:25:14 +04:00
status = nbt_getdc ( msg_ctx , 10 , & dclist [ i ] . ss , domain_name ,
2011-01-05 16:12:44 +03:00
NULL , nt_version ,
mem_ctx , & nt_version , & dc_name , & r ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
store_cache = true ;
namecache_store ( dc_name , NBT_NAME_SERVER , 1 , & ip_list ) ;
goto make_reply ;
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-09-24 00:21:52 +04:00
struct NETLOGON_SAM_LOGON_RESPONSE_NT40 logon1 ;
2008-04-22 02:04:25 +04:00
2011-06-07 05:44:43 +04:00
r = talloc_zero ( mem_ctx , struct netlogon_samlogon_response ) ;
2008-05-07 23:08:20 +04:00
NT_STATUS_HAVE_NO_MEMORY ( r ) ;
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-09-23 23:08:25 +04:00
nt_version = NETLOGON_NT_VERSION_1 ;
2008-04-24 23:53:55 +04:00
2008-05-07 20:57:43 +04:00
logon1 . nt_version = nt_version ;
2010-04-27 18:56:36 +04:00
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-10-02 10:09:25 +04:00
r - > data . nt4 = logon1 ;
2008-09-24 00:21:52 +04:00
r - > ntver = nt_version ;
2008-04-24 23:53:55 +04:00
2008-11-06 14:53:00 +03:00
map_netlogon_samlogon_response ( r ) ;
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 23:25:05 +04:00
status = make_dc_info_from_cldap_reply ( mem_ctx , flags , & dclist [ i ] . ss ,
2008-10-02 10:09:25 +04:00
& r - > data . nt5_ex , info ) ;
2008-05-14 11:42:23 +04:00
if ( NT_STATUS_IS_OK ( status ) & & store_cache ) {
2008-05-07 23:25:05 +04:00
return store_cldap_reply ( mem_ctx , flags , & dclist [ i ] . ss ,
2008-10-02 10:09:25 +04:00
nt_version , & r - > data . nt5_ex ) ;
2008-05-07 23:25:05 +04:00
}
return status ;
2007-08-28 19:01:23 +04:00
}
/****************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2008-01-11 17:32:20 +03:00
static NTSTATUS dsgetdcname_rediscover ( TALLOC_CTX * mem_ctx ,
2008-05-08 20:32:22 +04:00
struct messaging_context * msg_ctx ,
2007-08-28 19:01:23 +04:00
const char * domain_name ,
2009-08-25 19:03:26 +04:00
const struct GUID * domain_guid ,
2007-08-28 19:01:23 +04:00
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 ) ;
2008-05-08 20:32:22 +04:00
return process_dc_netbios ( mem_ctx , msg_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-05-08 20:32:22 +04:00
return process_dc_netbios ( mem_ctx , msg_ctx , domain_name , flags , dclist ,
2007-08-28 19:01:23 +04:00
num_dcs , info ) ;
}
2008-11-21 10:28:13 +03:00
static bool is_closest_site ( struct netr_DsRGetDCNameInfo * info )
{
if ( info - > dc_flags & DS_SERVER_CLOSEST ) {
return true ;
}
if ( ! info - > client_site_name ) {
return true ;
}
if ( ! info - > dc_site_name ) {
return false ;
}
if ( strcmp ( info - > client_site_name , info - > dc_site_name ) = = 0 ) {
return true ;
}
return false ;
}
2007-08-28 19:01:23 +04:00
/********************************************************************
2013-09-03 23:04:37 +04:00
Internal dsgetdcname .
2007-08-28 19:01:23 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-09-03 23:04:37 +04:00
static NTSTATUS dsgetdcname_internal ( TALLOC_CTX * mem_ctx ,
2008-05-08 20:32:22 +04:00
struct messaging_context * msg_ctx ,
2008-01-26 03:39:33 +03:00
const char * domain_name ,
2009-08-25 19:03:26 +04:00
const struct GUID * domain_guid ,
2008-01-26 03:39:33 +03:00
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 ;
2008-11-21 10:28:13 +03:00
bool first = true ;
struct netr_DsRGetDCNameInfo * first_info = NULL ;
2007-08-28 19:01:23 +04:00
2013-09-03 23:04:37 +04:00
DEBUG ( 10 , ( " dsgetdcname_internal: domain_name: %s, "
2008-01-26 03:39:33 +03:00
" domain_guid: %s, site_name: %s, flags: 0x%08x \n " ,
domain_name ,
domain_guid ? GUID_string ( mem_ctx , domain_guid ) : " (null) " ,
2013-09-03 23:08:46 +04:00
site_name ? site_name : " (null) " , flags ) ) ;
2008-01-26 03:39:33 +03:00
2007-08-28 19:01:23 +04:00
* info = NULL ;
2008-05-15 18:41:18 +04:00
if ( ! check_allowed_required_flags ( flags , site_name ) ) {
2007-08-28 19:01:23 +04:00
DEBUG ( 0 , ( " invalid flags specified \n " ) ) ;
return NT_STATUS_INVALID_PARAMETER ;
}
if ( flags & DS_FORCE_REDISCOVERY ) {
goto rediscover ;
}
2008-05-08 20:32:22 +04:00
status = dsgetdcname_cached ( mem_ctx , msg_ctx , domain_name , domain_guid ,
2013-09-03 23:08:46 +04:00
flags , site_name , & myinfo ) ;
2007-08-28 19:01:23 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2008-05-15 18:59:46 +04:00
goto done ;
2007-08-28 19:01:23 +04:00
}
if ( flags & DS_BACKGROUND_ONLY ) {
2008-05-15 18:59:46 +04:00
goto done ;
2007-08-28 19:01:23 +04:00
}
rediscover :
2008-05-08 20:32:22 +04:00
status = dsgetdcname_rediscover ( mem_ctx , msg_ctx , domain_name ,
2013-09-03 23:08:46 +04:00
domain_guid , flags , site_name ,
2007-08-28 19:01:23 +04:00
& myinfo ) ;
2008-05-15 18:59:46 +04:00
done :
2008-11-21 10:28:13 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
if ( ! first ) {
* info = first_info ;
return NT_STATUS_OK ;
}
return status ;
}
if ( ! first ) {
TALLOC_FREE ( first_info ) ;
} else if ( ! is_closest_site ( myinfo ) ) {
first = false ;
first_info = myinfo ;
/* TODO: may use the next_closest_site here */
2013-09-03 23:08:46 +04:00
site_name = myinfo - > client_site_name ;
2008-11-21 10:28:13 +03:00
goto rediscover ;
}
* info = myinfo ;
return NT_STATUS_OK ;
2007-08-28 19:01:23 +04:00
}
2013-09-03 23:04:37 +04:00
/********************************************************************
dsgetdcname .
This will be the only public function here .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS dsgetdcname ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg_ctx ,
const char * domain_name ,
const struct GUID * domain_guid ,
const char * site_name ,
uint32_t flags ,
struct netr_DsRGetDCNameInfo * * info )
{
2013-09-03 23:08:46 +04:00
NTSTATUS status ;
2013-09-03 23:20:52 +04:00
const char * query_site = NULL ;
char * ptr_to_free = NULL ;
2013-09-04 01:07:43 +04:00
bool retry_query_with_null = false ;
2013-09-03 23:08:46 +04:00
if ( ( site_name = = NULL ) | | ( site_name [ 0 ] = = ' \0 ' ) ) {
2013-09-05 00:58:18 +04:00
ptr_to_free = sitename_fetch ( mem_ctx , domain_name ) ;
2013-09-04 01:07:43 +04:00
if ( ptr_to_free ! = NULL ) {
retry_query_with_null = true ;
}
2013-09-03 23:20:52 +04:00
query_site = ptr_to_free ;
2013-09-03 23:08:46 +04:00
} else {
2013-09-03 23:20:52 +04:00
query_site = site_name ;
2013-09-03 23:08:46 +04:00
}
status = dsgetdcname_internal ( mem_ctx ,
2013-09-03 23:04:37 +04:00
msg_ctx ,
domain_name ,
domain_guid ,
2013-09-03 23:08:46 +04:00
query_site ,
2013-09-03 23:04:37 +04:00
flags ,
info ) ;
2013-09-03 23:08:46 +04:00
2013-09-05 00:58:18 +04:00
TALLOC_FREE ( ptr_to_free ) ;
2013-09-03 23:20:52 +04:00
if ( ! NT_STATUS_EQUAL ( status , NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND ) ) {
return status ;
}
/* Should we try again with site_name == NULL ? */
2013-09-04 01:07:43 +04:00
if ( retry_query_with_null ) {
2013-09-03 23:20:52 +04:00
status = dsgetdcname_internal ( mem_ctx ,
msg_ctx ,
domain_name ,
domain_guid ,
NULL ,
flags ,
info ) ;
}
2013-09-03 23:08:46 +04:00
return status ;
2013-09-03 23:04:37 +04:00
}