2005-04-06 15:17:08 +04:00
/*
Unix SMB / CIFS implementation .
NBT dgram testing
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 "libcli/dgram/libdgram.h"
2005-04-13 09:07:04 +04:00
# include "librpc/gen_ndr/ndr_samr.h"
2005-04-06 15:17:08 +04:00
# include "lib/socket/socket.h"
# include "lib/events/events.h"
# define TEST_NAME "TORTURE_TEST"
/*
reply handler for netlogon request
*/
static void netlogon_handler ( struct dgram_mailslot_handler * dgmslot ,
struct nbt_dgram_packet * packet ,
2005-10-14 16:22:15 +04:00
const struct nbt_peer_socket * src )
2005-04-06 15:17:08 +04:00
{
2005-04-08 09:34:13 +04:00
NTSTATUS status ;
struct nbt_netlogon_packet netlogon ;
2005-04-08 09:46:00 +04:00
int * replies = dgmslot - > private ;
2005-04-08 09:34:13 +04:00
2005-10-14 16:22:15 +04:00
printf ( " netlogon reply from %s:%d \n " , src - > addr , src - > port ) ;
2005-04-08 09:34:13 +04:00
status = dgram_mailslot_netlogon_parse ( dgmslot , dgmslot , packet , & netlogon ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to parse netlogon packet from %s:%d \n " ,
2005-10-14 16:22:15 +04:00
src - > addr , src - > port ) ;
2005-04-08 09:34:13 +04:00
return ;
}
NDR_PRINT_DEBUG ( nbt_netlogon_packet , & netlogon ) ;
2005-04-08 09:46:00 +04:00
( * replies ) + + ;
2005-04-06 15:17:08 +04:00
}
2005-04-08 09:34:13 +04:00
2005-04-06 15:17:08 +04:00
/* test UDP/138 netlogon requests */
static BOOL nbt_test_netlogon ( TALLOC_CTX * mem_ctx ,
struct nbt_name name , const char * address )
{
struct dgram_mailslot_handler * dgmslot ;
struct nbt_dgram_socket * dgmsock = nbt_dgram_socket_init ( mem_ctx , NULL ) ;
2005-10-14 16:22:15 +04:00
struct nbt_peer_socket dest ;
2005-04-13 09:07:04 +04:00
const char * myaddress = talloc_strdup ( dgmsock , iface_best_ip ( address ) ) ;
2005-04-06 15:17:08 +04:00
struct nbt_netlogon_packet logon ;
struct nbt_name myname ;
NTSTATUS status ;
struct timeval tv = timeval_current ( ) ;
2005-04-08 09:46:00 +04:00
int replies = 0 ;
2005-04-06 15:17:08 +04:00
2005-04-08 09:34:13 +04:00
/* try receiving replies on port 138 first, which will only
work if we are root and smbd / nmbd are not running - fall
back to listening on any port , which means replies from
some windows versions won ' t be seen */
status = socket_listen ( dgmsock - > sock , myaddress , lp_dgram_port ( ) , 0 , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
socket_listen ( dgmsock - > sock , myaddress , 0 , 0 , 0 ) ;
}
2005-04-06 15:17:08 +04:00
/* setup a temporary mailslot listener for replies */
2005-04-08 12:57:09 +04:00
dgmslot = dgram_mailslot_temp ( dgmsock , NBT_MAILSLOT_GETDC ,
2005-04-08 09:46:00 +04:00
netlogon_handler , & replies ) ;
2005-04-06 15:17:08 +04:00
ZERO_STRUCT ( logon ) ;
logon . command = NETLOGON_QUERY_FOR_PDC ;
logon . req . pdc . computer_name = TEST_NAME ;
logon . req . pdc . mailslot_name = dgmslot - > mailslot_name ;
logon . req . pdc . unicode_name = TEST_NAME ;
logon . req . pdc . nt_version = 1 ;
logon . req . pdc . lmnt_token = 0xFFFF ;
logon . req . pdc . lm20_token = 0xFFFF ;
2005-05-22 14:23:01 +04:00
make_nbt_name_client ( & myname , TEST_NAME ) ;
2005-04-06 15:17:08 +04:00
2005-10-14 16:22:15 +04:00
dest . port = 0 ;
dest . addr = address ;
status = dgram_mailslot_netlogon_send ( dgmsock , & name , & dest ,
& myname , & logon ) ;
2005-04-06 15:17:08 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to send netlogon request - %s \n " , nt_errstr ( status ) ) ;
goto failed ;
}
2005-04-08 09:46:00 +04:00
while ( timeval_elapsed ( & tv ) < 5 & & replies = = 0 ) {
2005-04-06 15:17:08 +04:00
event_loop_once ( dgmsock - > event_ctx ) ;
}
talloc_free ( dgmsock ) ;
return True ;
failed :
talloc_free ( dgmsock ) ;
return False ;
}
2005-04-14 06:36:30 +04:00
/* test UDP/138 netlogon requests */
static BOOL nbt_test_netlogon2 ( TALLOC_CTX * mem_ctx ,
struct nbt_name name , const char * address )
{
struct dgram_mailslot_handler * dgmslot ;
struct nbt_dgram_socket * dgmsock = nbt_dgram_socket_init ( mem_ctx , NULL ) ;
2005-10-14 16:22:15 +04:00
struct nbt_peer_socket dest ;
2005-04-14 06:36:30 +04:00
const char * myaddress = talloc_strdup ( dgmsock , iface_best_ip ( address ) ) ;
struct nbt_netlogon_packet logon ;
struct nbt_name myname ;
NTSTATUS status ;
struct timeval tv = timeval_current ( ) ;
int replies = 0 ;
/* try receiving replies on port 138 first, which will only
work if we are root and smbd / nmbd are not running - fall
back to listening on any port , which means replies from
some windows versions won ' t be seen */
status = socket_listen ( dgmsock - > sock , myaddress , lp_dgram_port ( ) , 0 , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
socket_listen ( dgmsock - > sock , myaddress , 0 , 0 , 0 ) ;
}
/* setup a temporary mailslot listener for replies */
dgmslot = dgram_mailslot_temp ( dgmsock , NBT_MAILSLOT_GETDC ,
netlogon_handler , & replies ) ;
ZERO_STRUCT ( logon ) ;
logon . command = NETLOGON_QUERY_FOR_PDC2 ;
logon . req . pdc2 . request_count = 0 ;
logon . req . pdc2 . computer_name = TEST_NAME ;
logon . req . pdc2 . user_name = " " ;
logon . req . pdc2 . mailslot_name = dgmslot - > mailslot_name ;
logon . req . pdc2 . nt_version = 11 ;
logon . req . pdc2 . lmnt_token = 0xFFFF ;
logon . req . pdc2 . lm20_token = 0xFFFF ;
2005-05-22 14:23:01 +04:00
make_nbt_name_client ( & myname , TEST_NAME ) ;
2005-04-14 06:36:30 +04:00
2005-10-14 16:22:15 +04:00
dest . port = 0 ;
dest . addr = address ;
status = dgram_mailslot_netlogon_send ( dgmsock , & name , & dest ,
& myname , & logon ) ;
2005-04-14 06:36:30 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to send netlogon request - %s \n " , nt_errstr ( status ) ) ;
goto failed ;
}
while ( timeval_elapsed ( & tv ) < 5 & & replies = = 0 ) {
event_loop_once ( dgmsock - > event_ctx ) ;
}
talloc_free ( dgmsock ) ;
return True ;
failed :
talloc_free ( dgmsock ) ;
return False ;
}
2005-04-13 09:07:04 +04:00
/*
reply handler for ntlogon request
*/
static void ntlogon_handler ( struct dgram_mailslot_handler * dgmslot ,
struct nbt_dgram_packet * packet ,
2005-10-14 16:22:15 +04:00
const struct nbt_peer_socket * src )
2005-04-13 09:07:04 +04:00
{
NTSTATUS status ;
struct nbt_ntlogon_packet ntlogon ;
int * replies = dgmslot - > private ;
2005-10-14 16:22:15 +04:00
printf ( " ntlogon reply from %s:%d \n " , src - > addr , src - > port ) ;
2005-04-13 09:07:04 +04:00
status = dgram_mailslot_ntlogon_parse ( dgmslot , dgmslot , packet , & ntlogon ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to parse ntlogon packet from %s:%d \n " ,
2005-10-14 16:22:15 +04:00
src - > addr , src - > port ) ;
2005-04-13 09:07:04 +04:00
return ;
}
NDR_PRINT_DEBUG ( nbt_ntlogon_packet , & ntlogon ) ;
( * replies ) + + ;
}
/* test UDP/138 ntlogon requests */
static BOOL nbt_test_ntlogon ( TALLOC_CTX * mem_ctx ,
struct nbt_name name , const char * address )
{
struct dgram_mailslot_handler * dgmslot ;
struct nbt_dgram_socket * dgmsock = nbt_dgram_socket_init ( mem_ctx , NULL ) ;
2005-10-14 16:22:15 +04:00
struct nbt_peer_socket dest ;
2005-04-13 09:07:04 +04:00
const char * myaddress = talloc_strdup ( dgmsock , iface_best_ip ( address ) ) ;
struct nbt_ntlogon_packet logon ;
struct nbt_name myname ;
NTSTATUS status ;
struct timeval tv = timeval_current ( ) ;
int replies = 0 ;
struct test_join * join_ctx ;
2005-10-04 03:46:21 +04:00
struct cli_credentials * machine_credentials ;
2005-04-13 09:07:04 +04:00
const char * dom_sid ;
2005-09-25 16:26:07 +04:00
join_ctx = torture_join_domain ( TEST_NAME ,
2005-10-04 03:46:21 +04:00
ACB_WSTRUST , & machine_credentials ) ;
2005-04-13 09:07:04 +04:00
if ( join_ctx = = NULL ) {
printf ( " Failed to join domain %s as %s \n " , lp_workgroup ( ) , TEST_NAME ) ;
talloc_free ( dgmsock ) ;
return False ;
}
dom_sid = torture_join_sid ( join_ctx ) ;
/* try receiving replies on port 138 first, which will only
work if we are root and smbd / nmbd are not running - fall
back to listening on any port , which means replies from
some windows versions won ' t be seen */
status = socket_listen ( dgmsock - > sock , myaddress , lp_dgram_port ( ) , 0 , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
socket_listen ( dgmsock - > sock , myaddress , 0 , 0 , 0 ) ;
}
/* setup a temporary mailslot listener for replies */
dgmslot = dgram_mailslot_temp ( dgmsock , NBT_MAILSLOT_GETDC ,
ntlogon_handler , & replies ) ;
ZERO_STRUCT ( logon ) ;
logon . command = NTLOGON_SAM_LOGON ;
logon . req . logon . request_count = 0 ;
logon . req . logon . computer_name = TEST_NAME ;
logon . req . logon . user_name = TEST_NAME " $ " ;
logon . req . logon . mailslot_name = dgmslot - > mailslot_name ;
logon . req . logon . acct_control = ACB_WSTRUST ;
logon . req . logon . sid = * dom_sid_parse_talloc ( dgmslot , dom_sid ) ;
logon . req . logon . nt_version = 1 ;
logon . req . logon . lmnt_token = 0xFFFF ;
logon . req . logon . lm20_token = 0xFFFF ;
2005-05-22 14:23:01 +04:00
make_nbt_name_client ( & myname , TEST_NAME ) ;
2005-04-13 09:07:04 +04:00
2005-10-14 16:22:15 +04:00
dest . port = 0 ;
dest . addr = address ;
2005-10-14 18:02:47 +04:00
status = dgram_mailslot_ntlogon_send ( dgmsock , DGRAM_DIRECT_UNIQUE ,
& name , & dest , & myname , & logon ) ;
2005-04-13 09:07:04 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to send ntlogon request - %s \n " , nt_errstr ( status ) ) ;
goto failed ;
}
while ( timeval_elapsed ( & tv ) < 5 & & replies = = 0 ) {
event_loop_once ( dgmsock - > event_ctx ) ;
}
torture_leave_domain ( join_ctx ) ;
talloc_free ( dgmsock ) ;
return True ;
failed :
torture_leave_domain ( join_ctx ) ;
talloc_free ( dgmsock ) ;
return False ;
}
2005-04-06 15:17:08 +04:00
/*
test nbt dgram operations
*/
BOOL torture_nbt_dgram ( void )
{
const char * address ;
struct nbt_name name ;
TALLOC_CTX * mem_ctx = talloc_new ( NULL ) ;
NTSTATUS status ;
BOOL ret = True ;
2005-04-13 09:07:04 +04:00
name . name = lp_workgroup ( ) ;
2005-04-14 11:40:23 +04:00
name . type = NBT_NAME_LOGON ;
2005-04-06 15:17:08 +04:00
name . scope = NULL ;
/* do an initial name resolution to find its IP */
2005-08-28 06:37:14 +04:00
status = resolve_name ( & name , mem_ctx , & address , event_context_find ( mem_ctx ) ) ;
2005-04-06 15:17:08 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
printf ( " Failed to resolve %s - %s \n " ,
name . name , nt_errstr ( status ) ) ;
talloc_free ( mem_ctx ) ;
return False ;
}
ret & = nbt_test_netlogon ( mem_ctx , name , address ) ;
2005-04-14 06:36:30 +04:00
ret & = nbt_test_netlogon2 ( mem_ctx , name , address ) ;
2005-04-13 09:07:04 +04:00
ret & = nbt_test_ntlogon ( mem_ctx , name , address ) ;
2005-04-06 15:17:08 +04:00
talloc_free ( mem_ctx ) ;
return ret ;
}