2005-09-26 01:01:56 +04:00
/*
Unix SMB / CIFS implementation .
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
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 .
*/
/*
a composite API for finding a DC and its name
*/
# include "includes.h"
# include "libcli/composite/composite.h"
2005-10-03 21:36:49 +04:00
# include "libcli/smb_composite/smb_composite.h"
2005-09-26 01:01:56 +04:00
# include "winbind/wb_async_helpers.h"
2005-10-08 20:25:00 +04:00
# include "winbind/wb_server.h"
# include "smbd/service_stream.h"
2005-09-26 01:01:56 +04:00
# include "librpc/gen_ndr/nbt.h"
# include "librpc/gen_ndr/samr.h"
# include "lib/messaging/irpc.h"
# include "librpc/gen_ndr/irpc.h"
# include "librpc/gen_ndr/ndr_irpc.h"
2005-10-03 17:46:11 +04:00
# include "libcli/raw/libcliraw.h"
# include "librpc/gen_ndr/ndr_netlogon.h"
2005-10-03 21:36:49 +04:00
# include "librpc/gen_ndr/ndr_lsa.h"
2005-10-03 17:46:11 +04:00
# include "libcli/auth/credentials.h"
2005-09-26 01:01:56 +04:00
struct finddcs_state {
2005-10-09 16:50:35 +04:00
struct composite_context * ctx ;
struct messaging_context * msg_ctx ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
const char * domain_name ;
const struct dom_sid * domain_sid ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
struct nbtd_getdcname r ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
int num_dcs ;
struct nbt_dc_name * dcs ;
} ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
static void finddcs_resolve ( struct composite_context * ctx ) ;
static void finddcs_getdc ( struct irpc_request * ireq ) ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
struct composite_context * wb_finddcs_send ( const char * domain_name ,
const struct dom_sid * domain_sid ,
struct event_context * event_ctx ,
struct messaging_context * msg_ctx )
2005-09-26 01:01:56 +04:00
{
2005-10-09 16:50:35 +04:00
struct composite_context * result , * ctx ;
struct finddcs_state * state ;
struct nbt_name name ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
result = talloc_zero ( NULL , struct composite_context ) ;
if ( result = = NULL ) goto failed ;
result - > state = COMPOSITE_STATE_IN_PROGRESS ;
2005-10-15 23:18:05 +04:00
result - > async . fn = NULL ;
2005-10-09 16:50:35 +04:00
result - > event_ctx = event_ctx ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
state = talloc ( result , struct finddcs_state ) ;
if ( state = = NULL ) goto failed ;
state - > ctx = result ;
result - > private_data = state ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
state - > domain_name = talloc_strdup ( state , domain_name ) ;
if ( state - > domain_name = = NULL ) goto failed ;
state - > domain_sid = dom_sid_dup ( state , domain_sid ) ;
if ( state - > domain_sid = = NULL ) goto failed ;
state - > msg_ctx = msg_ctx ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
make_nbt_name ( & name , state - > domain_name , 0x1c ) ;
ctx = resolve_name_send ( & name , result - > event_ctx ,
lp_name_resolve_order ( ) ) ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
if ( ctx = = NULL ) goto failed ;
ctx - > async . fn = finddcs_resolve ;
ctx - > async . private_data = state ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
2005-09-26 01:01:56 +04:00
}
2005-10-09 16:50:35 +04:00
static void finddcs_resolve ( struct composite_context * ctx )
2005-09-26 01:01:56 +04:00
{
2005-10-09 16:50:35 +04:00
struct finddcs_state * state =
talloc_get_type ( ctx - > async . private_data , struct finddcs_state ) ;
struct irpc_request * ireq ;
uint32_t * nbt_servers ;
const char * address ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
state - > ctx - > status = resolve_name_recv ( ctx , state , & address ) ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
state - > num_dcs = 1 ;
state - > dcs = talloc_array ( state , struct nbt_dc_name , state - > num_dcs ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > dcs , state - > ctx ) ) return ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
state - > dcs [ 0 ] . address = talloc_steal ( state - > dcs , address ) ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
nbt_servers = irpc_servers_byname ( state - > msg_ctx , " nbt_server " ) ;
if ( ( nbt_servers = = NULL ) | | ( nbt_servers [ 0 ] = = 0 ) ) {
2005-10-10 23:57:55 +04:00
composite_error ( state - > ctx , NT_STATUS_NO_LOGON_SERVERS ) ;
2005-10-09 16:50:35 +04:00
return ;
}
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
state - > r . in . domainname = state - > domain_name ;
state - > r . in . ip_address = state - > dcs [ 0 ] . address ;
state - > r . in . my_computername = lp_netbios_name ( ) ;
state - > r . in . my_accountname = talloc_asprintf ( state , " %s$ " ,
lp_netbios_name ( ) ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > r . in . my_accountname , state - > ctx ) ) return ;
2005-10-09 16:50:35 +04:00
state - > r . in . account_control = ACB_WSTRUST ;
state - > r . in . domain_sid = dom_sid_dup ( state , state - > domain_sid ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > r . in . domain_sid , state - > ctx ) ) return ;
2005-10-09 16:50:35 +04:00
ireq = irpc_call_send ( state - > msg_ctx , nbt_servers [ 0 ] ,
& dcerpc_table_irpc , DCERPC_NBTD_GETDCNAME ,
& state - > r , state ) ;
2005-10-10 23:57:55 +04:00
composite_continue_irpc ( state - > ctx , ireq , finddcs_getdc , state ) ;
2005-09-26 01:01:56 +04:00
}
2005-10-09 16:50:35 +04:00
static void finddcs_getdc ( struct irpc_request * ireq )
2005-09-26 01:01:56 +04:00
{
2005-10-09 16:50:35 +04:00
struct finddcs_state * state =
talloc_get_type ( ireq - > async . private , struct finddcs_state ) ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
state - > ctx - > status = irpc_call_recv ( ireq ) ;
2005-10-15 12:17:22 +04:00
talloc_free ( ireq ) ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-09-26 01:01:56 +04:00
2005-10-09 16:50:35 +04:00
state - > dcs [ 0 ] . name = talloc_steal ( state - > dcs , state - > r . out . dcname ) ;
2005-10-10 23:57:55 +04:00
composite_done ( state - > ctx ) ;
2005-10-09 16:50:35 +04:00
}
NTSTATUS wb_finddcs_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
int * num_dcs , struct nbt_dc_name * * dcs )
{
NTSTATUS status = composite_wait ( c ) ;
2005-09-26 01:01:56 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
2005-10-09 16:50:35 +04:00
struct finddcs_state * state =
talloc_get_type ( c - > private_data , struct finddcs_state ) ;
* num_dcs = state - > num_dcs ;
* dcs = talloc_steal ( mem_ctx , state - > dcs ) ;
2005-09-26 01:01:56 +04:00
}
talloc_free ( c ) ;
return status ;
}
2005-10-09 16:50:35 +04:00
NTSTATUS wb_finddcs ( const char * domain_name , const struct dom_sid * domain_sid ,
struct event_context * event_ctx ,
struct messaging_context * msg_ctx ,
TALLOC_CTX * mem_ctx ,
int * num_dcs , struct nbt_dc_name * * dcs )
2005-09-26 01:01:56 +04:00
{
2005-10-09 16:50:35 +04:00
struct composite_context * c = wb_finddcs_send ( domain_name , domain_sid ,
event_ctx , msg_ctx ) ;
return wb_finddcs_recv ( c , mem_ctx , num_dcs , dcs ) ;
2005-09-26 01:01:56 +04:00
}
2005-10-03 17:46:11 +04:00
struct get_schannel_creds_state {
struct composite_context * ctx ;
2005-10-08 20:25:00 +04:00
struct cli_credentials * wks_creds ;
2005-10-03 17:46:11 +04:00
struct dcerpc_pipe * p ;
2005-10-08 20:25:00 +04:00
struct netr_ServerReqChallenge r ;
2005-10-03 17:46:11 +04:00
2005-10-03 21:36:49 +04:00
struct creds_CredentialState * creds_state ;
2005-10-03 17:46:11 +04:00
struct netr_Credential netr_cred ;
uint32_t negotiate_flags ;
2005-10-08 20:25:00 +04:00
struct netr_ServerAuthenticate2 a ;
2005-10-03 17:46:11 +04:00
} ;
static void get_schannel_creds_recv_auth ( struct rpc_request * req ) ;
static void get_schannel_creds_recv_chal ( struct rpc_request * req ) ;
static void get_schannel_creds_recv_pipe ( struct composite_context * ctx ) ;
2005-10-08 20:25:00 +04:00
struct composite_context * wb_get_schannel_creds_send ( struct cli_credentials * wks_creds ,
struct smbcli_tree * tree ,
2005-10-03 17:46:11 +04:00
struct event_context * ev )
{
struct composite_context * result , * ctx ;
struct get_schannel_creds_state * state ;
result = talloc_zero ( NULL , struct composite_context ) ;
if ( result = = NULL ) goto failed ;
result - > state = COMPOSITE_STATE_IN_PROGRESS ;
2005-10-15 23:18:05 +04:00
result - > async . fn = NULL ;
2005-10-03 17:46:11 +04:00
result - > event_ctx = ev ;
state = talloc ( result , struct get_schannel_creds_state ) ;
if ( state = = NULL ) goto failed ;
result - > private_data = state ;
2005-10-07 23:08:51 +04:00
state - > ctx = result ;
2005-10-03 17:46:11 +04:00
2005-10-08 20:25:00 +04:00
state - > wks_creds = wks_creds ;
2005-10-03 17:46:11 +04:00
state - > p = dcerpc_pipe_init ( state , ev ) ;
if ( state - > p = = NULL ) goto failed ;
2005-10-08 20:25:00 +04:00
ctx = dcerpc_pipe_open_smb_send ( state - > p - > conn , tree , " \\ netlogon " ) ;
2005-10-03 17:46:11 +04:00
if ( ctx = = NULL ) goto failed ;
ctx - > async . fn = get_schannel_creds_recv_pipe ;
ctx - > async . private_data = state ;
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
static void get_schannel_creds_recv_pipe ( struct composite_context * ctx )
{
struct get_schannel_creds_state * state =
talloc_get_type ( ctx - > async . private_data ,
struct get_schannel_creds_state ) ;
struct rpc_request * req ;
state - > ctx - > status = dcerpc_pipe_open_smb_recv ( ctx ) ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-10-03 17:46:11 +04:00
state - > ctx - > status = dcerpc_bind_auth_none ( state - > p ,
DCERPC_NETLOGON_UUID ,
DCERPC_NETLOGON_VERSION ) ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-10-03 17:46:11 +04:00
2005-10-08 20:25:00 +04:00
state - > r . in . computer_name =
cli_credentials_get_workstation ( state - > wks_creds ) ;
state - > r . in . server_name =
talloc_asprintf ( state , " \\ \\ %s " ,
2005-10-03 17:46:11 +04:00
dcerpc_server_name ( state - > p ) ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > r . in . server_name , state - > ctx ) ) return ;
2005-10-03 17:46:11 +04:00
2005-10-08 20:25:00 +04:00
state - > r . in . credentials = talloc ( state , struct netr_Credential ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > r . in . credentials , state - > ctx ) ) return ;
2005-10-03 17:46:11 +04:00
2005-10-08 20:25:00 +04:00
state - > r . out . credentials = talloc ( state , struct netr_Credential ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > r . out . credentials , state - > ctx ) ) return ;
2005-10-03 17:46:11 +04:00
2005-10-08 20:25:00 +04:00
generate_random_buffer ( state - > r . in . credentials - > data ,
sizeof ( state - > r . in . credentials - > data ) ) ;
2005-10-03 17:46:11 +04:00
2005-10-08 20:25:00 +04:00
req = dcerpc_netr_ServerReqChallenge_send ( state - > p , state , & state - > r ) ;
2005-10-10 23:57:55 +04:00
composite_continue_rpc ( state - > ctx , req ,
get_schannel_creds_recv_chal , state ) ;
2005-10-03 17:46:11 +04:00
}
static void get_schannel_creds_recv_chal ( struct rpc_request * req )
{
struct get_schannel_creds_state * state =
talloc_get_type ( req - > async . private ,
struct get_schannel_creds_state ) ;
const struct samr_Password * mach_pwd ;
state - > ctx - > status = dcerpc_ndr_request_recv ( req ) ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-10-08 20:25:00 +04:00
state - > ctx - > status = state - > r . out . result ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-10-03 17:46:11 +04:00
2005-10-03 21:36:49 +04:00
state - > creds_state = talloc ( state , struct creds_CredentialState ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > creds_state , state - > ctx ) ) return ;
2005-10-08 20:25:00 +04:00
mach_pwd = cli_credentials_get_nt_hash ( state - > wks_creds , state ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( mach_pwd , state - > ctx ) ) return ;
2005-10-03 17:46:11 +04:00
state - > negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS ;
2005-10-08 20:25:00 +04:00
creds_client_init ( state - > creds_state , state - > r . in . credentials ,
state - > r . out . credentials , mach_pwd ,
2005-10-03 17:46:11 +04:00
& state - > netr_cred , state - > negotiate_flags ) ;
2005-10-08 20:25:00 +04:00
state - > a . in . server_name =
talloc_reference ( state , state - > r . in . server_name ) ;
state - > a . in . account_name =
cli_credentials_get_username ( state - > wks_creds ) ;
state - > a . in . secure_channel_type =
cli_credentials_get_secure_channel_type ( state - > wks_creds ) ;
state - > a . in . computer_name =
cli_credentials_get_workstation ( state - > wks_creds ) ;
state - > a . in . negotiate_flags = & state - > negotiate_flags ;
state - > a . out . negotiate_flags = & state - > negotiate_flags ;
state - > a . in . credentials = & state - > netr_cred ;
state - > a . out . credentials = & state - > netr_cred ;
req = dcerpc_netr_ServerAuthenticate2_send ( state - > p , state , & state - > a ) ;
2005-10-10 23:57:55 +04:00
composite_continue_rpc ( state - > ctx , req ,
get_schannel_creds_recv_auth , state ) ;
2005-10-03 17:46:11 +04:00
}
static void get_schannel_creds_recv_auth ( struct rpc_request * req )
{
struct get_schannel_creds_state * state =
talloc_get_type ( req - > async . private ,
struct get_schannel_creds_state ) ;
state - > ctx - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! NT_STATUS_IS_OK ( state - > ctx - > status ) ) goto done ;
2005-10-08 20:25:00 +04:00
state - > ctx - > status = state - > a . out . result ;
2005-10-03 17:46:11 +04:00
if ( ! NT_STATUS_IS_OK ( state - > ctx - > status ) ) goto done ;
2005-10-03 21:36:49 +04:00
if ( ! creds_client_check ( state - > creds_state ,
2005-10-08 20:25:00 +04:00
state - > a . out . credentials ) ) {
2005-10-03 21:36:49 +04:00
DEBUG ( 5 , ( " Server got us invalid creds \n " ) ) ;
state - > ctx - > status = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
2005-10-10 23:57:55 +04:00
cli_credentials_set_netlogon_creds ( state - > wks_creds ,
state - > creds_state ) ;
2005-10-03 21:36:49 +04:00
2005-10-03 17:46:11 +04:00
state - > ctx - > state = COMPOSITE_STATE_DONE ;
done :
if ( ! NT_STATUS_IS_OK ( state - > ctx - > status ) ) {
state - > ctx - > state = COMPOSITE_STATE_ERROR ;
}
if ( ( state - > ctx - > state > = COMPOSITE_STATE_DONE ) & &
( state - > ctx - > async . fn ! = NULL ) ) {
state - > ctx - > async . fn ( state - > ctx ) ;
}
}
NTSTATUS wb_get_schannel_creds_recv ( struct composite_context * c ,
2005-10-08 20:25:00 +04:00
TALLOC_CTX * mem_ctx ,
struct dcerpc_pipe * * netlogon_pipe )
2005-10-03 17:46:11 +04:00
{
NTSTATUS status = composite_wait ( c ) ;
2005-10-08 20:25:00 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
struct get_schannel_creds_state * state =
talloc_get_type ( c - > private_data ,
struct get_schannel_creds_state ) ;
* netlogon_pipe = talloc_steal ( mem_ctx , state - > p ) ;
}
2005-10-03 17:46:11 +04:00
talloc_free ( c ) ;
return status ;
}
2005-10-08 20:25:00 +04:00
NTSTATUS wb_get_schannel_creds ( struct cli_credentials * wks_creds ,
struct smbcli_tree * tree ,
struct event_context * event_ctx ,
2005-10-03 17:46:11 +04:00
TALLOC_CTX * mem_ctx ,
2005-10-08 20:25:00 +04:00
struct dcerpc_pipe * * netlogon_pipe )
2005-10-03 17:46:11 +04:00
{
2005-10-08 20:25:00 +04:00
struct composite_context * c =
wb_get_schannel_creds_send ( wks_creds , tree , event_ctx ) ;
return wb_get_schannel_creds_recv ( c , mem_ctx , netlogon_pipe ) ;
2005-10-03 17:46:11 +04:00
}
2005-10-03 21:36:49 +04:00
2005-10-19 17:45:44 +04:00
struct lsa_lookupsids_state {
struct composite_context * ctx ;
int num_sids ;
struct lsa_LookupSids r ;
struct lsa_SidArray sids ;
struct lsa_TransNameArray names ;
uint32_t count ;
struct wb_sid_object * * result ;
} ;
static void lsa_lookupsids_recv_names ( struct rpc_request * req ) ;
struct composite_context * wb_lsa_lookupsids_send ( struct dcerpc_pipe * lsa_pipe ,
struct policy_handle * handle ,
int num_sids ,
const struct dom_sid * * sids )
{
struct composite_context * result ;
struct rpc_request * req ;
struct lsa_lookupsids_state * state ;
int i ;
result = talloc_zero ( NULL , struct composite_context ) ;
if ( result = = NULL ) goto failed ;
result - > state = COMPOSITE_STATE_IN_PROGRESS ;
result - > async . fn = NULL ;
result - > event_ctx = lsa_pipe - > conn - > event_ctx ;
state = talloc ( result , struct lsa_lookupsids_state ) ;
if ( state = = NULL ) goto failed ;
result - > private_data = state ;
state - > ctx = result ;
state - > sids . num_sids = num_sids ;
state - > sids . sids = talloc_array ( state , struct lsa_SidPtr , num_sids ) ;
if ( state - > sids . sids = = NULL ) goto failed ;
for ( i = 0 ; i < num_sids ; i + + ) {
state - > sids . sids [ i ] . sid = dom_sid_dup ( state - > sids . sids ,
sids [ i ] ) ;
if ( state - > sids . sids [ i ] . sid = = NULL ) goto failed ;
}
state - > count = 0 ;
state - > num_sids = num_sids ;
state - > names . count = 0 ;
state - > names . names = NULL ;
state - > r . in . handle = handle ;
state - > r . in . sids = & state - > sids ;
state - > r . in . names = & state - > names ;
state - > r . in . level = 1 ;
state - > r . in . count = & state - > count ;
state - > r . out . names = & state - > names ;
state - > r . out . count = & state - > count ;
req = dcerpc_lsa_LookupSids_send ( lsa_pipe , state , & state - > r ) ;
if ( req = = NULL ) goto failed ;
req - > async . callback = lsa_lookupsids_recv_names ;
req - > async . private = state ;
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
static void lsa_lookupsids_recv_names ( struct rpc_request * req )
{
struct lsa_lookupsids_state * state =
talloc_get_type ( req - > async . private ,
struct lsa_lookupsids_state ) ;
int i ;
state - > ctx - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > ctx - > status = state - > r . out . result ;
if ( ! NT_STATUS_IS_OK ( state - > ctx - > status ) & &
! NT_STATUS_EQUAL ( state - > ctx - > status , STATUS_SOME_UNMAPPED ) ) {
composite_error ( state - > ctx , state - > ctx - > status ) ;
return ;
}
state - > result = talloc_array ( state , struct wb_sid_object * ,
state - > num_sids ) ;
if ( composite_nomem ( state - > result , state - > ctx ) ) return ;
for ( i = 0 ; i < state - > num_sids ; i + + ) {
struct lsa_TranslatedName * name =
& state - > r . out . names - > names [ i ] ;
struct lsa_TrustInformation * dom ;
state - > result [ i ] = talloc_zero ( state - > result ,
struct wb_sid_object ) ;
if ( composite_nomem ( state - > result [ i ] , state - > ctx ) ) return ;
state - > result [ i ] - > type = name - > sid_type ;
if ( state - > result [ i ] - > type = = SID_NAME_UNKNOWN ) {
continue ;
}
if ( name - > sid_index > = state - > r . out . domains - > count ) {
composite_error ( state - > ctx ,
NT_STATUS_INVALID_PARAMETER ) ;
return ;
}
dom = & state - > r . out . domains - > domains [ name - > sid_index ] ;
state - > result [ i ] - > domain = talloc_reference ( state - > result [ i ] ,
dom - > name . string ) ;
if ( ( name - > sid_type = = SID_NAME_DOMAIN ) | |
( name - > name . string = = NULL ) ) {
state - > result [ i ] - > name =
talloc_strdup ( state - > result [ i ] , " " ) ;
} else {
state - > result [ i ] - > name =
talloc_steal ( state - > result [ i ] ,
name - > name . string ) ;
}
if ( composite_nomem ( state - > result [ i ] - > name , state - > ctx ) ) {
return ;
}
}
composite_done ( state - > ctx ) ;
}
NTSTATUS wb_lsa_lookupsids_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
struct wb_sid_object * * * names )
{
NTSTATUS status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
struct lsa_lookupsids_state * state =
talloc_get_type ( c - > private_data ,
struct lsa_lookupsids_state ) ;
* names = talloc_steal ( mem_ctx , state - > result ) ;
}
talloc_free ( c ) ;
return status ;
}
NTSTATUS wb_lsa_lookupsids ( struct dcerpc_pipe * lsa_pipe ,
struct policy_handle * handle ,
int num_sids , const struct dom_sid * * sids ,
TALLOC_CTX * mem_ctx ,
struct wb_sid_object * * * names )
{
struct composite_context * c =
wb_lsa_lookupsids_send ( lsa_pipe , handle , num_sids , sids ) ;
return wb_lsa_lookupnames_recv ( c , mem_ctx , names ) ;
}
2005-10-07 23:08:51 +04:00
struct lsa_lookupnames_state {
struct composite_context * ctx ;
uint32_t num_names ;
struct lsa_LookupNames r ;
struct lsa_TransSidArray sids ;
uint32_t count ;
struct wb_sid_object * * result ;
} ;
static void lsa_lookupnames_recv_sids ( struct rpc_request * req ) ;
struct composite_context * wb_lsa_lookupnames_send ( struct dcerpc_pipe * lsa_pipe ,
struct policy_handle * handle ,
int num_names ,
const char * * names )
{
struct composite_context * result ;
struct rpc_request * req ;
struct lsa_lookupnames_state * state ;
struct lsa_String * lsa_names ;
int i ;
result = talloc_zero ( NULL , struct composite_context ) ;
if ( result = = NULL ) goto failed ;
result - > state = COMPOSITE_STATE_IN_PROGRESS ;
2005-10-15 23:18:05 +04:00
result - > async . fn = NULL ;
2005-10-07 23:08:51 +04:00
result - > event_ctx = lsa_pipe - > conn - > event_ctx ;
state = talloc ( result , struct lsa_lookupnames_state ) ;
if ( state = = NULL ) goto failed ;
result - > private_data = state ;
2005-10-08 20:25:00 +04:00
state - > ctx = result ;
2005-10-07 23:08:51 +04:00
state - > sids . count = 0 ;
state - > sids . sids = NULL ;
state - > num_names = num_names ;
state - > count = 0 ;
lsa_names = talloc_array ( state , struct lsa_String , num_names ) ;
if ( lsa_names = = NULL ) goto failed ;
for ( i = 0 ; i < num_names ; i + + ) {
lsa_names [ i ] . string = names [ i ] ;
}
state - > r . in . handle = handle ;
state - > r . in . num_names = num_names ;
state - > r . in . names = lsa_names ;
state - > r . in . sids = & state - > sids ;
state - > r . in . level = 1 ;
state - > r . in . count = & state - > count ;
state - > r . out . count = & state - > count ;
state - > r . out . sids = & state - > sids ;
req = dcerpc_lsa_LookupNames_send ( lsa_pipe , state , & state - > r ) ;
if ( req = = NULL ) goto failed ;
req - > async . callback = lsa_lookupnames_recv_sids ;
req - > async . private = state ;
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
static void lsa_lookupnames_recv_sids ( struct rpc_request * req )
{
struct lsa_lookupnames_state * state =
talloc_get_type ( req - > async . private ,
struct lsa_lookupnames_state ) ;
int i ;
state - > ctx - > status = dcerpc_ndr_request_recv ( req ) ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-10-07 23:08:51 +04:00
state - > ctx - > status = state - > r . out . result ;
if ( ! NT_STATUS_IS_OK ( state - > ctx - > status ) & &
! NT_STATUS_EQUAL ( state - > ctx - > status , STATUS_SOME_UNMAPPED ) ) {
2005-10-10 23:57:55 +04:00
composite_error ( state - > ctx , state - > ctx - > status ) ;
2005-10-08 20:25:00 +04:00
return ;
2005-10-07 23:08:51 +04:00
}
state - > result = talloc_array ( state , struct wb_sid_object * ,
state - > num_names ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > result , state - > ctx ) ) return ;
2005-10-07 23:08:51 +04:00
for ( i = 0 ; i < state - > num_names ; i + + ) {
struct lsa_TranslatedSid * sid = & state - > r . out . sids - > sids [ i ] ;
struct lsa_TrustInformation * dom ;
state - > result [ i ] = talloc_zero ( state - > result ,
struct wb_sid_object ) ;
2005-10-10 23:57:55 +04:00
if ( composite_nomem ( state - > result [ i ] , state - > ctx ) ) return ;
2005-10-07 23:08:51 +04:00
state - > result [ i ] - > type = sid - > sid_type ;
if ( state - > result [ i ] - > type = = SID_NAME_UNKNOWN ) {
continue ;
}
if ( sid - > sid_index > = state - > r . out . domains - > count ) {
2005-10-10 23:57:55 +04:00
composite_error ( state - > ctx ,
NT_STATUS_INVALID_PARAMETER ) ;
2005-10-08 20:25:00 +04:00
return ;
2005-10-07 23:08:51 +04:00
}
dom = & state - > r . out . domains - > domains [ sid - > sid_index ] ;
state - > result [ i ] - > sid = dom_sid_add_rid ( state - > result [ i ] ,
dom - > sid , sid - > rid ) ;
}
2005-10-10 23:57:55 +04:00
composite_done ( state - > ctx ) ;
2005-10-07 23:08:51 +04:00
}
NTSTATUS wb_lsa_lookupnames_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
struct wb_sid_object * * * sids )
{
NTSTATUS status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
struct lsa_lookupnames_state * state =
talloc_get_type ( c - > private_data ,
struct lsa_lookupnames_state ) ;
* sids = talloc_steal ( mem_ctx , state - > result ) ;
}
talloc_free ( c ) ;
return status ;
}
NTSTATUS wb_lsa_lookupnames ( struct dcerpc_pipe * lsa_pipe ,
struct policy_handle * handle ,
int num_names , const char * * names ,
TALLOC_CTX * mem_ctx ,
struct wb_sid_object * * * sids )
{
struct composite_context * c =
wb_lsa_lookupnames_send ( lsa_pipe , handle , num_names , names ) ;
return wb_lsa_lookupnames_recv ( c , mem_ctx , sids ) ;
}
2005-10-08 20:25:00 +04:00
struct cmd_checkmachacc_state {
struct composite_context * ctx ;
struct wbsrv_call * call ;
2005-10-09 16:50:35 +04:00
struct wbsrv_domain * domain ;
2005-10-08 20:25:00 +04:00
} ;
r10852: Continuation-based programming can become a bit spaghetti...
Initialize a domain structure properly. Excerpt from wb_init_domain.c:
/*
* Initialize a domain:
*
* - With schannel credentials, try to open the SMB connection with the machine
* creds. Fall back to anonymous.
*
* - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
* pipe.
*
* - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
* to schannel and then to anon bind.
*
* - With queryinfopolicy, verify that we're talking to the right domain
*
* A bit complex, but with all the combinations I think it's the best we can
* get. NT4, W2k3SP1 and W2k all have different combinations, but in the end we
* have a signed&sealed lsa connection on all of them.
*
* Is this overkill? In particular the authenticated SMB connection seems a
* bit overkill, given that we do schannel for netlogon and ntlmssp for
* lsa later on w2k3, the others don't do this anyway.
*/
Thanks to Jeremy for his detective work, and to the Samba4 team for providing
such a great infrastructure.
Next step is to connect to SAM. Do it via LDAP if we can, fall back to samr
with all we have.
Volker
(This used to be commit 3e69fdc07cd76b4bc01b032148609ee4b59b8be7)
2005-10-10 00:32:24 +04:00
static void cmd_checkmachacc_recv_init ( struct composite_context * ctx ) ;
2005-10-08 20:25:00 +04:00
struct composite_context * wb_cmd_checkmachacc_send ( struct wbsrv_call * call )
{
struct composite_context * result , * ctx ;
struct cmd_checkmachacc_state * state ;
struct wbsrv_service * service = call - > wbconn - > listen_socket - > service ;
result = talloc ( call , struct composite_context ) ;
if ( result = = NULL ) goto failed ;
result - > state = COMPOSITE_STATE_IN_PROGRESS ;
2005-10-15 23:18:05 +04:00
result - > async . fn = NULL ;
2005-10-08 20:25:00 +04:00
result - > event_ctx = call - > event_ctx ;
state = talloc ( result , struct cmd_checkmachacc_state ) ;
if ( state = = NULL ) goto failed ;
state - > ctx = result ;
result - > private_data = state ;
state - > call = call ;
2005-10-09 16:50:35 +04:00
state - > domain = service - > domains ;
2005-10-24 13:34:12 +04:00
ctx = wb_init_domain_send ( service , state - > domain ) ;
2005-10-08 20:25:00 +04:00
if ( ctx = = NULL ) goto failed ;
r10852: Continuation-based programming can become a bit spaghetti...
Initialize a domain structure properly. Excerpt from wb_init_domain.c:
/*
* Initialize a domain:
*
* - With schannel credentials, try to open the SMB connection with the machine
* creds. Fall back to anonymous.
*
* - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
* pipe.
*
* - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
* to schannel and then to anon bind.
*
* - With queryinfopolicy, verify that we're talking to the right domain
*
* A bit complex, but with all the combinations I think it's the best we can
* get. NT4, W2k3SP1 and W2k all have different combinations, but in the end we
* have a signed&sealed lsa connection on all of them.
*
* Is this overkill? In particular the authenticated SMB connection seems a
* bit overkill, given that we do schannel for netlogon and ntlmssp for
* lsa later on w2k3, the others don't do this anyway.
*/
Thanks to Jeremy for his detective work, and to the Samba4 team for providing
such a great infrastructure.
Next step is to connect to SAM. Do it via LDAP if we can, fall back to samr
with all we have.
Volker
(This used to be commit 3e69fdc07cd76b4bc01b032148609ee4b59b8be7)
2005-10-10 00:32:24 +04:00
ctx - > async . fn = cmd_checkmachacc_recv_init ;
2005-10-08 20:25:00 +04:00
ctx - > async . private_data = state ;
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
r10852: Continuation-based programming can become a bit spaghetti...
Initialize a domain structure properly. Excerpt from wb_init_domain.c:
/*
* Initialize a domain:
*
* - With schannel credentials, try to open the SMB connection with the machine
* creds. Fall back to anonymous.
*
* - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
* pipe.
*
* - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
* to schannel and then to anon bind.
*
* - With queryinfopolicy, verify that we're talking to the right domain
*
* A bit complex, but with all the combinations I think it's the best we can
* get. NT4, W2k3SP1 and W2k all have different combinations, but in the end we
* have a signed&sealed lsa connection on all of them.
*
* Is this overkill? In particular the authenticated SMB connection seems a
* bit overkill, given that we do schannel for netlogon and ntlmssp for
* lsa later on w2k3, the others don't do this anyway.
*/
Thanks to Jeremy for his detective work, and to the Samba4 team for providing
such a great infrastructure.
Next step is to connect to SAM. Do it via LDAP if we can, fall back to samr
with all we have.
Volker
(This used to be commit 3e69fdc07cd76b4bc01b032148609ee4b59b8be7)
2005-10-10 00:32:24 +04:00
static void cmd_checkmachacc_recv_init ( struct composite_context * ctx )
2005-10-08 20:25:00 +04:00
{
struct cmd_checkmachacc_state * state =
talloc_get_type ( ctx - > async . private_data ,
struct cmd_checkmachacc_state ) ;
r10852: Continuation-based programming can become a bit spaghetti...
Initialize a domain structure properly. Excerpt from wb_init_domain.c:
/*
* Initialize a domain:
*
* - With schannel credentials, try to open the SMB connection with the machine
* creds. Fall back to anonymous.
*
* - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
* pipe.
*
* - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
* to schannel and then to anon bind.
*
* - With queryinfopolicy, verify that we're talking to the right domain
*
* A bit complex, but with all the combinations I think it's the best we can
* get. NT4, W2k3SP1 and W2k all have different combinations, but in the end we
* have a signed&sealed lsa connection on all of them.
*
* Is this overkill? In particular the authenticated SMB connection seems a
* bit overkill, given that we do schannel for netlogon and ntlmssp for
* lsa later on w2k3, the others don't do this anyway.
*/
Thanks to Jeremy for his detective work, and to the Samba4 team for providing
such a great infrastructure.
Next step is to connect to SAM. Do it via LDAP if we can, fall back to samr
with all we have.
Volker
(This used to be commit 3e69fdc07cd76b4bc01b032148609ee4b59b8be7)
2005-10-10 00:32:24 +04:00
state - > ctx - > status = wb_init_domain_recv ( ctx ) ;
2005-10-10 23:57:55 +04:00
if ( ! composite_is_ok ( state - > ctx ) ) return ;
2005-10-08 20:25:00 +04:00
2005-10-10 23:57:55 +04:00
composite_done ( state - > ctx ) ;
2005-10-08 20:25:00 +04:00
}
NTSTATUS wb_cmd_checkmachacc_recv ( struct composite_context * c )
{
r10852: Continuation-based programming can become a bit spaghetti...
Initialize a domain structure properly. Excerpt from wb_init_domain.c:
/*
* Initialize a domain:
*
* - With schannel credentials, try to open the SMB connection with the machine
* creds. Fall back to anonymous.
*
* - If we have schannel creds, do the auth2 and open the schannel'ed netlogon
* pipe.
*
* - Open LSA. If we have machine creds, try to open with ntlmssp. Fall back
* to schannel and then to anon bind.
*
* - With queryinfopolicy, verify that we're talking to the right domain
*
* A bit complex, but with all the combinations I think it's the best we can
* get. NT4, W2k3SP1 and W2k all have different combinations, but in the end we
* have a signed&sealed lsa connection on all of them.
*
* Is this overkill? In particular the authenticated SMB connection seems a
* bit overkill, given that we do schannel for netlogon and ntlmssp for
* lsa later on w2k3, the others don't do this anyway.
*/
Thanks to Jeremy for his detective work, and to the Samba4 team for providing
such a great infrastructure.
Next step is to connect to SAM. Do it via LDAP if we can, fall back to samr
with all we have.
Volker
(This used to be commit 3e69fdc07cd76b4bc01b032148609ee4b59b8be7)
2005-10-10 00:32:24 +04:00
NTSTATUS status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
2005-10-08 20:25:00 +04:00
}
NTSTATUS wb_cmd_checkmachacc ( struct wbsrv_call * call )
{
struct composite_context * c = wb_cmd_checkmachacc_send ( call ) ;
return wb_cmd_checkmachacc_recv ( c ) ;
}
2005-10-15 23:18:05 +04:00
static void composite_netr_LogonSamLogon_recv_rpc ( struct rpc_request * req ) ;
struct composite_context * composite_netr_LogonSamLogon_send ( struct dcerpc_pipe * p ,
TALLOC_CTX * mem_ctx ,
struct netr_LogonSamLogon * r )
{
struct composite_context * result ;
struct rpc_request * req ;
result = talloc ( mem_ctx , struct composite_context ) ;
if ( result = = NULL ) goto failed ;
result - > state = COMPOSITE_STATE_IN_PROGRESS ;
result - > async . fn = NULL ;
result - > event_ctx = p - > conn - > event_ctx ;
req = dcerpc_netr_LogonSamLogon_send ( p , mem_ctx , r ) ;
if ( req = = NULL ) goto failed ;
req - > async . callback = composite_netr_LogonSamLogon_recv_rpc ;
req - > async . private = result ;
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
static void composite_netr_LogonSamLogon_recv_rpc ( struct rpc_request * req )
{
struct composite_context * ctx =
talloc_get_type ( req - > async . private , struct composite_context ) ;
ctx - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( ctx ) ) return ;
composite_done ( ctx ) ;
}
NTSTATUS composite_netr_LogonSamLogon_recv ( struct composite_context * ctx )
{
NTSTATUS status = composite_wait ( ctx ) ;
talloc_free ( ctx ) ;
return status ;
}
2005-10-16 02:01:15 +04:00
2005-10-16 16:43:09 +04:00
struct samr_getuserdomgroups_state {
struct composite_context * ctx ;
struct dcerpc_pipe * samr_pipe ;
int num_rids ;
uint32_t * rids ;
struct policy_handle * user_handle ;
struct samr_OpenUser o ;
struct samr_GetGroupsForUser g ;
struct samr_Close c ;
} ;
static void samr_usergroups_recv_open ( struct rpc_request * req ) ;
static void samr_usergroups_recv_groups ( struct rpc_request * req ) ;
static void samr_usergroups_recv_close ( struct rpc_request * req ) ;
struct composite_context * wb_samr_userdomgroups_send ( struct dcerpc_pipe * samr_pipe ,
struct policy_handle * domain_handle ,
uint32_t rid )
{
struct composite_context * result ;
struct rpc_request * req ;
struct samr_getuserdomgroups_state * state ;
result = talloc_zero ( NULL , struct composite_context ) ;
if ( result = = NULL ) goto failed ;
result - > state = COMPOSITE_STATE_IN_PROGRESS ;
result - > async . fn = NULL ;
result - > event_ctx = samr_pipe - > conn - > event_ctx ;
state = talloc ( result , struct samr_getuserdomgroups_state ) ;
if ( state = = NULL ) goto failed ;
result - > private_data = state ;
state - > ctx = result ;
state - > samr_pipe = samr_pipe ;
state - > user_handle = talloc ( state , struct policy_handle ) ;
if ( state - > user_handle = = NULL ) goto failed ;
state - > o . in . domain_handle = domain_handle ;
state - > o . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
state - > o . in . rid = rid ;
state - > o . out . user_handle = state - > user_handle ;
req = dcerpc_samr_OpenUser_send ( state - > samr_pipe , state , & state - > o ) ;
if ( req = = NULL ) goto failed ;
req - > async . callback = samr_usergroups_recv_open ;
req - > async . private = state ;
return result ;
failed :
talloc_free ( result ) ;
return NULL ;
}
static void samr_usergroups_recv_open ( struct rpc_request * req )
{
struct samr_getuserdomgroups_state * state =
talloc_get_type ( req - > async . private ,
struct samr_getuserdomgroups_state ) ;
state - > ctx - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > ctx - > status = state - > o . out . result ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > g . in . user_handle = state - > user_handle ;
req = dcerpc_samr_GetGroupsForUser_send ( state - > samr_pipe , state ,
& state - > g ) ;
composite_continue_rpc ( state - > ctx , req , samr_usergroups_recv_groups ,
state ) ;
}
static void samr_usergroups_recv_groups ( struct rpc_request * req )
{
struct samr_getuserdomgroups_state * state =
talloc_get_type ( req - > async . private ,
struct samr_getuserdomgroups_state ) ;
state - > ctx - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > ctx - > status = state - > g . out . result ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > c . in . handle = state - > user_handle ;
state - > c . out . handle = state - > user_handle ;
req = dcerpc_samr_Close_send ( state - > samr_pipe , state , & state - > c ) ;
composite_continue_rpc ( state - > ctx , req , samr_usergroups_recv_close ,
state ) ;
}
static void samr_usergroups_recv_close ( struct rpc_request * req )
{
struct samr_getuserdomgroups_state * state =
talloc_get_type ( req - > async . private ,
struct samr_getuserdomgroups_state ) ;
state - > ctx - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
state - > ctx - > status = state - > c . out . result ;
if ( ! composite_is_ok ( state - > ctx ) ) return ;
composite_done ( state - > ctx ) ;
}
NTSTATUS wb_samr_userdomgroups_recv ( struct composite_context * ctx ,
TALLOC_CTX * mem_ctx ,
int * num_rids , uint32_t * * rids )
{
struct samr_getuserdomgroups_state * state =
talloc_get_type ( ctx - > private_data ,
struct samr_getuserdomgroups_state ) ;
int i ;
NTSTATUS status = composite_wait ( ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) goto done ;
* num_rids = state - > g . out . rids - > count ;
* rids = talloc_array ( mem_ctx , uint32_t , * num_rids ) ;
if ( * rids = = NULL ) {
status = NT_STATUS_NO_MEMORY ;
goto done ;
}
for ( i = 0 ; i < * num_rids ; i + + ) {
( * rids ) [ i ] = state - > g . out . rids - > rids [ i ] . rid ;
}
done :
talloc_free ( ctx ) ;
return status ;
}