2005-04-08 08:57:09 +00:00
/*
Unix SMB / CIFS implementation .
NBT datagram netlogon server
Copyright ( C ) Andrew Tridgell 2005
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
# include "dlinklist.h"
# include "nbt_server/nbt_server.h"
# include "smbd/service_task.h"
# include "lib/socket/socket.h"
2005-08-03 18:30:21 +00:00
# include "lib/ldb/include/ldb.h"
2005-04-08 08:57:09 +00:00
2005-04-10 23:09:38 +00:00
/*
reply to a GETDC request
*/
static void nbtd_netlogon_getdc ( struct dgram_mailslot_handler * dgmslot ,
struct nbt_dgram_packet * packet ,
const char * src_address , int src_port ,
struct nbt_netlogon_packet * netlogon )
{
struct nbt_name * name = & packet - > data . msg . dest_name ;
struct nbt_netlogon_packet reply ;
struct nbt_netlogon_response_from_pdc * pdc ;
2005-08-03 18:30:21 +00:00
const char * ref_attrs [ ] = { " nETBIOSName " , NULL } ;
struct ldb_message * * ref_res ;
struct ldb_context * samctx ;
int ret ;
2005-04-10 23:09:38 +00:00
/* only answer getdc requests on the PDC or LOGON names */
if ( name - > type ! = NBT_NAME_PDC & & name - > type ! = NBT_NAME_LOGON ) {
return ;
}
2005-10-07 11:31:45 +00:00
samctx = samdb_connect ( packet , anonymous_session ( packet ) ) ;
2005-08-03 18:30:21 +00:00
if ( samctx = = NULL ) {
DEBUG ( 2 , ( " Unable to open sam in getdc reply \n " ) ) ;
return ;
}
ret = gendb_search ( samctx , samctx , NULL , & ref_res , ref_attrs ,
" (&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*)) " ,
name - > name ) ;
if ( ret ! = 1 ) {
DEBUG ( 2 , ( " Unable to find domain reference '%s' in sam \n " , name - > name ) ) ;
return ;
}
2005-04-10 23:09:38 +00:00
/* setup a GETDC reply */
2005-04-13 03:43:17 +00:00
ZERO_STRUCT ( reply ) ;
2005-04-10 23:09:38 +00:00
reply . command = NETLOGON_RESPONSE_FROM_PDC ;
pdc = & reply . req . response ;
pdc - > pdc_name = lp_netbios_name ( ) ;
pdc - > unicode_pdc_name = pdc - > pdc_name ;
2005-08-03 18:30:21 +00:00
pdc - > domain_name = samdb_result_string ( ref_res [ 0 ] , " nETBIOSName " , name - > name ) ; ;
2005-04-10 23:09:38 +00:00
pdc - > nt_version = 1 ;
pdc - > lmnt_token = 0xFFFF ;
pdc - > lm20_token = 0xFFFF ;
packet - > data . msg . dest_name . type = 0 ;
dgram_mailslot_netlogon_reply ( dgmslot - > dgmsock ,
packet ,
netlogon - > req . pdc . mailslot_name ,
& reply ) ;
}
2005-04-14 07:40:23 +00:00
/*
reply to a ADS style GETDC request
*/
static void nbtd_netlogon_getdc2 ( struct dgram_mailslot_handler * dgmslot ,
struct nbt_dgram_packet * packet ,
const char * src_address , int src_port ,
struct nbt_netlogon_packet * netlogon )
{
struct nbt_name * name = & packet - > data . msg . dest_name ;
struct nbt_netlogon_packet reply ;
struct nbt_netlogon_response_from_pdc2 * pdc ;
struct ldb_context * samctx ;
2005-08-03 18:30:21 +00:00
const char * ref_attrs [ ] = { " nETBIOSName " , " ncName " , NULL } ;
const char * dom_attrs [ ] = { " dnsDomain " , " objectGUID " , NULL } ;
struct ldb_message * * ref_res , * * dom_res ;
2005-04-14 07:40:23 +00:00
int ret ;
2005-04-14 08:00:45 +00:00
const char * * services = lp_server_services ( ) ;
2005-04-14 07:40:23 +00:00
/* only answer getdc requests on the PDC or LOGON names */
if ( name - > type ! = NBT_NAME_PDC & & name - > type ! = NBT_NAME_LOGON ) {
return ;
}
2005-10-07 11:31:45 +00:00
samctx = samdb_connect ( packet , anonymous_session ( packet ) ) ;
2005-04-14 07:40:23 +00:00
if ( samctx = = NULL ) {
DEBUG ( 2 , ( " Unable to open sam in getdc reply \n " ) ) ;
return ;
}
2005-08-03 18:30:21 +00:00
ret = gendb_search ( samctx , samctx , NULL , & ref_res , ref_attrs ,
" (&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*)) " ,
name - > name ) ;
if ( ret ! = 1 ) {
DEBUG ( 2 , ( " Unable to find domain reference '%s' in sam \n " , name - > name ) ) ;
return ;
}
2005-04-14 07:40:23 +00:00
/* try and find the domain */
2005-08-03 18:30:21 +00:00
ret = gendb_search_dn ( samctx , samctx ,
2005-08-18 15:02:01 +00:00
samdb_result_dn ( samctx , ref_res [ 0 ] , " ncName " , NULL ) ,
2005-08-03 18:30:21 +00:00
& dom_res , dom_attrs ) ;
2005-04-14 07:40:23 +00:00
if ( ret ! = 1 ) {
2005-08-18 15:02:01 +00:00
DEBUG ( 2 , ( " Unable to find domain from reference '%s' in sam \n " ,
ldb_dn_linearize ( samctx , ref_res [ 0 ] - > dn ) ) ) ;
2005-04-14 07:40:23 +00:00
return ;
}
/* setup a GETDC reply */
ZERO_STRUCT ( reply ) ;
if ( netlogon - > req . pdc2 . user_name [ 0 ] ) {
reply . command = NETLOGON_RESPONSE_FROM_PDC_USER ;
} else {
reply . command = NETLOGON_RESPONSE_FROM_PDC2 ;
}
pdc = & reply . req . response2 ;
/* TODO: accurately depict which services we are running */
pdc - > server_type =
2005-04-14 08:00:45 +00:00
NBT_SERVER_PDC | NBT_SERVER_GC |
NBT_SERVER_DS | NBT_SERVER_TIMESERV |
NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE |
NBT_SERVER_GOOD_TIMESERV ;
/* hmm, probably a better way to do this */
if ( str_list_check ( services , " ldap " ) ) {
pdc - > server_type | = NBT_SERVER_LDAP ;
}
2005-04-14 07:40:23 +00:00
2005-06-07 23:06:24 +00:00
if ( str_list_check ( services , " kdc " ) ) {
pdc - > server_type | = NBT_SERVER_KDC ;
}
2005-08-03 18:30:21 +00:00
pdc - > domain_uuid = samdb_result_guid ( dom_res [ 0 ] , " objectGUID " ) ;
pdc - > forest = samdb_result_string ( dom_res [ 0 ] , " dnsDomain " , lp_realm ( ) ) ;
pdc - > dns_domain = samdb_result_string ( dom_res [ 0 ] , " dnsDomain " , lp_realm ( ) ) ;
2005-04-14 07:40:23 +00:00
/* TODO: get our full DNS name from somewhere else */
pdc - > pdc_dns_name = talloc_asprintf ( packet , " %s.%s " ,
2005-06-07 23:06:24 +00:00
strlower_talloc ( packet , lp_netbios_name ( ) ) ,
pdc - > dns_domain ) ;
2005-08-03 18:30:21 +00:00
pdc - > domain = samdb_result_string ( dom_res [ 0 ] , " nETBIOSName " , name - > name ) ; ;
2005-04-14 07:40:23 +00:00
pdc - > pdc_name = lp_netbios_name ( ) ;
pdc - > user_name = netlogon - > req . pdc2 . user_name ;
/* TODO: we need to make sure these are in our DNS zone */
pdc - > site_name = " Default-First-Site-Name " ;
pdc - > site_name2 = " Default-First-Site-Name " ;
pdc - > unknown = 0x10 ; /* what is this? */
pdc - > unknown2 = 2 ; /* and this ... */
pdc - > pdc_ip = socket_get_my_addr ( dgmslot - > dgmsock - > sock , packet ) ;
pdc - > nt_version = 13 ;
pdc - > lmnt_token = 0xFFFF ;
pdc - > lm20_token = 0xFFFF ;
packet - > data . msg . dest_name . type = 0 ;
dgram_mailslot_netlogon_reply ( dgmslot - > dgmsock ,
packet ,
netlogon - > req . pdc2 . mailslot_name ,
& reply ) ;
}
2005-04-08 08:57:09 +00:00
/*
handle incoming netlogon mailslot requests
*/
void nbtd_mailslot_netlogon_handler ( struct dgram_mailslot_handler * dgmslot ,
struct nbt_dgram_packet * packet ,
const char * src_address , int src_port )
{
NTSTATUS status = NT_STATUS_NO_MEMORY ;
2005-04-10 23:09:38 +00:00
struct nbtd_interface * iface =
talloc_get_type ( dgmslot - > private , struct nbtd_interface ) ;
2005-04-08 08:57:09 +00:00
struct nbt_netlogon_packet * netlogon =
talloc ( dgmslot , struct nbt_netlogon_packet ) ;
2005-04-10 23:09:38 +00:00
struct nbtd_iface_name * iname ;
struct nbt_name * name = & packet - > data . msg . dest_name ;
2005-04-08 08:57:09 +00:00
if ( netlogon = = NULL ) goto failed ;
2005-04-10 23:09:38 +00:00
/*
see if the we are listening on the destination netbios name
*/
iname = nbtd_find_iname ( iface , name , 0 ) ;
if ( iname = = NULL ) {
status = NT_STATUS_BAD_NETWORK_NAME ;
goto failed ;
}
DEBUG ( 2 , ( " netlogon request to %s from %s:%d \n " ,
nbt_name_string ( netlogon , name ) , src_address , src_port ) ) ;
2005-04-08 08:57:09 +00:00
status = dgram_mailslot_netlogon_parse ( dgmslot , netlogon , packet , netlogon ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto failed ;
2005-04-10 23:09:38 +00:00
switch ( netlogon - > command ) {
case NETLOGON_QUERY_FOR_PDC :
nbtd_netlogon_getdc ( dgmslot , packet , src_address , src_port , netlogon ) ;
break ;
2005-04-14 07:40:23 +00:00
case NETLOGON_QUERY_FOR_PDC2 :
nbtd_netlogon_getdc2 ( dgmslot , packet , src_address , src_port , netlogon ) ;
break ;
2005-04-10 23:09:38 +00:00
default :
DEBUG ( 2 , ( " unknown netlogon op %d from %s:%d \n " ,
netlogon - > command , src_address , src_port ) ) ;
2005-05-05 11:14:12 +00:00
NDR_PRINT_DEBUG ( nbt_netlogon_packet , netlogon ) ;
2005-04-10 23:09:38 +00:00
break ;
}
2005-04-08 08:57:09 +00:00
talloc_free ( netlogon ) ;
return ;
failed :
DEBUG ( 2 , ( " nbtd netlogon handler failed from %s:%d - %s \n " ,
src_address , src_port , nt_errstr ( status ) ) ) ;
talloc_free ( netlogon ) ;
}