2010-09-08 19:01:10 +02:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
1997-12-13 14:16:07 +00:00
NBT netbios routines and daemon - version 2
1998-01-22 13:27:43 +00:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Luke Kenneth Casson Leighton 1994 - 1998
2003-08-27 01:25:01 +00:00
Copyright ( C ) Jeremy Allison 1994 - 2003
2003-08-01 15:30:44 +00:00
Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2002
2010-09-08 19:01:10 +02:00
1997-12-13 14:16:07 +00:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
1997-12-13 14:16:07 +00:00
( at your option ) any later version .
2010-09-08 19:01:10 +02:00
1997-12-13 14:16:07 +00:00
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 .
2010-09-08 19:01:10 +02:00
1997-12-13 14:16:07 +00:00
You should have received a copy of the GNU General Public License
2007-07-10 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2010-09-08 19:01:10 +02:00
1997-12-13 14:16:07 +00:00
Revision History :
*/
# include "includes.h"
2011-01-07 12:01:42 +01:00
# include "../libcli/netlogon/netlogon.h"
2009-01-28 10:10:12 +01:00
# include "../libcli/cldap/cldap.h"
# include "../lib/tsocket/tsocket.h"
2010-10-12 15:27:50 +11:00
# include "../libcli/security/security.h"
2010-08-05 02:25:37 +02:00
# include "secrets.h"
2010-08-18 15:22:09 +02:00
# include "nmbd/nmbd.h"
1997-12-13 14:16:07 +00:00
2001-08-24 19:28:08 +00:00
struct sam_database_info {
2015-04-29 20:14:34 -07:00
uint32_t index ;
uint32_t serial_lo , serial_hi ;
uint32_t date_lo , date_hi ;
2001-08-24 19:28:08 +00:00
} ;
2008-08-09 01:04:55 +02:00
/**
* check whether the client belongs to the hosts
* for which initial logon should be delayed . . .
*/
static bool delay_logon ( const char * peer_name , const char * peer_addr )
{
const char * * delay_list = lp_init_logon_delayed_hosts ( ) ;
const char * peer [ 2 ] ;
if ( delay_list = = NULL ) {
return False ;
}
peer [ 0 ] = peer_name ;
peer [ 1 ] = peer_addr ;
return list_match ( delay_list , ( const char * ) peer , client_match ) ;
}
2013-02-18 09:58:40 +01:00
static void delayed_init_logon_handler ( struct tevent_context * event_ctx ,
2013-02-18 10:18:29 +01:00
struct tevent_timer * te ,
2009-01-05 10:22:50 +01:00
struct timeval now ,
2008-08-09 01:04:55 +02:00
void * private_data )
{
struct packet_struct * p = ( struct packet_struct * ) private_data ;
DEBUG ( 10 , ( " delayed_init_logon_handler (%lx): re-queuing packet. \n " ,
( unsigned long ) te ) ) ;
queue_packet ( p ) ;
TALLOC_FREE ( te ) ;
}
1997-12-13 14:16:07 +00:00
/****************************************************************************
Process a domain logon packet
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2011-05-05 11:29:01 -07:00
void process_logon_packet ( struct packet_struct * p , const char * buf , int len ,
2003-01-03 08:28:12 +00:00
const char * mailslot )
1997-12-13 14:16:07 +00:00
{
2010-09-09 22:38:37 +02:00
fstring source_name ;
2003-08-27 01:25:01 +00:00
struct dgram_packet * dgram = & p - > packet . dgram ;
2007-10-10 18:25:16 -07:00
struct sockaddr_storage ss ;
const struct sockaddr_storage * pss ;
struct in_addr ip ;
2010-09-09 22:39:05 +02:00
DATA_BLOB blob_in , blob_out ;
2010-09-07 11:41:05 +02:00
enum ndr_err_code ndr_err ;
struct nbt_netlogon_packet request ;
2010-09-09 22:39:05 +02:00
struct nbt_netlogon_response response ;
NTSTATUS status ;
const char * pdc_name ;
2010-09-07 11:41:05 +02:00
2007-10-10 18:25:16 -07:00
in_addr_to_sockaddr_storage ( & ss , p - > ip ) ;
2008-10-23 19:53:15 +02:00
pss = iface_ip ( ( struct sockaddr * ) & ss ) ;
2007-10-10 18:25:16 -07:00
if ( ! pss ) {
DEBUG ( 5 , ( " process_logon_packet:can't find outgoing interface "
" for packet from IP %s \n " ,
inet_ntoa ( p - > ip ) ) ) ;
return ;
}
2011-05-05 14:22:11 -07:00
ip = ( ( const struct sockaddr_in * ) pss ) - > sin_addr ;
2003-08-27 01:25:01 +00:00
2011-11-10 13:37:54 +11:00
if ( ! IS_DC ) {
2004-01-24 10:46:55 +00:00
DEBUG ( 5 , ( " process_logon_packet: Logon packet received from IP %s and domain \
1997-12-13 14:16:07 +00:00
logons are not enabled . \ n " , inet_ntoa(p->ip) ));
2003-08-27 01:25:01 +00:00
return ;
}
2010-09-09 22:38:37 +02:00
pull_ascii_nstring ( source_name , sizeof ( source_name ) , dgram - > source_name . name ) ;
2011-06-09 15:31:03 +10:00
pdc_name = talloc_asprintf ( talloc_tos ( ) , " \\ \\ %s " , lp_netbios_name ( ) ) ;
2010-09-09 22:39:05 +02:00
if ( ! pdc_name ) {
return ;
}
2010-09-07 11:41:05 +02:00
ZERO_STRUCT ( request ) ;
blob_in = data_blob_const ( buf , len ) ;
ndr_err = ndr_pull_struct_blob ( & blob_in , talloc_tos ( ) , & request ,
( ndr_pull_flags_fn_t ) ndr_pull_nbt_netlogon_packet ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 1 , ( " process_logon_packet: Failed to pull logon packet \n " ) ) ;
return ;
}
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( nbt_netlogon_packet , & request ) ;
}
DEBUG ( 4 , ( " process_logon_packet: Logon from %s: code = 0x%x \n " ,
inet_ntoa ( p - > ip ) , request . command ) ) ;
2003-08-27 01:25:01 +00:00
2010-09-07 11:41:05 +02:00
switch ( request . command ) {
2010-09-09 22:39:05 +02:00
case LOGON_REQUEST : {
2010-09-07 11:50:39 +02:00
2010-09-09 22:39:05 +02:00
struct nbt_netlogon_response2 response2 ;
2004-09-04 01:57:16 +00:00
2010-09-09 22:39:05 +02:00
DEBUG ( 5 , ( " process_logon_packet: Domain login request from %s at IP %s user=%s token=%x \n " ,
request . req . logon0 . computer_name , inet_ntoa ( p - > ip ) ,
request . req . logon0 . user_name ,
request . req . logon0 . lm20_token ) ) ;
2003-08-27 01:25:01 +00:00
2010-09-09 22:39:05 +02:00
response2 . command = LOGON_RESPONSE2 ;
response2 . pdc_name = pdc_name ;
response2 . lm20_token = 0xffff ;
2003-08-27 01:25:01 +00:00
2010-09-09 22:39:05 +02:00
response . response_type = NETLOGON_RESPONSE2 ;
response . data . response2 = response2 ;
2003-08-27 01:25:01 +00:00
2010-09-09 22:39:05 +02:00
status = push_nbt_netlogon_response ( & blob_out , talloc_tos ( ) , & response ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " process_logon_packet: failed to push packet \n " ) ) ;
2010-09-07 11:50:39 +02:00
return ;
}
2003-08-27 01:25:01 +00:00
2010-09-09 22:39:05 +02:00
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( nbt_netlogon_response2 , & response . data . response2 ) ;
}
2003-08-27 01:25:01 +00:00
2010-09-09 22:39:05 +02:00
send_mailslot ( True , request . req . logon0 . mailslot_name ,
( char * ) blob_out . data ,
blob_out . length ,
2011-06-09 15:31:03 +10:00
lp_netbios_name ( ) , 0x0 ,
2010-09-09 22:38:37 +02:00
source_name ,
2010-09-07 11:50:39 +02:00
dgram - > source_name . name_type ,
p - > ip , ip , p - > port ) ;
break ;
}
2003-08-27 01:25:01 +00:00
2010-09-07 11:50:39 +02:00
case LOGON_PRIMARY_QUERY : {
2010-09-09 13:16:21 +02:00
struct nbt_netlogon_response_from_pdc get_pdc ;
2003-08-27 01:25:01 +00:00
2010-09-07 11:50:39 +02:00
if ( ! lp_domain_master ( ) ) {
/* We're not Primary Domain Controller -- ignore this */
return ;
}
2003-08-27 01:25:01 +00:00
2010-09-09 13:16:21 +02:00
DEBUG ( 5 , ( " process_logon_packet: GETDC request from %s at IP %s, "
" reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x \n " ,
request . req . pdc . computer_name ,
inet_ntoa ( p - > ip ) ,
2011-06-09 15:31:03 +10:00
lp_netbios_name ( ) ,
2010-09-09 13:16:21 +02:00
lp_workgroup ( ) ,
NETLOGON_RESPONSE_FROM_PDC ,
request . req . pdc . nt_version ,
request . req . pdc . lmnt_token ,
request . req . pdc . lm20_token ) ) ;
get_pdc . command = NETLOGON_RESPONSE_FROM_PDC ;
2011-06-09 15:31:03 +10:00
get_pdc . pdc_name = lp_netbios_name ( ) ;
2010-09-09 13:16:21 +02:00
get_pdc . _pad = data_blob_null ;
2011-06-09 15:31:03 +10:00
get_pdc . unicode_pdc_name = lp_netbios_name ( ) ;
2010-09-09 13:16:21 +02:00
get_pdc . domain_name = lp_workgroup ( ) ;
2010-09-09 23:13:33 +02:00
get_pdc . nt_version = NETLOGON_NT_VERSION_1 ;
2010-09-09 13:16:21 +02:00
get_pdc . lmnt_token = 0xffff ;
get_pdc . lm20_token = 0xffff ;
response . response_type = NETLOGON_GET_PDC ;
response . data . get_pdc = get_pdc ;
2004-09-04 01:57:16 +00:00
2010-09-09 13:16:21 +02:00
status = push_nbt_netlogon_response ( & blob_out , talloc_tos ( ) , & response ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " process_logon_packet: failed to push packet \n " ) ) ;
2010-09-07 11:50:39 +02:00
return ;
}
2010-09-09 13:16:21 +02:00
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( nbt_netlogon_response_from_pdc , & response . data . get_pdc ) ;
2010-09-07 11:50:39 +02:00
}
2003-08-27 01:25:01 +00:00
2010-09-09 13:16:21 +02:00
send_mailslot ( True , request . req . pdc . mailslot_name ,
( char * ) blob_out . data ,
blob_out . length ,
2011-06-09 15:31:03 +10:00
lp_netbios_name ( ) , 0x0 ,
2010-09-07 11:50:39 +02:00
source_name ,
dgram - > source_name . name_type ,
p - > ip , ip , p - > port ) ;
2010-09-09 13:16:21 +02:00
2010-09-07 11:50:39 +02:00
return ;
}
2004-09-04 01:57:16 +00:00
2010-09-07 11:50:39 +02:00
case LOGON_SAM_LOGON_REQUEST : {
char * source_addr ;
2010-09-08 18:55:27 +02:00
bool user_unknown = false ;
struct netlogon_samlogon_response samlogon ;
2011-11-10 17:41:28 +11:00
struct NETLOGON_SAM_LOGON_RESPONSE_NT40 nt4 ;
2004-09-04 01:57:16 +00:00
2010-09-08 18:55:27 +02:00
source_addr = SMB_STRDUP ( inet_ntoa ( dgram - > header . source_ip ) ) ;
if ( source_addr = = NULL ) {
DEBUG ( 3 , ( " out of memory copying client "
" address string \n " ) ) ;
2010-09-07 11:50:39 +02:00
return ;
}
2004-09-04 01:57:16 +00:00
2010-09-08 18:55:27 +02:00
DEBUG ( 5 , ( " process_logon_packet: LOGON_SAM_LOGON_REQUEST request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x \n " ,
request . req . logon . computer_name ,
inet_ntoa ( p - > ip ) ,
request . req . logon . user_name ,
pdc_name ,
lp_workgroup ( ) ,
LOGON_SAM_LOGON_RESPONSE ,
request . req . logon . lmnt_token ) ) ;
2010-09-07 11:50:39 +02:00
2010-09-08 18:55:27 +02:00
if ( ! request . req . logon . user_name ) {
user_unknown = true ;
2010-09-07 11:50:39 +02:00
}
2011-11-10 17:41:28 +11:00
nt4 . command = user_unknown ? LOGON_SAM_LOGON_USER_UNKNOWN :
LOGON_SAM_LOGON_RESPONSE ;
nt4 . pdc_name = pdc_name ;
nt4 . user_name = request . req . logon . user_name ;
nt4 . domain_name = lp_workgroup ( ) ;
nt4 . nt_version = NETLOGON_NT_VERSION_1 ;
nt4 . lmnt_token = 0xffff ;
nt4 . lm20_token = 0xffff ;
samlogon . ntver = NETLOGON_NT_VERSION_1 ;
samlogon . data . nt4 = nt4 ;
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( NETLOGON_SAM_LOGON_RESPONSE_NT40 , & nt4 ) ;
2010-09-07 11:50:39 +02:00
}
2001-08-24 19:28:08 +00:00
2010-09-08 18:55:27 +02:00
response . response_type = NETLOGON_SAMLOGON ;
response . data . samlogon = samlogon ;
2010-09-07 11:50:39 +02:00
2010-09-08 18:55:27 +02:00
status = push_nbt_netlogon_response ( & blob_out , talloc_tos ( ) , & response ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " process_logon_packet: failed to push packet \n " ) ) ;
2012-04-19 15:30:06 +02:00
SAFE_FREE ( source_addr ) ;
2003-08-27 01:25:01 +00:00
return ;
2010-09-07 11:50:39 +02:00
}
/*
* handle delay .
* packets requeued after delay are marked as
* locked .
*/
if ( ( p - > locked = = False ) & &
2010-09-08 18:55:27 +02:00
( strlen ( request . req . logon . user_name ) = = 0 ) & &
2010-09-07 11:50:39 +02:00
delay_logon ( source_name , source_addr ) )
{
struct timeval when ;
DEBUG ( 3 , ( " process_logon_packet: "
" delaying initial logon "
" reply for client %s(%s) for "
" %u milliseconds \n " ,
source_name , source_addr ,
lp_init_logon_delay ( ) ) ) ;
2011-06-01 11:21:15 +09:30
when = timeval_current_ofs_msec ( lp_init_logon_delay ( ) ) ;
2010-09-07 11:50:39 +02:00
p - > locked = true ;
2013-02-18 10:57:54 +01:00
tevent_add_timer ( nmbd_event_context ( ) ,
2010-09-07 11:50:39 +02:00
NULL ,
when ,
delayed_init_logon_handler ,
p ) ;
} else {
DEBUG ( 3 , ( " process_logon_packet: "
" processing delayed initial "
" logon reply for client "
" %s(%s) \n " ,
source_name , source_addr ) ) ;
p - > locked = false ;
2010-09-08 18:55:27 +02:00
send_mailslot ( true , request . req . logon . mailslot_name ,
( char * ) blob_out . data ,
blob_out . length ,
2011-06-09 15:31:03 +10:00
lp_netbios_name ( ) , 0x0 ,
2010-09-07 11:50:39 +02:00
source_name ,
dgram - > source_name . name_type ,
p - > ip , ip , p - > port ) ;
}
SAFE_FREE ( source_addr ) ;
break ;
}
/* Announce change to UAS or SAM. Send by the domain controller when a
replication event is required . */
case NETLOGON_ANNOUNCE_UAS :
DEBUG ( 5 , ( " Got NETLOGON_ANNOUNCE_UAS \n " ) ) ;
break ;
default :
2010-09-07 11:41:05 +02:00
DEBUG ( 3 , ( " process_logon_packet: Unknown domain request %d \n " ,
request . command ) ) ;
2010-09-07 11:50:39 +02:00
return ;
2003-08-27 01:25:01 +00:00
}
1997-12-13 14:16:07 +00:00
}