2001-01-03 05:19:21 +00:00
/*
2002-01-30 06:08:46 +00:00
Unix SMB / CIFS implementation .
2001-01-03 05:19:21 +00: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 19:25:36 +00:00
the Free Software Foundation ; either version 3 of the License , or
2001-01-03 05:19:21 +00: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 00:52:41 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2001-01-03 05:19:21 +00:00
*/
# include "includes.h"
/*
* cli_send_mailslot , send a mailslot for client code . . .
*/
2007-10-18 17:40:25 -07:00
bool cli_send_mailslot ( struct messaging_context * msg_ctx ,
bool unique , const char * mailslot ,
2005-06-08 22:10:34 +00:00
uint16 priority ,
char * buf , int len ,
2007-10-24 14:16:54 -07:00
const char * srcname , int src_type ,
2005-06-08 22:10:34 +00:00
const char * dstname , int dest_type ,
2007-10-24 14:16:54 -07:00
const struct sockaddr_storage * dest_ss )
2001-01-03 05:19:21 +00:00
{
2005-06-08 22:10:34 +00:00
struct packet_struct p ;
struct dgram_packet * dgram = & p . packet . dgram ;
char * ptr , * p2 ;
char tmp [ 4 ] ;
pid_t nmbd_pid ;
2007-10-24 14:16:54 -07:00
char addr [ INET6_ADDRSTRLEN ] ;
2005-06-08 22:10:34 +00:00
if ( ( nmbd_pid = pidfile_pid ( " nmbd " ) ) = = 0 ) {
DEBUG ( 3 , ( " No nmbd found \n " ) ) ;
return False ;
}
2007-10-24 14:16:54 -07:00
if ( dest_ss - > ss_family ! = AF_INET ) {
DEBUG ( 3 , ( " cli_send_mailslot: can't send to IPv6 address. \n " ) ) ;
return false ;
}
2005-06-08 22:10:34 +00:00
memset ( ( char * ) & p , ' \0 ' , sizeof ( p ) ) ;
/*
* Next , build the DGRAM . . .
*/
/* DIRECT GROUP or UNIQUE datagram. */
2007-10-24 14:16:54 -07:00
dgram - > header . msg_type = unique ? 0x10 : 0x11 ;
2005-06-08 22:10:34 +00: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-24 14:16:54 -07:00
2005-06-08 22:10:34 +00: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-13 16:44:24 -08: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-26 17:12:36 -08:00
cli_set_message ( ptr , 17 , strlen ( mailslot ) + 1 + len , True ) ;
2005-06-08 22:10:34 +00: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-02 20:10:21 +00:00
p2 = skip_string ( ptr , MAX_DGRAM_SIZE , p2 ) ;
2007-03-30 22:25:08 +00:00
if ( ! p2 ) {
return False ;
}
2005-06-08 22:10:34 +00: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-25 18:15:02 -07:00
p . ip = ( ( const struct sockaddr_in * ) dest_ss ) - > sin_addr ;
2005-06-08 22:10:34 +00:00
p . timestamp = time ( NULL ) ;
DEBUG ( 4 , ( " send_mailslot: Sending to mailslot %s from %s " ,
mailslot , nmb_namestr ( & dgram - > source_name ) ) ) ;
2007-10-24 14:16:54 -07:00
print_sockaddr ( addr , sizeof ( addr ) , dest_ss ) ;
DEBUGADD ( 4 , ( " to %s IP %s \n " , nmb_namestr ( & dgram - > dest_name ) , addr ) ) ;
2005-06-08 22:10:34 +00:00
2007-05-15 13:56:00 +00: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 05:19:21 +00:00
}
2008-04-16 23:52:34 +02:00
2008-04-21 10:55:23 +02:00
static const char * mailslot_name ( TALLOC_CTX * mem_ctx , struct in_addr dc_ip )
2008-04-16 23:52:34 +02:00
{
2008-04-21 10:55:23 +02:00
return talloc_asprintf ( mem_ctx , " %s%X " ,
NBT_MAILSLOT_GETDC , dc_ip . s_addr ) ;
2008-04-16 23:52:34 +02:00
}
2008-04-21 17:51:36 +02:00
bool send_getdc_request ( TALLOC_CTX * mem_ctx ,
struct messaging_context * msg_ctx ,
2008-04-16 23:52:34 +02:00
struct sockaddr_storage * dc_ss ,
const char * domain_name ,
2008-04-24 21:28:03 +02:00
const DOM_SID * sid ,
uint32_t nt_version )
2008-04-16 23:52:34 +02:00
{
struct in_addr dc_ip ;
2008-04-21 10:55:23 +02:00
const char * my_acct_name = NULL ;
const char * my_mailslot = NULL ;
struct nbt_ntlogon_packet packet ;
struct nbt_ntlogon_sam_logon * s ;
enum ndr_err_code ndr_err ;
DATA_BLOB blob ;
struct dom_sid my_sid ;
ZERO_STRUCT ( packet ) ;
ZERO_STRUCT ( my_sid ) ;
2008-04-16 23:52:34 +02:00
if ( dc_ss - > ss_family ! = AF_INET ) {
return false ;
}
2008-04-21 10:55:23 +02:00
if ( sid ) {
my_sid = * sid ;
}
2008-04-16 23:52:34 +02:00
2008-04-21 10:55:23 +02:00
dc_ip = ( ( struct sockaddr_in * ) dc_ss ) - > sin_addr ;
my_mailslot = mailslot_name ( mem_ctx , dc_ip ) ;
if ( ! my_mailslot ) {
2008-04-16 23:52:34 +02:00
return false ;
}
2008-04-21 10:55:23 +02:00
my_acct_name = talloc_asprintf ( mem_ctx , " %s$ " , global_myname ( ) ) ;
if ( ! my_acct_name ) {
2008-04-16 23:52:34 +02:00
return false ;
}
2008-04-21 10:55:23 +02:00
packet . command = NTLOGON_SAM_LOGON ;
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 21:28:03 +02:00
s - > nt_version = nt_version ;
2008-04-21 10:55:23 +02:00
s - > lmnt_token = 0xffff ;
s - > lm20_token = 0xffff ;
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( nbt_ntlogon_packet , & packet ) ;
2008-04-16 23:52:34 +02:00
}
2008-04-21 10:55:23 +02:00
ndr_err = ndr_push_struct_blob ( & blob , mem_ctx , & packet ,
( ndr_push_flags_fn_t ) ndr_push_nbt_ntlogon_packet ) ;
if ( ! NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) {
2008-04-16 23:52:34 +02:00
return false ;
}
return cli_send_mailslot ( msg_ctx ,
2008-04-21 10:55:23 +02:00
false , NBT_MAILSLOT_NTLOGON , 0 ,
( char * ) blob . data , blob . length ,
2008-04-16 23:52:34 +02:00
global_myname ( ) , 0 , domain_name , 0x1c ,
dc_ss ) ;
}
2008-04-21 17:51:36 +02:00
bool receive_getdc_response ( TALLOC_CTX * mem_ctx ,
struct sockaddr_storage * dc_ss ,
2008-04-16 23:52:34 +02:00
const char * domain_name ,
2008-05-07 18:57:43 +02:00
uint32_t * nt_version ,
2008-04-24 21:37:42 +02:00
const char * * dc_name ,
2008-05-07 18:57:43 +02:00
union nbt_cldap_netlogon * * reply )
2008-04-16 23:52:34 +02:00
{
struct packet_struct * packet ;
2008-04-21 10:55:23 +02:00
const char * my_mailslot = NULL ;
2008-04-16 23:52:34 +02:00
struct in_addr dc_ip ;
2008-04-21 10:55:23 +02:00
DATA_BLOB blob ;
2008-05-07 18:57:43 +02:00
union nbt_cldap_netlogon r ;
2008-04-21 10:55:23 +02:00
union dgram_message_body p ;
enum ndr_err_code ndr_err ;
2008-04-16 23:52:34 +02:00
2008-04-24 21:29:48 +02:00
const char * returned_dc = NULL ;
const char * returned_domain = NULL ;
2008-04-16 23:52:34 +02:00
if ( dc_ss - > ss_family ! = AF_INET ) {
return false ;
}
2008-04-21 10:55:23 +02:00
2008-04-16 23:52:34 +02:00
dc_ip = ( ( struct sockaddr_in * ) dc_ss ) - > sin_addr ;
2008-04-21 10:55:23 +02:00
my_mailslot = mailslot_name ( mem_ctx , dc_ip ) ;
if ( ! my_mailslot ) {
return false ;
}
2008-04-16 23:52:34 +02: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 10:55:23 +02:00
blob = data_blob_const ( packet - > packet . dgram . data ,
packet - > packet . dgram . datasize ) ;
2008-04-16 23:52:34 +02:00
2008-04-21 10:55:23 +02:00
if ( blob . length < 4 ) {
DEBUG ( 0 , ( " invalid length: %d \n " , ( int ) blob . length ) ) ;
return false ;
2008-04-16 23:52:34 +02:00
}
2008-04-21 10:55:23 +02:00
if ( RIVAL ( blob . data , 0 ) ! = DGRAM_SMB ) {
DEBUG ( 0 , ( " invalid packet \n " ) ) ;
return false ;
}
blob . data + = 4 ;
blob . length - = 4 ;
ndr_err = ndr_pull_union_blob_all ( & blob , mem_ctx , & p , DGRAM_SMB ,
( 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 18:57:43 +02:00
if ( DEBUGLEVEL > = 10 ) {
NDR_PRINT_DEBUG ( dgram_smb_packet , & p ) ;
}
2008-04-21 10:55:23 +02:00
blob = p . smb . body . trans . data ;
2008-05-07 18:57:43 +02:00
if ( ! pull_mailslot_cldap_reply ( mem_ctx , & blob ,
& r , nt_version ) )
{
2008-04-21 10:55:23 +02:00
return false ;
}
2008-05-07 18:57:43 +02:00
switch ( * nt_version ) {
case 1 :
2008-05-14 09:41:24 +02:00
case 16 :
case 17 :
2008-05-07 18:57:43 +02:00
returned_domain = r . logon1 . domain_name ;
returned_dc = r . logon1 . pdc_name ;
break ;
case 2 :
case 3 :
2008-05-14 09:41:24 +02:00
case 18 :
case 19 :
2008-05-07 18:57:43 +02:00
returned_domain = r . logon3 . domain_name ;
returned_dc = r . logon3 . pdc_name ;
2008-04-24 21:29:48 +02:00
break ;
2008-05-07 18:57:43 +02:00
case 4 :
case 5 :
case 6 :
case 7 :
returned_domain = r . logon5 . domain ;
returned_dc = r . logon5 . pdc_name ;
break ;
case 8 :
case 9 :
case 10 :
case 11 :
case 12 :
case 13 :
case 14 :
case 15 :
returned_domain = r . logon13 . domain ;
returned_dc = r . logon13 . pdc_name ;
2008-04-24 21:29:48 +02:00
break ;
2008-05-14 09:41:24 +02:00
case 20 :
case 21 :
case 22 :
case 23 :
case 24 :
case 25 :
case 26 :
case 27 :
case 28 :
returned_domain = r . logon15 . domain ;
returned_dc = r . logon15 . pdc_name ;
break ;
case 29 :
case 30 :
case 31 :
2008-05-07 18:57:43 +02:00
returned_domain = r . logon29 . domain ;
returned_dc = r . logon29 . pdc_name ;
break ;
2008-05-14 09:41:24 +02:00
default :
return false ;
2008-04-24 21:29:48 +02:00
}
if ( ! strequal ( returned_domain , domain_name ) ) {
2008-04-21 10:55:23 +02:00
DEBUG ( 3 , ( " GetDC: Expected domain %s, got %s \n " ,
2008-04-24 21:29:48 +02:00
domain_name , returned_domain ) ) ;
2008-04-21 10:55:23 +02:00
return false ;
}
2008-04-24 21:29:48 +02:00
* dc_name = talloc_strdup ( mem_ctx , returned_dc ) ;
2008-04-21 10:55:23 +02:00
if ( ! * dc_name ) {
return false ;
2008-04-16 23:52:34 +02:00
}
2008-04-21 10:55:23 +02:00
if ( * * dc_name = = ' \\ ' ) * dc_name + = 1 ;
if ( * * dc_name = = ' \\ ' ) * dc_name + = 1 ;
2008-04-16 23:52:34 +02:00
2008-04-24 21:37:42 +02:00
if ( reply ) {
2008-05-07 18:57:43 +02:00
* reply = ( union nbt_cldap_netlogon * ) talloc_memdup (
mem_ctx , & r , sizeof ( union nbt_cldap_netlogon ) ) ;
2008-04-24 21:37:42 +02:00
if ( ! * reply ) {
return false ;
}
}
2008-04-16 23:52:34 +02:00
DEBUG ( 10 , ( " GetDC gave name %s for domain %s \n " ,
2008-04-24 21:29:48 +02:00
* dc_name , returned_domain ) ) ;
2008-04-16 23:52:34 +02:00
return True ;
}