2005-10-04 05:51:55 +04:00
/*
Unix SMB / CIFS implementation .
irpc services for the NBT server
Copyright ( C ) Andrew Tridgell 2005
Copyright ( C ) Volker Lendecke 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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-10-04 05:51:55 +04: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 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-10-04 05:51:55 +04:00
*/
# include "includes.h"
# include "smbd/service_task.h"
2006-03-07 17:13:38 +03:00
# include "smbd/service.h"
2005-10-04 05:51:55 +04:00
# include "nbt_server/nbt_server.h"
2005-12-30 15:43:11 +03:00
# include "nbt_server/wins/winsserver.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/ndr_irpc.h"
2006-01-10 01:12:53 +03:00
# include "lib/socket/socket.h"
2006-03-07 14:07:23 +03:00
# include "libcli/resolve/resolve.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/ndr_nbt.h"
2005-10-04 05:51:55 +04:00
/*
serve out the nbt statistics
*/
static NTSTATUS nbtd_information ( struct irpc_message * msg ,
struct nbtd_information * r )
{
struct nbtd_server * server = talloc_get_type ( msg - > private , struct nbtd_server ) ;
switch ( r - > in . level ) {
case NBTD_INFO_STATISTICS :
r - > out . info . stats = & server - > stats ;
break ;
}
return NT_STATUS_OK ;
}
/*
2008-05-17 06:43:42 +04:00
winbind needs to be able to do a getdc request , but most ( all ? ) windows
2005-10-04 05:51:55 +04:00
servers always send the reply to port 138 , regardless of the request
port . To cope with this we use a irpc request to the NBT server
which has port 138 open , and thus can receive the replies
*/
struct getdc_state {
struct irpc_message * msg ;
struct nbtd_getdcname * req ;
} ;
2008-05-17 06:43:42 +04:00
static void getdc_recv_netlogon_reply ( struct dgram_mailslot_handler * dgmslot ,
2008-05-17 07:24:29 +04:00
struct nbt_dgram_packet * packet ,
struct socket_address * src )
2005-10-04 05:51:55 +04:00
{
struct getdc_state * s =
talloc_get_type ( dgmslot - > private , struct getdc_state ) ;
2008-05-17 06:43:42 +04:00
const char * p ;
struct nbt_netlogon_response netlogon ;
2005-10-04 05:51:55 +04:00
NTSTATUS status ;
2008-05-17 07:24:29 +04:00
status = dgram_mailslot_netlogon_parse_response ( dgmslot , packet , packet ,
& netlogon ) ;
2005-10-04 05:51:55 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 5 , ( " dgram_mailslot_ntlogon_parse failed: %s \n " ,
nt_errstr ( status ) ) ) ;
goto done ;
}
2008-05-17 06:43:42 +04:00
/* We asked for version 1 only */
if ( netlogon . response_type = = NETLOGON_SAMLOGON
& & netlogon . samlogon . ntver ! = NETLOGON_NT_VERSION_1 ) {
status = NT_STATUS_INVALID_NETWORK_RESPONSE ;
goto done ;
}
p = netlogon . samlogon . nt4 . server ;
2005-10-04 05:51:55 +04:00
2008-05-17 06:43:42 +04:00
DEBUG ( 10 , ( " NTLOGON_SAM_LOGON_REPLY: server: %s, user: %s, "
" domain: %s \n " , p , netlogon . samlogon . nt4 . user_name ,
netlogon . samlogon . nt4 . domain ) ) ;
if ( * p = = ' \\ ' ) p + = 1 ;
if ( * p = = ' \\ ' ) p + = 1 ;
s - > req - > out . dcname = talloc_strdup ( s - > req , p ) ;
if ( s - > req - > out . dcname = = NULL ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
status = NT_STATUS_NO_MEMORY ;
goto done ;
2005-10-04 05:51:55 +04:00
}
2008-05-20 09:28:26 +04:00
status = NT_STATUS_OK ;
2005-10-04 05:51:55 +04:00
done :
irpc_send_reply ( s - > msg , status ) ;
}
static NTSTATUS nbtd_getdcname ( struct irpc_message * msg ,
struct nbtd_getdcname * req )
{
struct nbtd_server * server =
talloc_get_type ( msg - > private , struct nbtd_server ) ;
2007-10-07 01:33:16 +04:00
struct nbtd_interface * iface = nbtd_find_request_iface ( server , req - > in . ip_address , true ) ;
2005-10-04 05:51:55 +04:00
struct getdc_state * s ;
2008-05-17 06:43:42 +04:00
struct nbt_netlogon_packet p ;
struct NETLOGON_SAM_LOGON_REQUEST * r ;
2005-10-04 05:51:55 +04:00
struct nbt_name src , dst ;
2006-01-10 01:12:53 +03:00
struct socket_address * dest ;
2005-10-04 05:51:55 +04:00
struct dgram_mailslot_handler * handler ;
NTSTATUS status = NT_STATUS_UNSUCCESSFUL ;
DEBUG ( 0 , ( " nbtd_getdcname called \n " ) ) ;
s = talloc ( msg , struct getdc_state ) ;
NT_STATUS_HAVE_NO_MEMORY ( s ) ;
s - > msg = msg ;
s - > req = req ;
2005-11-14 04:50:55 +03:00
handler = dgram_mailslot_temp ( iface - > dgmsock , NBT_MAILSLOT_GETDC ,
2008-05-17 06:43:42 +04:00
getdc_recv_netlogon_reply , s ) ;
2005-10-04 05:51:55 +04:00
NT_STATUS_HAVE_NO_MEMORY ( handler ) ;
ZERO_STRUCT ( p ) ;
2008-05-17 06:43:42 +04:00
p . command = LOGON_SAM_LOGON_REQUEST ;
2005-10-04 05:51:55 +04:00
r = & p . req . logon ;
r - > request_count = 0 ;
r - > computer_name = req - > in . my_computername ;
r - > user_name = req - > in . my_accountname ;
r - > mailslot_name = handler - > mailslot_name ;
r - > acct_control = req - > in . account_control ;
r - > sid = * req - > in . domain_sid ;
2008-05-17 06:43:42 +04:00
r - > nt_version = NETLOGON_NT_VERSION_1 ;
2005-10-04 05:51:55 +04:00
r - > lmnt_token = 0xffff ;
r - > lm20_token = 0xffff ;
make_nbt_name_client ( & src , req - > in . my_computername ) ;
make_nbt_name ( & dst , req - > in . domainname , 0x1c ) ;
2006-01-10 01:12:53 +03:00
dest = socket_address_from_strings ( msg , iface - > dgmsock - > sock - > backend_name ,
req - > in . ip_address , 138 ) ;
NT_STATUS_HAVE_NO_MEMORY ( dest ) ;
2008-05-17 06:43:42 +04:00
status = dgram_mailslot_netlogon_send ( iface - > dgmsock ,
& dst , dest ,
NBT_MAILSLOT_NETLOGON ,
& src , & p ) ;
2005-10-04 05:51:55 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " dgram_mailslot_ntlogon_send failed: %s \n " ,
nt_errstr ( status ) ) ) ;
return status ;
}
2007-10-07 01:33:16 +04:00
msg - > defer_reply = true ;
2005-10-04 05:51:55 +04:00
return NT_STATUS_OK ;
}
/*
register the irpc handlers for the nbt server
*/
void nbtd_register_irpc ( struct nbtd_server * nbtsrv )
{
NTSTATUS status ;
struct task_server * task = nbtsrv - > task ;
status = IRPC_REGISTER ( task - > msg_ctx , irpc , NBTD_INFORMATION ,
nbtd_information , nbtsrv ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
task_server_terminate ( task , " nbtd failed to setup monitoring " ) ;
return ;
}
status = IRPC_REGISTER ( task - > msg_ctx , irpc , NBTD_GETDCNAME ,
nbtd_getdcname , nbtsrv ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
task_server_terminate ( task , " nbtd failed to setup getdcname "
" handler " ) ;
return ;
}
2005-12-02 18:37:52 +03:00
status = IRPC_REGISTER ( task - > msg_ctx , irpc , NBTD_PROXY_WINS_CHALLENGE ,
nbtd_proxy_wins_challenge , nbtsrv ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
task_server_terminate ( task , " nbtd failed to setup wins challenge "
" handler " ) ;
return ;
}
status = IRPC_REGISTER ( task - > msg_ctx , irpc , NBTD_PROXY_WINS_RELEASE_DEMAND ,
nbtd_proxy_wins_release_demand , nbtsrv ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
task_server_terminate ( task , " nbtd failed to setup wins release demand "
" handler " ) ;
return ;
}
2005-10-04 05:51:55 +04:00
}