2001-01-03 08:19:21 +03:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2001-01-03 08:19:21 +03:00
client dgram calls
Copyright ( C ) Andrew Tridgell 1994 - 1998
Copyright ( C ) Richard Sharpe 2001
Copyright ( C ) John Terpstra 2001
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 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2001-01-03 08:19:21 +03:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-01-03 08:19:21 +03:00
*/
# include "includes.h"
2010-05-05 03:39:16 +04:00
# include "librpc/gen_ndr/messaging.h"
2001-01-03 08:19:21 +03:00
/*
* cli_send_mailslot , send a mailslot for client code . . .
*/
2009-07-21 02:15:08 +04:00
static bool cli_send_mailslot ( struct messaging_context * msg_ctx ,
2007-10-19 04:40:25 +04:00
bool unique , const char * mailslot ,
2005-06-09 02:10:34 +04:00
uint16 priority ,
char * buf , int len ,
2007-10-25 01:16:54 +04:00
const char * srcname , int src_type ,
2005-06-09 02:10:34 +04:00
const char * dstname , int dest_type ,
2007-10-25 01:16:54 +04:00
const struct sockaddr_storage * dest_ss )
2001-01-03 08:19:21 +03:00
{
2005-06-09 02:10:34 +04:00
struct packet_struct p ;
struct dgram_packet * dgram = & p . packet . dgram ;
char * ptr , * p2 ;
char tmp [ 4 ] ;
pid_t nmbd_pid ;
2007-10-25 01:16:54 +04:00
char addr [ INET6_ADDRSTRLEN ] ;
2005-06-09 02:10:34 +04:00
if ( ( nmbd_pid = pidfile_pid ( " nmbd " ) ) = = 0 ) {
DEBUG ( 3 , ( " No nmbd found \n " ) ) ;
return False ;
}
2007-10-25 01:16:54 +04:00
if ( dest_ss - > ss_family ! = AF_INET ) {
DEBUG ( 3 , ( " cli_send_mailslot: can't send to IPv6 address. \n " ) ) ;
return false ;
}
2005-06-09 02:10:34 +04:00
memset ( ( char * ) & p , ' \0 ' , sizeof ( p ) ) ;
/*
* Next , build the DGRAM . . .
*/
/* DIRECT GROUP or UNIQUE datagram. */
2007-10-25 01:16:54 +04:00
dgram - > header . msg_type = unique ? 0x10 : 0x11 ;
2005-06-09 02:10:34 +04:00
dgram - > header . flags . node_type = M_NODE ;
dgram - > header . flags . first = True ;
dgram - > header . flags . more = False ;
dgram - > header . dgm_id = ( ( unsigned ) time ( NULL ) % ( unsigned ) 0x7FFF ) +
( ( unsigned ) sys_getpid ( ) % ( unsigned ) 100 ) ;
/* source ip is filled by nmbd */
dgram - > header . dgm_length = 0 ; /* Let build_dgram() handle this. */
dgram - > header . packet_offset = 0 ;
2007-10-25 01:16:54 +04:00
2005-06-09 02:10:34 +04:00
make_nmb_name ( & dgram - > source_name , srcname , src_type ) ;
make_nmb_name ( & dgram - > dest_name , dstname , dest_type ) ;
ptr = & dgram - > data [ 0 ] ;
/* Setup the smb part. */
ptr - = 4 ; /* XXX Ugliness because of handling of tcp SMB length. */
memcpy ( tmp , ptr , 4 ) ;
2007-12-14 03:44:24 +03:00
if ( smb_size + 17 * 2 + strlen ( mailslot ) + 1 + len > MAX_DGRAM_SIZE ) {
DEBUG ( 0 , ( " cli_send_mailslot: Cannot write beyond end of packet \n " ) ) ;
return False ;
}
2007-12-27 04:12:36 +03:00
cli_set_message ( ptr , 17 , strlen ( mailslot ) + 1 + len , True ) ;
2005-06-09 02:10:34 +04:00
memcpy ( ptr , tmp , 4 ) ;
SCVAL ( ptr , smb_com , SMBtrans ) ;
SSVAL ( ptr , smb_vwv1 , len ) ;
SSVAL ( ptr , smb_vwv11 , len ) ;
SSVAL ( ptr , smb_vwv12 , 70 + strlen ( mailslot ) ) ;
SSVAL ( ptr , smb_vwv13 , 3 ) ;
SSVAL ( ptr , smb_vwv14 , 1 ) ;
SSVAL ( ptr , smb_vwv15 , priority ) ;
SSVAL ( ptr , smb_vwv16 , 2 ) ;
p2 = smb_buf ( ptr ) ;
fstrcpy ( p2 , mailslot ) ;
2007-04-03 00:10:21 +04:00
p2 = skip_string ( ptr , MAX_DGRAM_SIZE , p2 ) ;
2007-03-31 02:25:08 +04:00
if ( ! p2 ) {
return False ;
}
2005-06-09 02:10:34 +04:00
memcpy ( p2 , buf , len ) ;
p2 + = len ;
dgram - > datasize = PTR_DIFF ( p2 , ptr + 4 ) ; /* +4 for tcp length. */
p . packet_type = DGRAM_PACKET ;
2007-10-26 05:15:02 +04:00
p . ip = ( ( const struct sockaddr_in * ) dest_ss ) - > sin_addr ;
2005-06-09 02:10:34 +04:00
p . timestamp = time ( NULL ) ;
DEBUG ( 4 , ( " send_mailslot: Sending to mailslot %s from %s " ,
mailslot , nmb_namestr ( & dgram - > source_name ) ) ) ;
2007-10-25 01:16:54 +04:00
print_sockaddr ( addr , sizeof ( addr ) , dest_ss ) ;
DEBUGADD ( 4 , ( " to %s IP %s \n " , nmb_namestr ( & dgram - > dest_name ) , addr ) ) ;
2005-06-09 02:10:34 +04:00
2007-05-15 17:56:00 +04:00
return NT_STATUS_IS_OK ( messaging_send_buf ( msg_ctx ,
pid_to_procid ( nmbd_pid ) ,
MSG_SEND_PACKET ,
( uint8 * ) & p , sizeof ( p ) ) ) ;
2001-01-03 08:19:21 +03:00
}
2008-04-17 01:52:34 +04:00
2008-04-21 12:55:23 +04:00
static const char * mailslot_name ( TALLOC_CTX * mem_ctx , struct in_addr dc_ip )
2008-04-17 01:52:34 +04:00
{
2008-04-21 12:55:23 +04:00
return talloc_asprintf ( mem_ctx , " %s%X " ,
NBT_MAILSLOT_GETDC , dc_ip . s_addr ) ;
2008-04-17 01:52:34 +04:00
}
2008-04-21 19:51:36 +04:00
bool send_getdc_request ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg_ctx ,
2008-04-17 01:52:34 +04:00
struct sockaddr_storage * dc_ss ,
const char * domain_name ,
2008-04-24 23:28:03 +04:00
const DOM_SID * sid ,
uint32_t nt_version )
2008-04-17 01:52:34 +04:00
{
struct in_addr dc_ip ;
2008-04-21 12:55:23 +04:00
const char * my_acct_name = NULL ;
const char * my_mailslot = NULL ;
2008-09-24 00:21:52 +04:00
struct nbt_netlogon_packet packet ;
struct NETLOGON_SAM_LOGON_REQUEST * s ;
2008-04-21 12:55:23 +04:00
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
struct dom_sid my_sid ;
ZERO_STRUCT ( packet ) ;
ZERO_STRUCT ( my_sid ) ;
2008-04-17 01:52:34 +04:00
if ( dc_ss - > ss_family ! = AF_INET ) {
return false ;
}
2008-04-21 12:55:23 +04:00
if ( sid ) {
my_sid = * sid ;
}
2008-04-17 01:52:34 +04:00
2008-04-21 12:55:23 +04:00
dc_ip = ( ( struct sockaddr_in * ) dc_ss ) - > sin_addr ;
my_mailslot = mailslot_name ( mem_ctx , dc_ip ) ;
if ( ! my_mailslot ) {
2008-04-17 01:52:34 +04:00
return false ;
}
2008-04-21 12:55:23 +04:00
my_acct_name = talloc_asprintf ( mem_ctx , " %s$ " , global_myname ( ) ) ;
if ( ! my_acct_name ) {
2008-04-17 01:52:34 +04:00
return false ;
}
2008-09-24 00:21:52 +04:00
packet . command = LOGON_SAM_LOGON_REQUEST ;
2008-04-21 12:55:23 +04:00
s = & packet . req . logon ;
s - > request_count = 0 ;
s - > computer_name = global_myname ( ) ;
s - > user_name = my_acct_name ;
s - > mailslot_name = my_mailslot ;
s - > acct_control = ACB_WSTRUST ;
s - > sid = my_sid ;
2008-04-24 23:28:03 +04:00
s - > nt_version = nt_version ;
2008-04-21 12:55:23 +04:00
s - > lmnt_token = 0xffff ;
s - > lm20_token = 0xffff ;
if ( DEBUGLEVEL > = 10 ) {
2008-09-24 00:21:52 +04:00
NDR_PRINT_DEBUG ( nbt_netlogon_packet , & packet ) ;
2008-04-17 01:52:34 +04:00
}
2008-09-23 11:49:56 +04:00
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , NULL , & packet ,
2008-09-24 00:21:52 +04:00
( ndr_push_flags_fn_t ) ndr_push_nbt_netlogon_packet ) ;
2008-04-21 12:55:23 +04:00
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2008-04-17 01:52:34 +04:00
return false ;
}
return cli_send_mailslot ( msg_ctx ,
2008-04-21 12:55:23 +04:00
false , NBT_MAILSLOT_NTLOGON , 0 ,
( char * ) blob . data , blob . length ,
2008-04-17 01:52:34 +04:00
global_myname ( ) , 0 , domain_name , 0x1c ,
dc_ss ) ;
}
2008-04-21 19:51:36 +04:00
bool receive_getdc_response ( TALLOC_CTX * mem_ctx ,
struct sockaddr_storage * dc_ss ,
2008-04-17 01:52:34 +04:00
const char * domain_name ,
2008-05-07 20:57:43 +04:00
uint32_t * nt_version ,
2008-04-24 23:37:42 +04:00
const char * * dc_name ,
2008-09-24 00:21:52 +04:00
struct netlogon_samlogon_response * * _r )
2008-04-17 01:52:34 +04:00
{
struct packet_struct * packet ;
2008-04-21 12:55:23 +04:00
const char * my_mailslot = NULL ;
2008-04-17 01:52:34 +04:00
struct in_addr dc_ip ;
2008-04-21 12:55:23 +04:00
DATA_BLOB blob ;
2008-09-24 00:21:52 +04:00
struct netlogon_samlogon_response r ;
2008-04-21 12:55:23 +04:00
union dgram_message_body p ;
enum ndr_err_code ndr_err ;
2008-09-24 00:21:52 +04:00
NTSTATUS status ;
2008-04-17 01:52:34 +04:00
2008-04-24 23:29:48 +04:00
const char * returned_dc = NULL ;
const char * returned_domain = NULL ;
2008-04-17 01:52:34 +04:00
if ( dc_ss - > ss_family ! = AF_INET ) {
return false ;
}
2008-04-21 12:55:23 +04:00
2008-04-17 01:52:34 +04:00
dc_ip = ( ( struct sockaddr_in * ) dc_ss ) - > sin_addr ;
2008-04-21 12:55:23 +04:00
my_mailslot = mailslot_name ( mem_ctx , dc_ip ) ;
if ( ! my_mailslot ) {
return false ;
}
2008-04-17 01:52:34 +04:00
packet = receive_unexpected ( DGRAM_PACKET , 0 , my_mailslot ) ;
if ( packet = = NULL ) {
DEBUG ( 5 , ( " Did not receive packet for %s \n " , my_mailslot ) ) ;
return False ;
}
DEBUG ( 5 , ( " Received packet for %s \n " , my_mailslot ) ) ;
2008-04-21 12:55:23 +04:00
blob = data_blob_const ( packet - > packet . dgram . data ,
packet - > packet . dgram . datasize ) ;
2008-04-17 01:52:34 +04:00
2008-04-21 12:55:23 +04:00
if ( blob . length < 4 ) {
DEBUG ( 0 , ( " invalid length: %d \n " , ( int ) blob . length ) ) ;
return false ;
2008-04-17 01:52:34 +04:00
}
2008-04-21 12:55:23 +04:00
if ( RIVAL ( blob . data , 0 ) ! = DGRAM_SMB ) {
DEBUG ( 0 , ( " invalid packet \n " ) ) ;
return false ;
}
blob . data + = 4 ;
blob . length - = 4 ;
2008-10-13 17:01:28 +04:00
ndr_err = ndr_pull_union_blob_all ( & blob , mem_ctx , NULL , & p , DGRAM_SMB ,
2008-04-21 12:55:23 +04:00
( ndr_pull_flags_fn_t ) ndr_pull_dgram_smb_packet ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
DEBUG ( 0 , ( " failed to parse packet \n " ) ) ;
return false ;
}
if ( p . smb . smb_command ! = SMB_TRANSACTION ) {
DEBUG ( 0 , ( " invalid smb_command: %d \n " , p . smb . smb_command ) ) ;
return false ;
}
2008-05-07 20:57:43 +04:00
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( dgram_smb_packet , & p ) ;
}
2008-04-21 12:55:23 +04:00
blob = p . smb . body . trans . data ;
2008-09-24 00:21:52 +04:00
ZERO_STRUCT ( r ) ;
status = pull_netlogon_samlogon_response ( & blob , mem_ctx , NULL , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-04-21 12:55:23 +04:00
return false ;
}
2008-09-24 00:21:52 +04:00
map_netlogon_samlogon_response ( & r ) ;
/* do we still need this ? */
* nt_version = r . ntver ;
2010-04-27 18:56:36 +04:00
returned_domain = r . data . nt5_ex . domain_name ;
2008-10-02 10:09:25 +04:00
returned_dc = r . data . nt5_ex . pdc_name ;
2008-04-24 23:29:48 +04:00
if ( ! strequal ( returned_domain , domain_name ) ) {
2008-04-21 12:55:23 +04:00
DEBUG ( 3 , ( " GetDC: Expected domain %s, got %s \n " ,
2008-04-24 23:29:48 +04:00
domain_name , returned_domain ) ) ;
2008-04-21 12:55:23 +04:00
return false ;
}
2008-04-24 23:29:48 +04:00
* dc_name = talloc_strdup ( mem_ctx , returned_dc ) ;
2008-04-21 12:55:23 +04:00
if ( ! * dc_name ) {
return false ;
2008-04-17 01:52:34 +04:00
}
2008-04-21 12:55:23 +04:00
if ( * * dc_name = = ' \\ ' ) * dc_name + = 1 ;
if ( * * dc_name = = ' \\ ' ) * dc_name + = 1 ;
2008-04-17 01:52:34 +04:00
2008-09-24 00:21:52 +04:00
if ( _r ) {
* _r = ( struct netlogon_samlogon_response * ) talloc_memdup (
mem_ctx , & r , sizeof ( struct netlogon_samlogon_response ) ) ;
if ( ! * _r ) {
2008-04-24 23:37:42 +04:00
return false ;
}
}
2008-04-17 01:52:34 +04:00
DEBUG ( 10 , ( " GetDC gave name %s for domain %s \n " ,
2008-04-24 23:29:48 +04:00
* dc_name , returned_domain ) ) ;
2008-04-17 01:52:34 +04:00
return True ;
}