2010-11-12 09:23:34 +03:00
/*
Unix SMB / CIFS implementation .
KDC Server request proxying
Copyright ( C ) Andrew Tridgell 2010
Copyright ( C ) Andrew Bartlett 2010
2011-02-09 11:07:47 +03:00
Copyright ( C ) Stefan Metzmacher 2011
2010-11-12 09:23:34 +03: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
the Free Software Foundation ; either version 3 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 , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
# include "smbd/process_model.h"
# include "lib/tsocket/tsocket.h"
# include "libcli/util/tstream.h"
2011-02-09 11:07:47 +03:00
# include "lib/util/tevent_ntstatus.h"
2010-11-12 09:23:34 +03:00
# include "lib/stream/packet.h"
# include "kdc/kdc-glue.h"
2010-12-12 14:15:51 +03:00
# include "dsdb/samdb/samdb.h"
2010-11-12 09:23:34 +03:00
# include "libcli/composite/composite.h"
# include "libcli/resolve/resolve.h"
/*
get a list of our replication partners from repsFrom , returning it in * proxy_list
*/
static WERROR kdc_proxy_get_writeable_dcs ( struct kdc_server * kdc , TALLOC_CTX * mem_ctx , char * * * proxy_list )
{
WERROR werr ;
uint32_t count , i ;
struct repsFromToBlob * reps ;
werr = dsdb_loadreps ( kdc - > samdb , mem_ctx , ldb_get_default_basedn ( kdc - > samdb ) , " repsFrom " , & reps , & count ) ;
W_ERROR_NOT_OK_RETURN ( werr ) ;
if ( count = = 0 ) {
/* we don't have any DCs to replicate with. Very
strange for a RODC */
DEBUG ( 1 , ( __location__ " : No replication sources for RODC in KDC proxy \n " ) ) ;
talloc_free ( reps ) ;
return WERR_DS_DRA_NO_REPLICA ;
}
( * proxy_list ) = talloc_array ( mem_ctx , char * , count + 1 ) ;
W_ERROR_HAVE_NO_MEMORY_AND_FREE ( * proxy_list , reps ) ;
talloc_steal ( * proxy_list , reps ) ;
for ( i = 0 ; i < count ; i + + ) {
const char * dns_name = NULL ;
if ( reps - > version = = 1 ) {
dns_name = reps - > ctr . ctr1 . other_info - > dns_name ;
} else if ( reps - > version = = 2 ) {
dns_name = reps - > ctr . ctr2 . other_info - > dns_name1 ;
}
( * proxy_list ) [ i ] = talloc_strdup ( * proxy_list , dns_name ) ;
W_ERROR_HAVE_NO_MEMORY_AND_FREE ( ( * proxy_list ) [ i ] , * proxy_list ) ;
}
( * proxy_list ) [ i ] = NULL ;
talloc_free ( reps ) ;
return WERR_OK ;
}
struct kdc_udp_proxy_state {
2011-02-09 11:07:47 +03:00
struct tevent_context * ev ;
2010-11-12 09:23:34 +03:00
struct kdc_server * kdc ;
2011-02-09 11:07:47 +03:00
uint16_t port ;
DATA_BLOB in ;
DATA_BLOB out ;
2010-11-12 09:23:34 +03:00
char * * proxy_list ;
uint32_t next_proxy ;
2011-02-09 11:07:47 +03:00
struct {
struct nbt_name name ;
const char * ip ;
struct tdgram_context * dgram ;
} proxy ;
2010-11-12 09:23:34 +03:00
} ;
2011-02-09 11:07:47 +03:00
static void kdc_udp_next_proxy ( struct tevent_req * req ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
struct tevent_req * kdc_udp_proxy_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct kdc_server * kdc ,
uint16_t port ,
DATA_BLOB in )
2010-11-12 09:23:34 +03:00
{
2011-02-09 11:07:47 +03:00
struct tevent_req * req ;
struct kdc_udp_proxy_state * state ;
WERROR werr ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct kdc_udp_proxy_state ) ;
if ( req = = NULL ) {
return NULL ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 11:07:47 +03:00
state - > ev = ev ;
state - > kdc = kdc ;
state - > port = port ;
state - > in = in ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
werr = kdc_proxy_get_writeable_dcs ( kdc , state , & state - > proxy_list ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
NTSTATUS status = werror_to_ntstatus ( werr ) ;
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
}
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
kdc_udp_next_proxy ( req ) ;
if ( ! tevent_req_is_in_progress ( req ) ) {
return tevent_req_post ( req , ev ) ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 11:07:47 +03:00
return req ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 11:07:47 +03:00
static void kdc_udp_proxy_resolve_done ( struct composite_context * csubreq ) ;
2010-11-12 09:23:34 +03:00
/*
2011-02-09 11:07:47 +03:00
try the next proxy in the list
2010-11-12 09:23:34 +03:00
*/
2011-02-09 11:07:47 +03:00
static void kdc_udp_next_proxy ( struct tevent_req * req )
2010-11-12 09:23:34 +03:00
{
2011-02-09 11:07:47 +03:00
struct kdc_udp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_udp_proxy_state ) ;
const char * proxy_dnsname = state - > proxy_list [ state - > next_proxy ] ;
struct composite_context * csubreq ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
if ( proxy_dnsname = = NULL ) {
tevent_req_nterror ( req , NT_STATUS_NO_LOGON_SERVERS ) ;
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 11:07:47 +03:00
state - > next_proxy + + ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
/* make sure we close the socket of the last try */
TALLOC_FREE ( state - > proxy . dgram ) ;
ZERO_STRUCT ( state - > proxy ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
make_nbt_name ( & state - > proxy . name , proxy_dnsname , 0 ) ;
csubreq = resolve_name_ex_send ( lpcfg_resolve_context ( state - > kdc - > task - > lp_ctx ) ,
state ,
RESOLVE_NAME_FLAG_FORCE_DNS ,
0 ,
& state - > proxy . name ,
state - > ev ) ;
if ( tevent_req_nomem ( csubreq , req ) ) {
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 11:07:47 +03:00
csubreq - > async . fn = kdc_udp_proxy_resolve_done ;
csubreq - > async . private_data = req ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 11:07:47 +03:00
static void kdc_udp_proxy_sendto_done ( struct tevent_req * subreq ) ;
static void kdc_udp_proxy_recvfrom_done ( struct tevent_req * subreq ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
static void kdc_udp_proxy_resolve_done ( struct composite_context * csubreq )
2010-11-12 09:23:34 +03:00
{
2011-02-09 11:07:47 +03:00
struct tevent_req * req =
talloc_get_type_abort ( csubreq - > async . private_data ,
struct tevent_req ) ;
struct kdc_udp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_udp_proxy_state ) ;
2010-11-12 09:23:34 +03:00
NTSTATUS status ;
2011-02-09 11:07:47 +03:00
struct tevent_req * subreq ;
2010-11-12 09:23:34 +03:00
struct tsocket_address * local_addr , * proxy_addr ;
int ret ;
2011-02-09 11:07:47 +03:00
status = resolve_name_recv ( csubreq , state , & state - > proxy . ip ) ;
2010-11-12 09:23:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-02-09 11:07:47 +03:00
DEBUG ( 0 , ( " Unable to resolve proxy[%s] - %s \n " ,
state - > proxy . name . name , nt_errstr ( status ) ) ) ;
kdc_udp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
/* get an address for us to use locally */
ret = tsocket_address_inet_from_strings ( state , " ip " , NULL , 0 , & local_addr ) ;
if ( ret ! = 0 ) {
2011-02-09 11:07:47 +03:00
kdc_udp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
ret = tsocket_address_inet_from_strings ( state , " ip " ,
2011-02-09 11:07:47 +03:00
state - > proxy . ip ,
state - > port ,
& proxy_addr ) ;
2010-11-12 09:23:34 +03:00
if ( ret ! = 0 ) {
2011-02-09 11:07:47 +03:00
kdc_udp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
/* create a socket for us to work on */
2011-02-09 11:07:47 +03:00
ret = tdgram_inet_udp_socket ( local_addr , proxy_addr ,
state , & state - > proxy . dgram ) ;
2010-11-12 09:23:34 +03:00
if ( ret ! = 0 ) {
2011-02-09 11:07:47 +03:00
kdc_udp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 11:07:47 +03:00
subreq = tdgram_sendto_send ( state ,
state - > ev ,
state - > proxy . dgram ,
state - > in . data ,
state - > in . length ,
NULL ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 11:07:47 +03:00
tevent_req_set_callback ( subreq , kdc_udp_proxy_sendto_done , req ) ;
2010-11-12 09:23:34 +03:00
/* setup to receive the reply from the proxy */
2011-02-09 11:07:47 +03:00
subreq = tdgram_recvfrom_send ( state , state - > ev , state - > proxy . dgram ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 11:07:47 +03:00
tevent_req_set_callback ( subreq , kdc_udp_proxy_recvfrom_done , req ) ;
tevent_req_set_endtime ( subreq , state - > ev ,
2010-11-12 09:23:34 +03:00
timeval_current_ofs ( state - > kdc - > proxy_timeout , 0 ) ) ;
2011-02-09 11:07:47 +03:00
DEBUG ( 4 , ( " kdc_udp_proxy: proxying request to %s[%s] \n " ,
state - > proxy . name . name , state - > proxy . ip ) ) ;
2010-11-12 09:23:34 +03:00
}
/*
2011-02-09 11:07:47 +03:00
called when the send of the call to the proxy is complete
this is used to get an errors from the sendto ( )
2010-11-12 09:23:34 +03:00
*/
2011-02-09 11:07:47 +03:00
static void kdc_udp_proxy_sendto_done ( struct tevent_req * subreq )
2010-11-12 09:23:34 +03:00
{
2011-02-09 11:07:47 +03:00
struct tevent_req * req =
tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct kdc_udp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_udp_proxy_state ) ;
ssize_t ret ;
int sys_errno ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
ret = tdgram_sendto_recv ( subreq , & sys_errno ) ;
TALLOC_FREE ( subreq ) ;
if ( ret = = - 1 ) {
DEBUG ( 4 , ( " kdc_udp_proxy: sendto for %s[%s] gave %d : %s \n " ,
state - > proxy . name . name , state - > proxy . ip ,
sys_errno , strerror ( sys_errno ) ) ) ;
kdc_udp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
}
}
/*
2011-02-09 11:07:47 +03:00
called when the proxy replies
2010-11-12 09:23:34 +03:00
*/
2011-02-09 11:07:47 +03:00
static void kdc_udp_proxy_recvfrom_done ( struct tevent_req * subreq )
2010-11-12 09:23:34 +03:00
{
2011-02-09 11:07:47 +03:00
struct tevent_req * req =
tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct kdc_udp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_udp_proxy_state ) ;
int sys_errno ;
uint8_t * buf ;
ssize_t len ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
len = tdgram_recvfrom_recv ( subreq , & sys_errno ,
state , & buf , NULL ) ;
TALLOC_FREE ( subreq ) ;
if ( len = = - 1 ) {
DEBUG ( 4 , ( " kdc_udp_proxy: reply from %s[%s] gave %d : %s \n " ,
state - > proxy . name . name , state - > proxy . ip ,
sys_errno , strerror ( sys_errno ) ) ) ;
kdc_udp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 11:07:47 +03:00
/*
* Check the reply came from the right IP ?
* As we use connected udp sockets , that should not be needed . . .
*/
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
state - > out . length = len ;
state - > out . data = buf ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
tevent_req_done ( req ) ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 11:07:47 +03:00
NTSTATUS kdc_udp_proxy_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * out )
2010-11-12 09:23:34 +03:00
{
2011-02-09 11:07:47 +03:00
struct kdc_udp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_udp_proxy_state ) ;
NTSTATUS status ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 11:07:47 +03:00
out - > data = talloc_move ( mem_ctx , & state - > out . data ) ;
out - > length = state - > out . length ;
2010-11-12 09:23:34 +03:00
2011-02-09 11:07:47 +03:00
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2010-11-12 09:23:34 +03:00
}
struct kdc_tcp_proxy_state {
2011-02-09 14:17:23 +03:00
struct tevent_context * ev ;
2010-11-12 09:23:34 +03:00
struct kdc_server * kdc ;
uint16_t port ;
2011-02-09 14:17:23 +03:00
DATA_BLOB in ;
uint8_t in_hdr [ 4 ] ;
struct iovec in_iov [ 2 ] ;
DATA_BLOB out ;
2010-11-12 09:23:34 +03:00
char * * proxy_list ;
2011-02-09 14:17:23 +03:00
uint32_t next_proxy ;
struct {
struct nbt_name name ;
const char * ip ;
struct tstream_context * stream ;
} proxy ;
2010-11-12 09:23:34 +03:00
} ;
2011-02-09 14:17:23 +03:00
static void kdc_tcp_next_proxy ( struct tevent_req * req ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
struct tevent_req * kdc_tcp_proxy_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct kdc_server * kdc ,
uint16_t port ,
DATA_BLOB in )
2010-11-12 09:23:34 +03:00
{
2011-02-09 14:17:23 +03:00
struct tevent_req * req ;
struct kdc_tcp_proxy_state * state ;
WERROR werr ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
req = tevent_req_create ( mem_ctx , & state ,
struct kdc_tcp_proxy_state ) ;
if ( req = = NULL ) {
return NULL ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 14:17:23 +03:00
state - > ev = ev ;
state - > kdc = kdc ;
state - > port = port ;
state - > in = in ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
werr = kdc_proxy_get_writeable_dcs ( kdc , state , & state - > proxy_list ) ;
if ( ! W_ERROR_IS_OK ( werr ) ) {
NTSTATUS status = werror_to_ntstatus ( werr ) ;
tevent_req_nterror ( req , status ) ;
return tevent_req_post ( req , ev ) ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 14:17:23 +03:00
RSIVAL ( state - > in_hdr , 0 , state - > in . length ) ;
state - > in_iov [ 0 ] . iov_base = ( char * ) state - > in_hdr ;
state - > in_iov [ 0 ] . iov_len = 4 ;
state - > in_iov [ 1 ] . iov_base = ( char * ) state - > in . data ;
state - > in_iov [ 1 ] . iov_len = state - > in . length ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
kdc_tcp_next_proxy ( req ) ;
if ( ! tevent_req_is_in_progress ( req ) ) {
return tevent_req_post ( req , ev ) ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 14:17:23 +03:00
return req ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 14:17:23 +03:00
static void kdc_tcp_proxy_resolve_done ( struct composite_context * csubreq ) ;
2010-11-12 09:23:34 +03:00
/*
2011-02-09 14:17:23 +03:00
try the next proxy in the list
2010-11-12 09:23:34 +03:00
*/
2011-02-09 14:17:23 +03:00
static void kdc_tcp_next_proxy ( struct tevent_req * req )
2010-11-12 09:23:34 +03:00
{
2011-02-09 14:17:23 +03:00
struct kdc_tcp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_tcp_proxy_state ) ;
const char * proxy_dnsname = state - > proxy_list [ state - > next_proxy ] ;
struct composite_context * csubreq ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
if ( proxy_dnsname = = NULL ) {
tevent_req_nterror ( req , NT_STATUS_NO_LOGON_SERVERS ) ;
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 14:17:23 +03:00
state - > next_proxy + + ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
/* make sure we close the socket of the last try */
TALLOC_FREE ( state - > proxy . stream ) ;
ZERO_STRUCT ( state - > proxy ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
make_nbt_name ( & state - > proxy . name , proxy_dnsname , 0 ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
csubreq = resolve_name_ex_send ( lpcfg_resolve_context ( state - > kdc - > task - > lp_ctx ) ,
state ,
RESOLVE_NAME_FLAG_FORCE_DNS ,
0 ,
& state - > proxy . name ,
state - > ev ) ;
if ( tevent_req_nomem ( csubreq , req ) ) {
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 14:17:23 +03:00
csubreq - > async . fn = kdc_tcp_proxy_resolve_done ;
csubreq - > async . private_data = req ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 14:17:23 +03:00
static void kdc_tcp_proxy_connect_done ( struct tevent_req * subreq ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
static void kdc_tcp_proxy_resolve_done ( struct composite_context * csubreq )
2010-11-12 09:23:34 +03:00
{
2011-02-09 14:17:23 +03:00
struct tevent_req * req =
talloc_get_type_abort ( csubreq - > async . private_data ,
struct tevent_req ) ;
struct kdc_tcp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_tcp_proxy_state ) ;
2010-11-12 09:23:34 +03:00
NTSTATUS status ;
2011-02-09 14:17:23 +03:00
struct tevent_req * subreq ;
2010-11-12 09:23:34 +03:00
struct tsocket_address * local_addr , * proxy_addr ;
int ret ;
2011-02-09 14:17:23 +03:00
status = resolve_name_recv ( csubreq , state , & state - > proxy . ip ) ;
2010-11-12 09:23:34 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2011-02-09 14:17:23 +03:00
DEBUG ( 0 , ( " Unable to resolve proxy[%s] - %s \n " ,
state - > proxy . name . name , nt_errstr ( status ) ) ) ;
kdc_tcp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
/* get an address for us to use locally */
ret = tsocket_address_inet_from_strings ( state , " ip " , NULL , 0 , & local_addr ) ;
if ( ret ! = 0 ) {
2011-02-09 14:17:23 +03:00
kdc_tcp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
ret = tsocket_address_inet_from_strings ( state , " ip " ,
2011-02-09 14:17:23 +03:00
state - > proxy . ip ,
state - > port ,
& proxy_addr ) ;
2010-11-12 09:23:34 +03:00
if ( ret ! = 0 ) {
2011-02-09 14:17:23 +03:00
kdc_tcp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 14:17:23 +03:00
subreq = tstream_inet_tcp_connect_send ( state , state - > ev ,
local_addr , proxy_addr ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 14:17:23 +03:00
tevent_req_set_callback ( subreq , kdc_tcp_proxy_connect_done , req ) ;
tevent_req_set_endtime ( subreq , state - > ev ,
2010-11-12 09:23:34 +03:00
timeval_current_ofs ( state - > kdc - > proxy_timeout , 0 ) ) ;
}
2011-02-09 14:17:23 +03:00
static void kdc_tcp_proxy_writev_done ( struct tevent_req * subreq ) ;
static void kdc_tcp_proxy_read_pdu_done ( struct tevent_req * subreq ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
static void kdc_tcp_proxy_connect_done ( struct tevent_req * subreq )
2010-11-12 09:23:34 +03:00
{
2011-02-09 14:17:23 +03:00
struct tevent_req * req =
tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct kdc_tcp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_tcp_proxy_state ) ;
int ret , sys_errno ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
ret = tstream_inet_tcp_connect_recv ( subreq , & sys_errno ,
state , & state - > proxy . stream , NULL ) ;
TALLOC_FREE ( subreq ) ;
if ( ret ! = 0 ) {
kdc_tcp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 14:17:23 +03:00
subreq = tstream_writev_send ( state ,
state - > ev ,
state - > proxy . stream ,
state - > in_iov , 2 ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 14:17:23 +03:00
tevent_req_set_callback ( subreq , kdc_tcp_proxy_writev_done , req ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
subreq = tstream_read_pdu_blob_send ( state ,
state - > ev ,
state - > proxy . stream ,
4 , /* initial_read_size */
packet_full_request_u32 ,
req ) ;
if ( tevent_req_nomem ( subreq , req ) ) {
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 14:17:23 +03:00
tevent_req_set_callback ( subreq , kdc_tcp_proxy_read_pdu_done , req ) ;
tevent_req_set_endtime ( subreq , state - > kdc - > task - > event_ctx ,
timeval_current_ofs ( state - > kdc - > proxy_timeout , 0 ) ) ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
DEBUG ( 4 , ( " kdc_tcp_proxy: proxying request to %s[%s] \n " ,
state - > proxy . name . name , state - > proxy . ip ) ) ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 14:17:23 +03:00
static void kdc_tcp_proxy_writev_done ( struct tevent_req * subreq )
2010-11-12 09:23:34 +03:00
{
2011-02-09 14:17:23 +03:00
struct tevent_req * req =
tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
int ret , sys_errno ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
ret = tstream_writev_recv ( subreq , & sys_errno ) ;
TALLOC_FREE ( subreq ) ;
if ( ret = = - 1 ) {
kdc_tcp_next_proxy ( req ) ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 14:17:23 +03:00
}
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
static void kdc_tcp_proxy_read_pdu_done ( struct tevent_req * subreq )
{
struct tevent_req * req =
tevent_req_callback_data ( subreq ,
struct tevent_req ) ;
struct kdc_tcp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_tcp_proxy_state ) ;
NTSTATUS status ;
DATA_BLOB raw ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
status = tstream_read_pdu_blob_recv ( subreq , state , & raw ) ;
TALLOC_FREE ( subreq ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
kdc_tcp_next_proxy ( req ) ;
return ;
}
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
/*
* raw blob has the length in the first 4 bytes ,
* which we do not need here .
*/
state - > out = data_blob_talloc ( state , raw . data + 4 , raw . length - 4 ) ;
if ( state - > out . length ! = raw . length - 4 ) {
2011-06-19 23:10:01 +04:00
tevent_req_oom ( req ) ;
2010-11-12 09:23:34 +03:00
return ;
}
2011-02-09 14:17:23 +03:00
tevent_req_done ( req ) ;
}
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
NTSTATUS kdc_tcp_proxy_recv ( struct tevent_req * req ,
TALLOC_CTX * mem_ctx ,
DATA_BLOB * out )
2010-11-12 09:23:34 +03:00
{
2011-02-09 14:17:23 +03:00
struct kdc_tcp_proxy_state * state =
tevent_req_data ( req ,
struct kdc_tcp_proxy_state ) ;
NTSTATUS status ;
2010-11-12 09:23:34 +03:00
2011-02-09 14:17:23 +03:00
if ( tevent_req_is_nterror ( req , & status ) ) {
tevent_req_received ( req ) ;
return status ;
2010-11-12 09:23:34 +03:00
}
2011-02-09 14:17:23 +03:00
out - > data = talloc_move ( mem_ctx , & state - > out . data ) ;
out - > length = state - > out . length ;
tevent_req_received ( req ) ;
return NT_STATUS_OK ;
2010-11-12 09:23:34 +03:00
}