2007-07-19 01:24:37 +04:00
/*
2005-06-04 03:10:26 +04:00
Unix SMB / CIFS implementation .
Copyright ( C ) Rafal Szczesniak 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-06-04 03:10:26 +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-06-04 03:10:26 +04:00
*/
/*
2006-08-31 00:48:06 +04:00
a composite function for domain handling on samr and lsa pipes
2005-06-04 03:10:26 +04:00
*/
# include "includes.h"
# include "libcli/composite/composite.h"
2006-05-16 01:49:27 +04:00
# include "libnet/libnet.h"
2006-03-15 02:35:30 +03:00
# include "librpc/gen_ndr/ndr_samr_c.h"
2006-08-22 00:52:14 +04:00
# include "librpc/gen_ndr/ndr_lsa_c.h"
2005-06-04 03:10:26 +04:00
2006-08-22 00:52:14 +04:00
struct domain_open_samr_state {
2006-05-16 01:49:27 +04:00
struct libnet_context * ctx ;
2005-06-04 03:10:26 +04:00
struct dcerpc_pipe * pipe ;
2007-04-25 19:24:01 +04:00
struct libnet_RpcConnect rpcconn ;
2005-06-04 03:10:26 +04:00
struct samr_Connect connect ;
struct samr_LookupDomain lookup ;
struct samr_OpenDomain open ;
2006-05-16 01:49:27 +04:00
struct samr_Close close ;
2005-07-08 12:09:02 +04:00
struct lsa_String domain_name ;
2005-06-04 03:10:26 +04:00
uint32_t access_mask ;
2005-06-06 12:59:19 +04:00
struct policy_handle connect_handle ;
2005-06-04 03:10:26 +04:00
struct policy_handle domain_handle ;
2006-09-05 21:56:35 +04:00
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
2005-06-04 03:10:26 +04:00
} ;
2007-04-25 19:24:01 +04:00
static void continue_domain_open_close ( struct rpc_request * req ) ;
static void continue_domain_open_connect ( struct rpc_request * req ) ;
static void continue_domain_open_lookup ( struct rpc_request * req ) ;
static void continue_domain_open_open ( struct rpc_request * req ) ;
2006-05-16 01:49:27 +04:00
/**
* Stage 0.5 ( optional ) : Connect to samr rpc pipe
*/
2007-04-25 19:24:01 +04:00
static void continue_domain_open_rpc_connect ( struct composite_context * ctx )
2006-05-16 01:49:27 +04:00
{
struct composite_context * c ;
2006-08-22 00:52:14 +04:00
struct domain_open_samr_state * s ;
2007-04-25 19:24:01 +04:00
struct rpc_request * conn_req ;
2006-05-16 01:49:27 +04:00
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
2006-08-22 00:52:14 +04:00
s = talloc_get_type ( c - > private_data , struct domain_open_samr_state ) ;
2006-05-16 01:49:27 +04:00
c - > status = libnet_RpcConnect_recv ( ctx , s - > ctx , c , & s - > rpcconn ) ;
if ( ! composite_is_ok ( c ) ) return ;
s - > pipe = s - > rpcconn . out . dcerpc_pipe ;
/* preparing parameters for samr_Connect rpc call */
s - > connect . in . system_name = 0 ;
s - > connect . in . access_mask = s - > access_mask ;
s - > connect . out . connect_handle = & s - > connect_handle ;
/* send request */
2007-04-25 19:24:01 +04:00
conn_req = dcerpc_samr_Connect_send ( s - > pipe , c , & s - > connect ) ;
if ( composite_nomem ( conn_req , c ) ) return ;
2006-05-16 01:49:27 +04:00
/* callback handler */
2007-04-25 19:24:01 +04:00
composite_continue_rpc ( c , conn_req , continue_domain_open_connect , c ) ;
2006-05-16 01:49:27 +04:00
}
/**
* Stage 0.5 ( optional ) : Close existing ( in libnet context ) domain
* handle
*/
2007-04-25 19:24:01 +04:00
static void continue_domain_open_close ( struct rpc_request * req )
2006-05-16 01:49:27 +04:00
{
2007-04-25 19:24:01 +04:00
struct composite_context * c ;
struct domain_open_samr_state * s ;
struct rpc_request * conn_req ;
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2007-04-25 19:24:01 +04:00
s = talloc_get_type ( c - > private_data , struct domain_open_samr_state ) ;
2006-05-16 01:49:27 +04:00
/* receive samr_Close reply */
2007-04-25 19:24:01 +04:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-05-16 01:49:27 +04:00
2007-07-19 01:24:37 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
2007-07-26 03:17:02 +04:00
msg . type = mon_SamrClose ;
2007-07-19 01:24:37 +04:00
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2006-05-16 01:49:27 +04:00
/* reset domain handle and associated data in libnet_context */
2006-08-22 00:52:14 +04:00
s - > ctx - > samr . name = NULL ;
s - > ctx - > samr . access_mask = 0 ;
ZERO_STRUCT ( s - > ctx - > samr . handle ) ;
2006-05-16 01:49:27 +04:00
/* preparing parameters for samr_Connect rpc call */
s - > connect . in . system_name = 0 ;
s - > connect . in . access_mask = s - > access_mask ;
s - > connect . out . connect_handle = & s - > connect_handle ;
/* send request */
2007-04-25 19:24:01 +04:00
conn_req = dcerpc_samr_Connect_send ( s - > pipe , c , & s - > connect ) ;
if ( composite_nomem ( conn_req , c ) ) return ;
2006-05-16 01:49:27 +04:00
/* callback handler */
2007-04-25 19:24:01 +04:00
composite_continue_rpc ( c , conn_req , continue_domain_open_connect , c ) ;
2006-05-16 01:49:27 +04:00
}
2005-06-15 02:08:00 +04:00
/**
* Stage 1 : Connect to SAM server .
*/
2007-04-25 19:24:01 +04:00
static void continue_domain_open_connect ( struct rpc_request * req )
2005-06-06 12:59:19 +04:00
{
2007-04-25 19:24:01 +04:00
struct composite_context * c ;
struct domain_open_samr_state * s ;
struct rpc_request * lookup_req ;
struct samr_LookupDomain * r ;
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2007-04-25 19:24:01 +04:00
s = talloc_get_type ( c - > private_data , struct domain_open_samr_state ) ;
2005-06-06 12:59:19 +04:00
/* receive samr_Connect reply */
2007-04-25 19:24:01 +04:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-07-19 01:24:37 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
2007-07-26 03:17:02 +04:00
msg . type = mon_SamrConnect ;
2007-07-19 01:24:37 +04:00
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2007-04-25 19:24:01 +04:00
r = & s - > lookup ;
2005-06-06 12:59:19 +04:00
/* prepare for samr_LookupDomain call */
r - > in . connect_handle = & s - > connect_handle ;
r - > in . domain_name = & s - > domain_name ;
2007-04-25 19:24:01 +04:00
lookup_req = dcerpc_samr_LookupDomain_send ( s - > pipe , c , r ) ;
if ( composite_nomem ( lookup_req , c ) ) return ;
2005-06-06 12:59:19 +04:00
2007-04-25 19:24:01 +04:00
composite_continue_rpc ( c , lookup_req , continue_domain_open_lookup , c ) ;
2005-06-06 12:59:19 +04:00
}
2005-06-15 02:08:00 +04:00
/**
* Stage 2 : Lookup domain by name .
*/
2007-04-25 19:24:01 +04:00
static void continue_domain_open_lookup ( struct rpc_request * req )
2005-06-06 12:59:19 +04:00
{
2007-04-25 19:24:01 +04:00
struct composite_context * c ;
struct domain_open_samr_state * s ;
struct rpc_request * opendom_req ;
struct samr_OpenDomain * r ;
2005-06-06 12:59:19 +04:00
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2007-04-25 19:24:01 +04:00
s = talloc_get_type ( c - > private_data , struct domain_open_samr_state ) ;
2005-06-15 02:08:00 +04:00
/* receive samr_LookupDomain reply */
2007-04-25 19:24:01 +04:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
2007-07-19 01:24:37 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
struct msg_rpc_lookup_domain data ;
data . domain_name = s - > domain_name . string ;
2007-07-26 03:17:02 +04:00
msg . type = mon_SamrLookupDomain ;
2007-07-19 01:24:37 +04:00
msg . data = ( void * ) & data ;
msg . data_size = sizeof ( data ) ;
s - > monitor_fn ( & msg ) ;
}
2007-04-25 19:24:01 +04:00
r = & s - > open ;
/* check the rpc layer status */
if ( ! composite_is_ok ( c ) ) ;
/* check the rpc call itself status */
if ( ! NT_STATUS_IS_OK ( s - > lookup . out . result ) ) {
composite_error ( c , s - > lookup . out . result ) ;
return ;
}
2005-06-06 12:59:19 +04:00
2005-06-15 02:08:00 +04:00
/* prepare for samr_OpenDomain call */
2005-06-06 12:59:19 +04:00
r - > in . connect_handle = & s - > connect_handle ;
r - > in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
r - > in . sid = s - > lookup . out . sid ;
r - > out . domain_handle = & s - > domain_handle ;
2007-04-25 19:24:01 +04:00
opendom_req = dcerpc_samr_OpenDomain_send ( s - > pipe , c , r ) ;
if ( composite_nomem ( opendom_req , c ) ) return ;
2005-06-06 12:59:19 +04:00
2007-04-25 19:24:01 +04:00
composite_continue_rpc ( c , opendom_req , continue_domain_open_open , c ) ;
2005-06-06 12:59:19 +04:00
}
2005-06-15 02:08:00 +04:00
/*
* Stage 3 : Open domain .
*/
2007-04-25 19:24:01 +04:00
static void continue_domain_open_open ( struct rpc_request * req )
2005-06-06 12:59:19 +04:00
{
2007-04-25 19:24:01 +04:00
struct composite_context * c ;
struct domain_open_samr_state * s ;
2005-06-06 12:59:19 +04:00
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2007-04-25 19:24:01 +04:00
s = talloc_get_type ( c - > private_data , struct domain_open_samr_state ) ;
2005-06-04 03:10:26 +04:00
2007-04-25 19:24:01 +04:00
/* receive samr_OpenDomain reply */
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-05-16 01:49:27 +04:00
2007-07-19 01:24:37 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
2007-07-26 03:17:02 +04:00
msg . type = mon_SamrOpenDomain ;
2007-07-19 01:24:37 +04:00
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2007-04-25 19:24:01 +04:00
composite_done ( c ) ;
2005-06-04 03:10:26 +04:00
}
2005-06-15 02:08:00 +04:00
/**
2006-08-31 00:48:06 +04:00
* Sends asynchronous DomainOpenSamr request
2005-06-15 02:08:00 +04:00
*
2006-05-16 01:49:27 +04:00
* @ param ctx initialised libnet context
2005-06-15 02:08:00 +04:00
* @ param io arguments and results of the call
2006-05-16 01:49:27 +04:00
* @ param monitor pointer to monitor function that is passed monitor message
2005-06-15 02:08:00 +04:00
*/
2006-05-16 01:49:27 +04:00
2006-08-22 00:52:14 +04:00
struct composite_context * libnet_DomainOpenSamr_send ( struct libnet_context * ctx ,
struct libnet_DomainOpen * io ,
void ( * monitor ) ( struct monitor_msg * ) )
2005-06-04 03:10:26 +04:00
{
struct composite_context * c ;
2006-08-22 00:52:14 +04:00
struct domain_open_samr_state * s ;
2007-04-25 19:24:01 +04:00
struct composite_context * rpcconn_req ;
struct rpc_request * close_req , * conn_req ;
2005-06-04 03:10:26 +04:00
2006-09-05 21:56:35 +04:00
c = composite_create ( ctx , ctx - > event_ctx ) ;
2006-05-16 01:49:27 +04:00
if ( c = = NULL ) return NULL ;
2005-06-04 03:10:26 +04:00
2006-08-22 00:52:14 +04:00
s = talloc_zero ( c , struct domain_open_samr_state ) ;
2006-05-16 01:49:27 +04:00
if ( composite_nomem ( s , c ) ) return c ;
2005-06-04 03:10:26 +04:00
2006-05-16 01:49:27 +04:00
c - > private_data = s ;
2006-09-05 21:56:35 +04:00
s - > monitor_fn = monitor ;
2005-06-04 03:10:26 +04:00
2006-05-16 01:49:27 +04:00
s - > ctx = ctx ;
2006-08-22 00:52:14 +04:00
s - > pipe = ctx - > samr . pipe ;
2005-06-06 12:59:19 +04:00
s - > access_mask = io - > in . access_mask ;
2006-09-05 22:45:03 +04:00
s - > domain_name . string = talloc_strdup ( c , io - > in . domain_name ) ;
2005-06-06 12:59:19 +04:00
2006-08-31 00:48:06 +04:00
/* check, if there's samr pipe opened already, before opening a domain */
2006-08-22 00:52:14 +04:00
if ( ctx - > samr . pipe = = NULL ) {
2006-08-31 00:48:06 +04:00
/* attempting to connect a domain controller */
2006-05-16 01:49:27 +04:00
s - > rpcconn . level = LIBNET_RPC_CONNECT_DC ;
s - > rpcconn . in . name = io - > in . domain_name ;
s - > rpcconn . in . dcerpc_iface = & dcerpc_table_samr ;
2006-08-31 00:48:06 +04:00
/* send rpc pipe connect request */
2007-07-19 01:24:37 +04:00
rpcconn_req = libnet_RpcConnect_send ( ctx , c , & s - > rpcconn , s - > monitor_fn ) ;
2007-04-25 19:24:01 +04:00
if ( composite_nomem ( rpcconn_req , c ) ) return c ;
2006-05-16 01:49:27 +04:00
2007-04-25 19:24:01 +04:00
composite_continue ( c , rpcconn_req , continue_domain_open_rpc_connect , c ) ;
2006-05-16 01:49:27 +04:00
return c ;
}
/* libnet context's domain handle is not empty, so check out what
was opened first , before doing anything */
2006-08-22 00:52:14 +04:00
if ( ! policy_handle_empty ( & ctx - > samr . handle ) ) {
if ( strequal ( ctx - > samr . name , io - > in . domain_name ) & &
ctx - > samr . access_mask = = io - > in . access_mask ) {
2006-05-16 01:49:27 +04:00
/* this domain is already opened */
composite_done ( c ) ;
return c ;
} else {
/* another domain or access rights have been
requested - close the existing handle first */
2006-08-22 00:52:14 +04:00
s - > close . in . handle = & ctx - > samr . handle ;
2006-05-16 01:49:27 +04:00
/* send request to close domain handle */
2007-04-25 19:24:01 +04:00
close_req = dcerpc_samr_Close_send ( s - > pipe , c , & s - > close ) ;
if ( composite_nomem ( close_req , c ) ) return c ;
2006-05-16 01:49:27 +04:00
/* callback handler */
2007-04-25 19:24:01 +04:00
composite_continue_rpc ( c , close_req , continue_domain_open_close , c ) ;
2006-05-16 01:49:27 +04:00
return c ;
}
}
/* preparing parameters for samr_Connect rpc call */
2005-06-06 12:59:19 +04:00
s - > connect . in . system_name = 0 ;
s - > connect . in . access_mask = s - > access_mask ;
s - > connect . out . connect_handle = & s - > connect_handle ;
2005-06-04 03:10:26 +04:00
/* send request */
2007-04-25 19:24:01 +04:00
conn_req = dcerpc_samr_Connect_send ( s - > pipe , c , & s - > connect ) ;
if ( composite_nomem ( conn_req , c ) ) return c ;
2005-06-04 03:10:26 +04:00
/* callback handler */
2007-04-25 19:24:01 +04:00
composite_continue_rpc ( c , conn_req , continue_domain_open_connect , c ) ;
2005-06-04 03:10:26 +04:00
return c ;
}
2005-06-06 12:59:19 +04:00
2005-06-15 02:08:00 +04:00
/**
2006-08-31 00:48:06 +04:00
* Waits for and receives result of asynchronous DomainOpenSamr call
2005-06-15 02:08:00 +04:00
*
2006-06-28 02:16:36 +04:00
* @ param c composite context returned by asynchronous DomainOpen call
2006-05-16 01:49:27 +04:00
* @ param ctx initialised libnet context
2005-06-15 02:08:00 +04:00
* @ param mem_ctx memory context of the call
* @ param io pointer to results ( and arguments ) of the call
* @ return nt status code of execution
*/
2006-05-16 01:49:27 +04:00
2006-08-22 00:52:14 +04:00
NTSTATUS libnet_DomainOpenSamr_recv ( struct composite_context * c , struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx , struct libnet_DomainOpen * io )
2005-06-06 12:59:19 +04:00
{
NTSTATUS status ;
2006-08-22 00:52:14 +04:00
struct domain_open_samr_state * s ;
2005-06-06 12:59:19 +04:00
2005-06-15 02:08:00 +04:00
/* wait for results of sending request */
2005-06-06 12:59:19 +04:00
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & io ) {
2006-08-22 00:52:14 +04:00
s = talloc_get_type ( c - > private_data , struct domain_open_samr_state ) ;
2005-06-06 12:59:19 +04:00
io - > out . domain_handle = s - > domain_handle ;
2006-05-16 01:49:27 +04:00
/* store the resulting handle and related data for use by other
libnet functions */
2007-07-24 10:02:32 +04:00
ctx - > samr . connect_handle = s - > connect_handle ;
2006-08-22 00:52:14 +04:00
ctx - > samr . handle = s - > domain_handle ;
2007-08-02 17:08:39 +04:00
ctx - > samr . sid = talloc_steal ( ctx , s - > lookup . out . sid ) ;
2006-09-05 22:45:03 +04:00
ctx - > samr . name = talloc_steal ( ctx , s - > domain_name . string ) ;
2006-08-22 00:52:14 +04:00
ctx - > samr . access_mask = s - > access_mask ;
}
talloc_free ( c ) ;
return status ;
}
struct domain_open_lsa_state {
const char * name ;
uint32_t access_mask ;
struct libnet_context * ctx ;
struct libnet_RpcConnect rpcconn ;
struct lsa_OpenPolicy2 openpol ;
struct policy_handle handle ;
struct dcerpc_pipe * pipe ;
2006-09-05 21:56:35 +04:00
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
2006-08-22 00:52:14 +04:00
} ;
static void continue_rpc_connect_lsa ( struct composite_context * ctx ) ;
static void continue_lsa_policy_open ( struct rpc_request * req ) ;
2006-08-31 00:48:06 +04:00
/**
* Sends asynchronous DomainOpenLsa request
*
* @ param ctx initialised libnet context
* @ param io arguments and results of the call
* @ param monitor pointer to monitor function that is passed monitor message
*/
2006-08-22 00:52:14 +04:00
struct composite_context * libnet_DomainOpenLsa_send ( struct libnet_context * ctx ,
struct libnet_DomainOpen * io ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct domain_open_lsa_state * s ;
struct composite_context * rpcconn_req ;
struct rpc_request * openpol_req ;
struct lsa_QosInfo * qos ;
2006-08-31 00:48:06 +04:00
/* create composite context and state */
2006-08-22 00:52:14 +04:00
c = composite_create ( ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return c ;
s = talloc_zero ( c , struct domain_open_lsa_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2006-08-31 00:48:06 +04:00
/* store arguments in the state structure */
s - > name = talloc_strdup ( c , io - > in . domain_name ) ;
s - > access_mask = io - > in . access_mask ;
s - > ctx = ctx ;
2006-08-22 00:52:14 +04:00
2006-08-31 00:48:06 +04:00
/* check, if there's lsa pipe opened already, before opening a handle */
2006-08-22 00:52:14 +04:00
if ( ctx - > lsa . pipe = = NULL ) {
2006-08-31 00:48:06 +04:00
/* attempting to connect a domain controller */
2006-08-22 00:52:14 +04:00
s - > rpcconn . level = LIBNET_RPC_CONNECT_DC ;
s - > rpcconn . in . name = talloc_strdup ( c , io - > in . domain_name ) ;
s - > rpcconn . in . dcerpc_iface = & dcerpc_table_lsarpc ;
2006-08-31 00:48:06 +04:00
/* send rpc pipe connect request */
2007-07-19 01:24:37 +04:00
rpcconn_req = libnet_RpcConnect_send ( ctx , c , & s - > rpcconn , s - > monitor_fn ) ;
2006-08-22 00:52:14 +04:00
if ( composite_nomem ( rpcconn_req , c ) ) return c ;
composite_continue ( c , rpcconn_req , continue_rpc_connect_lsa , c ) ;
return c ;
}
s - > pipe = ctx - > lsa . pipe ;
2006-08-31 00:48:06 +04:00
/* preparing parameters for lsa_OpenPolicy2 rpc call */
2006-08-22 00:52:14 +04:00
s - > openpol . in . system_name = s - > name ;
s - > openpol . in . access_mask = s - > access_mask ;
s - > openpol . in . attr = talloc_zero ( c , struct lsa_ObjectAttribute ) ;
qos = talloc_zero ( c , struct lsa_QosInfo ) ;
qos - > len = 0 ;
qos - > impersonation_level = 2 ;
qos - > context_mode = 1 ;
qos - > effective_only = 0 ;
s - > openpol . in . attr - > sec_qos = qos ;
s - > openpol . out . handle = & s - > handle ;
2006-08-31 00:48:06 +04:00
/* send rpc request */
2006-08-22 00:52:14 +04:00
openpol_req = dcerpc_lsa_OpenPolicy2_send ( s - > pipe , c , & s - > openpol ) ;
if ( composite_nomem ( openpol_req , c ) ) return c ;
composite_continue_rpc ( c , openpol_req , continue_lsa_policy_open , c ) ;
return c ;
}
2006-08-31 00:48:06 +04:00
/*
Stage 0.5 ( optional ) : Rpc pipe connected , send lsa open policy request
*/
2006-08-22 00:52:14 +04:00
static void continue_rpc_connect_lsa ( struct composite_context * ctx )
{
struct composite_context * c ;
struct domain_open_lsa_state * s ;
struct lsa_QosInfo * qos ;
struct rpc_request * openpol_req ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct domain_open_lsa_state ) ;
2006-08-31 00:48:06 +04:00
/* receive rpc connection */
2006-08-22 00:52:14 +04:00
c - > status = libnet_RpcConnect_recv ( ctx , s - > ctx , c , & s - > rpcconn ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-08-31 00:48:06 +04:00
/* RpcConnect function leaves the pipe in libnet context,
so get it from there */
2006-08-22 00:52:14 +04:00
s - > pipe = s - > ctx - > lsa . pipe ;
2006-08-31 00:48:06 +04:00
/* prepare lsa_OpenPolicy2 call */
2006-08-22 00:52:14 +04:00
s - > openpol . in . system_name = s - > name ;
s - > openpol . in . access_mask = s - > access_mask ;
s - > openpol . in . attr = talloc_zero ( c , struct lsa_ObjectAttribute ) ;
qos = talloc_zero ( c , struct lsa_QosInfo ) ;
qos - > len = 0 ;
qos - > impersonation_level = 2 ;
qos - > context_mode = 1 ;
qos - > effective_only = 0 ;
s - > openpol . in . attr - > sec_qos = qos ;
s - > openpol . out . handle = & s - > handle ;
2006-08-31 00:48:06 +04:00
/* send rpc request */
2006-08-22 00:52:14 +04:00
openpol_req = dcerpc_lsa_OpenPolicy2_send ( s - > pipe , c , & s - > openpol ) ;
if ( composite_nomem ( openpol_req , c ) ) return ;
composite_continue_rpc ( c , openpol_req , continue_lsa_policy_open , c ) ;
}
2006-08-31 00:48:06 +04:00
/*
Stage 1 : Lsa policy opened - we ' re done , if successfully
*/
2006-08-22 00:52:14 +04:00
static void continue_lsa_policy_open ( struct rpc_request * req )
{
struct composite_context * c ;
struct domain_open_lsa_state * s ;
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2006-08-22 00:52:14 +04:00
s = talloc_get_type ( c - > private_data , struct domain_open_lsa_state ) ;
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-07-26 03:17:02 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
msg . type = mon_LsaOpenPolicy ;
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2006-08-22 00:52:14 +04:00
composite_done ( c ) ;
}
2006-08-31 00:48:06 +04:00
/**
* Receives result of asynchronous DomainOpenLsa call
*
* @ param c composite context returned by asynchronous DomainOpenLsa call
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of the call
* @ param io pointer to results ( and arguments ) of the call
* @ return nt status code of execution
*/
2006-08-22 00:52:14 +04:00
NTSTATUS libnet_DomainOpenLsa_recv ( struct composite_context * c , struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx , struct libnet_DomainOpen * io )
{
NTSTATUS status ;
struct domain_open_lsa_state * s ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & io ) {
2006-08-31 00:48:06 +04:00
/* everything went fine - get the results and
return the error string */
2006-08-22 00:52:14 +04:00
s = talloc_get_type ( c - > private_data , struct domain_open_lsa_state ) ;
io - > out . domain_handle = s - > handle ;
ctx - > lsa . handle = s - > handle ;
2006-08-31 00:48:06 +04:00
ctx - > lsa . name = talloc_steal ( ctx , s - > name ) ;
2006-08-22 00:52:14 +04:00
ctx - > lsa . access_mask = s - > access_mask ;
2006-08-31 00:48:06 +04:00
io - > out . error_string = talloc_strdup ( mem_ctx , " Success " ) ;
2006-08-22 00:52:14 +04:00
} else if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-08-31 00:48:06 +04:00
/* there was an error, so provide nt status code description */
2006-08-22 00:52:14 +04:00
io - > out . error_string = talloc_asprintf ( mem_ctx ,
" Failed to open domain: %s " ,
nt_errstr ( status ) ) ;
2005-06-06 12:59:19 +04:00
}
talloc_free ( c ) ;
return status ;
}
2006-08-31 00:48:06 +04:00
/**
* Sends a request to open a domain in desired service
*
* @ param ctx initalised libnet context
* @ param io arguments and results of the call
* @ param monitor pointer to monitor function that is passed monitor message
*/
2006-08-22 00:52:14 +04:00
struct composite_context * libnet_DomainOpen_send ( struct libnet_context * ctx ,
struct libnet_DomainOpen * io ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
switch ( io - > in . type ) {
case DOMAIN_LSA :
2006-08-31 00:48:06 +04:00
/* reques to open a policy handle on \pipe\lsarpc */
2006-08-22 00:52:14 +04:00
c = libnet_DomainOpenLsa_send ( ctx , io , monitor ) ;
break ;
case DOMAIN_SAMR :
default :
2006-08-31 00:48:06 +04:00
/* request to open a domain policy handle on \pipe\samr */
2006-08-22 00:52:14 +04:00
c = libnet_DomainOpenSamr_send ( ctx , io , monitor ) ;
break ;
}
return c ;
}
2006-08-31 00:48:06 +04:00
/**
* Receive result of domain open request
*
* @ param c composite context returned by DomainOpen_send function
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of the call
* @ param io results and arguments of the call
*/
2006-08-22 00:52:14 +04:00
NTSTATUS libnet_DomainOpen_recv ( struct composite_context * c , struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx , struct libnet_DomainOpen * io )
{
NTSTATUS status ;
switch ( io - > in . type ) {
case DOMAIN_LSA :
status = libnet_DomainOpenLsa_recv ( c , ctx , mem_ctx , io ) ;
break ;
case DOMAIN_SAMR :
default :
status = libnet_DomainOpenSamr_recv ( c , ctx , mem_ctx , io ) ;
break ;
}
return status ;
}
2005-06-15 02:08:00 +04:00
/**
2006-06-28 02:16:36 +04:00
* Synchronous version of DomainOpen call
2005-06-15 02:08:00 +04:00
*
2006-05-16 01:49:27 +04:00
* @ param ctx initialised libnet context
2005-06-15 02:08:00 +04:00
* @ param mem_ctx memory context for the call
* @ param io arguments and results of the call
* @ return nt status code of execution
*/
2006-05-16 01:49:27 +04:00
NTSTATUS libnet_DomainOpen ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_DomainOpen * io )
2005-06-06 12:59:19 +04:00
{
2006-05-16 01:49:27 +04:00
struct composite_context * c = libnet_DomainOpen_send ( ctx , io , NULL ) ;
return libnet_DomainOpen_recv ( c , ctx , mem_ctx , io ) ;
2005-06-06 12:59:19 +04:00
}
2006-08-22 00:52:14 +04:00
struct domain_close_lsa_state {
struct dcerpc_pipe * pipe ;
struct lsa_Close close ;
struct policy_handle handle ;
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_lsa_close ( struct rpc_request * req ) ;
struct composite_context * libnet_DomainCloseLsa_send ( struct libnet_context * ctx ,
struct libnet_DomainClose * io ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct domain_close_lsa_state * s ;
struct rpc_request * close_req ;
2006-08-31 00:48:06 +04:00
/* composite context and state structure allocation */
2006-08-22 00:52:14 +04:00
c = composite_create ( ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return c ;
s = talloc_zero ( c , struct domain_close_lsa_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
s - > monitor_fn = monitor ;
/* TODO: check if lsa pipe pointer is non-null */
if ( ! strequal ( ctx - > lsa . name , io - > in . domain_name ) ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER ) ;
return c ;
}
2006-08-31 00:48:06 +04:00
/* get opened lsarpc pipe pointer */
2006-08-22 00:52:14 +04:00
s - > pipe = ctx - > lsa . pipe ;
2006-08-31 00:48:06 +04:00
/* prepare close handle call arguments */
2006-08-22 00:52:14 +04:00
s - > close . in . handle = & ctx - > lsa . handle ;
s - > close . out . handle = & s - > handle ;
2006-08-31 00:48:06 +04:00
/* send the request */
2006-08-22 00:52:14 +04:00
close_req = dcerpc_lsa_Close_send ( s - > pipe , c , & s - > close ) ;
if ( composite_nomem ( close_req , c ) ) return c ;
composite_continue_rpc ( c , close_req , continue_lsa_close , c ) ;
return c ;
}
2006-08-31 00:48:06 +04:00
/*
Stage 1 : Receive result of lsa close call
*/
2006-08-22 00:52:14 +04:00
static void continue_lsa_close ( struct rpc_request * req )
{
struct composite_context * c ;
struct domain_close_lsa_state * s ;
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2006-08-22 00:52:14 +04:00
s = talloc_get_type ( c - > private_data , struct domain_close_lsa_state ) ;
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-07-26 03:17:02 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
msg . type = mon_LsaClose ;
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2006-08-22 00:52:14 +04:00
composite_done ( c ) ;
}
NTSTATUS libnet_DomainCloseLsa_recv ( struct composite_context * c , struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx , struct libnet_DomainClose * io )
{
NTSTATUS status ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & io ) {
2006-08-31 00:48:06 +04:00
/* policy handle closed successfully */
2006-08-22 00:52:14 +04:00
ctx - > lsa . name = NULL ;
ZERO_STRUCT ( ctx - > lsa . handle ) ;
2006-08-28 00:37:23 +04:00
2006-08-22 00:52:14 +04:00
io - > out . error_string = talloc_asprintf ( mem_ctx , " Success " ) ;
} else if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-08-31 00:48:06 +04:00
/* there was an error, so return description of the status code */
2006-08-22 00:52:14 +04:00
io - > out . error_string = talloc_asprintf ( mem_ctx , " Error: %s " , nt_errstr ( status ) ) ;
}
talloc_free ( c ) ;
return status ;
}
struct domain_close_samr_state {
struct samr_Close close ;
2006-09-05 22:45:03 +04:00
struct policy_handle handle ;
2006-08-22 00:52:14 +04:00
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_samr_close ( struct rpc_request * req ) ;
struct composite_context * libnet_DomainCloseSamr_send ( struct libnet_context * ctx ,
struct libnet_DomainClose * io ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct domain_close_samr_state * s ;
struct rpc_request * close_req ;
2006-08-31 00:48:06 +04:00
/* composite context and state structure allocation */
2006-08-22 00:52:14 +04:00
c = composite_create ( ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return c ;
s = talloc_zero ( c , struct domain_close_samr_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
s - > monitor_fn = monitor ;
/* TODO: check if samr pipe pointer is non-null */
if ( ! strequal ( ctx - > samr . name , io - > in . domain_name ) ) {
composite_error ( c , NT_STATUS_INVALID_PARAMETER ) ;
return c ;
}
2006-08-31 00:48:06 +04:00
/* prepare close domain handle call arguments */
2006-09-05 22:45:03 +04:00
ZERO_STRUCT ( s - > close ) ;
s - > close . in . handle = & ctx - > samr . handle ;
s - > close . out . handle = & s - > handle ;
2006-08-22 00:52:14 +04:00
2006-08-31 00:48:06 +04:00
/* send the request */
2006-08-22 00:52:14 +04:00
close_req = dcerpc_samr_Close_send ( ctx - > samr . pipe , ctx , & s - > close ) ;
if ( composite_nomem ( close_req , c ) ) return c ;
composite_continue_rpc ( c , close_req , continue_samr_close , c ) ;
return c ;
}
2006-08-31 00:48:06 +04:00
/*
Stage 1 : Receive result of samr close call
*/
2006-08-22 00:52:14 +04:00
static void continue_samr_close ( struct rpc_request * req )
{
struct composite_context * c ;
struct domain_close_samr_state * s ;
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2006-08-22 00:52:14 +04:00
s = talloc_get_type ( c - > private_data , struct domain_close_samr_state ) ;
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-07-26 03:17:02 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
msg . type = mon_SamrClose ;
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2006-08-22 00:52:14 +04:00
composite_done ( c ) ;
}
NTSTATUS libnet_DomainCloseSamr_recv ( struct composite_context * c , struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx , struct libnet_DomainClose * io )
{
NTSTATUS status ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & io ) {
2006-08-31 00:48:06 +04:00
/* domain policy handle closed successfully */
2006-08-22 00:52:14 +04:00
ZERO_STRUCT ( ctx - > samr . handle ) ;
2007-08-02 17:08:39 +04:00
talloc_free ( ctx - > samr . name ) ;
talloc_free ( ctx - > samr . sid ) ;
2006-08-22 00:52:14 +04:00
ctx - > samr . name = NULL ;
2007-08-02 17:08:39 +04:00
ctx - > samr . sid = NULL ;
2006-08-31 00:48:06 +04:00
2006-08-22 00:52:14 +04:00
io - > out . error_string = talloc_asprintf ( mem_ctx , " Success " ) ;
} else if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-08-31 00:48:06 +04:00
/* there was an error, so return description of the status code */
2006-08-22 00:52:14 +04:00
io - > out . error_string = talloc_asprintf ( mem_ctx , " Error: %s " , nt_errstr ( status ) ) ;
}
talloc_free ( c ) ;
return status ;
}
struct composite_context * libnet_DomainClose_send ( struct libnet_context * ctx ,
struct libnet_DomainClose * io ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
switch ( io - > in . type ) {
case DOMAIN_LSA :
2006-08-31 00:48:06 +04:00
/* request to close policy handle on \pipe\lsarpc */
2006-08-22 00:52:14 +04:00
c = libnet_DomainCloseLsa_send ( ctx , io , monitor ) ;
break ;
case DOMAIN_SAMR :
default :
2006-08-31 00:48:06 +04:00
/* request to close domain policy handle on \pipe\samr */
2006-08-22 00:52:14 +04:00
c = libnet_DomainCloseSamr_send ( ctx , io , monitor ) ;
break ;
}
return c ;
}
NTSTATUS libnet_DomainClose_recv ( struct composite_context * c , struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx , struct libnet_DomainClose * io )
{
NTSTATUS status ;
switch ( io - > in . type ) {
case DOMAIN_LSA :
2006-08-31 00:48:06 +04:00
/* receive result of closing lsa policy handle */
2006-08-22 00:52:14 +04:00
status = libnet_DomainCloseLsa_recv ( c , ctx , mem_ctx , io ) ;
break ;
case DOMAIN_SAMR :
default :
2006-08-31 00:48:06 +04:00
/* receive result of closing samr domain policy handle */
2006-08-22 00:52:14 +04:00
status = libnet_DomainCloseSamr_recv ( c , ctx , mem_ctx , io ) ;
break ;
}
return status ;
}
NTSTATUS libnet_DomainClose ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_DomainClose * io )
{
struct composite_context * c ;
c = libnet_DomainClose_send ( ctx , io , NULL ) ;
return libnet_DomainClose_recv ( c , ctx , mem_ctx , io ) ;
}
2007-04-29 16:31:09 +04:00
struct domain_list_state {
struct libnet_context * ctx ;
struct libnet_RpcConnect rpcconn ;
struct samr_Connect samrconn ;
struct samr_EnumDomains enumdom ;
2007-05-07 09:42:26 +04:00
struct samr_Close samrclose ;
2007-04-29 16:31:09 +04:00
const char * hostname ;
struct policy_handle connect_handle ;
int buf_size ;
struct domainlist * domains ;
uint32_t resume_handle ;
uint32_t count ;
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_rpc_connect ( struct composite_context * c ) ;
static void continue_samr_connect ( struct rpc_request * c ) ;
static void continue_samr_enum_domains ( struct rpc_request * req ) ;
2007-05-07 09:42:26 +04:00
static void continue_samr_close_handle ( struct rpc_request * req ) ;
2007-04-29 16:31:09 +04:00
static struct domainlist * get_domain_list ( TALLOC_CTX * mem_ctx , struct domain_list_state * s ) ;
/*
Stage 1 : Receive connected rpc pipe and send connection
request to SAMR service
*/
static void continue_rpc_connect ( struct composite_context * ctx )
{
struct composite_context * c ;
struct domain_list_state * s ;
struct rpc_request * samrconn_req ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct domain_list_state ) ;
c - > status = libnet_RpcConnect_recv ( ctx , s - > ctx , c , & s - > rpcconn ) ;
if ( ! composite_is_ok ( c ) ) return ;
s - > samrconn . in . system_name = 0 ;
s - > samrconn . in . access_mask = SEC_GENERIC_READ ; /* should be enough */
s - > samrconn . out . connect_handle = & s - > connect_handle ;
samrconn_req = dcerpc_samr_Connect_send ( s - > ctx - > samr . pipe , c , & s - > samrconn ) ;
if ( composite_nomem ( samrconn_req , c ) ) return ;
composite_continue_rpc ( c , samrconn_req , continue_samr_connect , c ) ;
}
/*
Stage 2 : Receive policy handle to the connected SAMR service and issue
a request to enumerate domain databases available
*/
static void continue_samr_connect ( struct rpc_request * req )
{
struct composite_context * c ;
struct domain_list_state * s ;
struct rpc_request * enumdom_req ;
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2007-04-29 16:31:09 +04:00
s = talloc_get_type ( c - > private_data , struct domain_list_state ) ;
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-07-26 03:17:02 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
msg . type = mon_SamrConnect ;
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2007-04-29 16:31:09 +04:00
s - > enumdom . in . connect_handle = & s - > connect_handle ;
s - > enumdom . in . resume_handle = & s - > resume_handle ;
s - > enumdom . in . buf_size = s - > buf_size ;
s - > enumdom . out . resume_handle = & s - > resume_handle ;
enumdom_req = dcerpc_samr_EnumDomains_send ( s - > ctx - > samr . pipe , c , & s - > enumdom ) ;
if ( composite_nomem ( enumdom_req , c ) ) return ;
composite_continue_rpc ( c , enumdom_req , continue_samr_enum_domains , c ) ;
}
/*
Stage 3 : Receive domain names available and repeat the request
2007-05-07 09:42:26 +04:00
enumeration is not complete yet . Close samr connection handle
upon completion .
2007-04-29 16:31:09 +04:00
*/
static void continue_samr_enum_domains ( struct rpc_request * req )
{
struct composite_context * c ;
struct domain_list_state * s ;
struct rpc_request * enumdom_req ;
2007-05-07 09:42:26 +04:00
struct rpc_request * samrclose_req ;
2007-04-29 16:31:09 +04:00
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2007-04-29 16:31:09 +04:00
s = talloc_get_type ( c - > private_data , struct domain_list_state ) ;
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-07-26 03:17:02 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
msg . type = mon_SamrEnumDomains ;
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2007-04-29 16:31:09 +04:00
if ( NT_STATUS_IS_OK ( s - > enumdom . out . result ) ) {
s - > domains = get_domain_list ( c , s ) ;
} else if ( NT_STATUS_EQUAL ( s - > enumdom . out . result , STATUS_MORE_ENTRIES ) ) {
s - > domains = get_domain_list ( c , s ) ;
2007-05-07 09:42:26 +04:00
/* prepare next round of enumeration */
2007-04-29 16:31:09 +04:00
s - > enumdom . in . connect_handle = & s - > connect_handle ;
s - > enumdom . in . resume_handle = & s - > resume_handle ;
2007-05-12 01:45:03 +04:00
s - > enumdom . in . buf_size = s - > ctx - > samr . buf_size ;
2007-04-29 16:31:09 +04:00
s - > enumdom . out . resume_handle = & s - > resume_handle ;
2007-05-07 09:42:26 +04:00
/* send the request */
2007-04-29 16:31:09 +04:00
enumdom_req = dcerpc_samr_EnumDomains_send ( s - > ctx - > samr . pipe , c , & s - > enumdom ) ;
if ( composite_nomem ( enumdom_req , c ) ) return ;
composite_continue_rpc ( c , enumdom_req , continue_samr_enum_domains , c ) ;
} else {
composite_error ( c , s - > enumdom . out . result ) ;
2007-05-07 09:42:26 +04:00
return ;
}
/* close samr connection handle */
s - > samrclose . in . handle = & s - > connect_handle ;
s - > samrclose . out . handle = & s - > connect_handle ;
/* send the request */
samrclose_req = dcerpc_samr_Close_send ( s - > ctx - > samr . pipe , c , & s - > samrclose ) ;
if ( composite_nomem ( samrclose_req , c ) ) return ;
composite_continue_rpc ( c , samrclose_req , continue_samr_close_handle , c ) ;
}
/*
Stage 4 : Receive result of closing samr connection handle .
*/
static void continue_samr_close_handle ( struct rpc_request * req )
{
struct composite_context * c ;
struct domain_list_state * s ;
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2007-05-07 09:42:26 +04:00
s = talloc_get_type ( c - > private_data , struct domain_list_state ) ;
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-07-26 03:17:02 +04:00
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
msg . type = mon_SamrClose ;
msg . data = NULL ;
msg . data_size = 0 ;
s - > monitor_fn ( & msg ) ;
}
2007-05-07 09:42:26 +04:00
/* did everything go fine ? */
if ( ! NT_STATUS_IS_OK ( s - > samrclose . out . result ) ) {
composite_error ( c , s - > samrclose . out . result ) ;
2007-04-29 16:31:09 +04:00
}
2007-05-07 09:42:26 +04:00
composite_done ( c ) ;
2007-04-29 16:31:09 +04:00
}
/*
Utility function to copy domain names from result of samr_EnumDomains call
*/
static struct domainlist * get_domain_list ( TALLOC_CTX * mem_ctx , struct domain_list_state * s )
{
int i ;
if ( mem_ctx = = NULL | | s = = NULL ) return NULL ;
2007-05-07 09:55:40 +04:00
/* prepare domains array */
2007-05-07 09:42:26 +04:00
if ( s - > domains = = NULL ) {
s - > domains = talloc_array ( mem_ctx , struct domainlist ,
s - > enumdom . out . num_entries ) ;
} else {
s - > domains = talloc_realloc ( mem_ctx , s - > domains , struct domainlist ,
s - > count + s - > enumdom . out . num_entries ) ;
}
2007-05-07 09:55:40 +04:00
/* copy domain names returned from samr_EnumDomains call */
2007-05-07 09:42:26 +04:00
for ( i = s - > count ; i < s - > count + s - > enumdom . out . num_entries ; i + + )
2007-04-29 16:31:09 +04:00
{
2007-05-07 09:42:26 +04:00
struct lsa_String * domain_name = & s - > enumdom . out . sam - > entries [ i - s - > count ] . name ;
2007-04-29 16:31:09 +04:00
/* strdup name as a child of allocated array to make it follow the array
in case of talloc_steal or talloc_free */
2007-05-07 09:42:26 +04:00
s - > domains [ i ] . name = talloc_strdup ( s - > domains , domain_name - > string ) ;
2007-04-29 16:31:09 +04:00
s - > domains [ i ] . sid = NULL ; /* this is to be filled out later */
}
2007-05-07 09:42:26 +04:00
/* number of entries returned (domains enumerated) */
s - > count + = s - > enumdom . out . num_entries ;
2007-04-29 16:31:09 +04:00
return s - > domains ;
}
/**
* Sends a request to list domains on given host
*
* @ param ctx initalised libnet context
* @ param mem_ctx memory context
* @ param io arguments and results of the call
* @ param monitor pointer to monitor function that is passed monitor messages
*/
struct composite_context * libnet_DomainList_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_DomainList * io ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct domain_list_state * s ;
struct composite_context * rpcconn_req ;
2007-05-07 09:42:26 +04:00
struct rpc_request * samrconn_req ;
2007-04-29 16:31:09 +04:00
/* composite context and state structure allocation */
c = composite_create ( ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return c ;
s = talloc_zero ( c , struct domain_list_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
s - > monitor_fn = monitor ;
s - > ctx = ctx ;
s - > hostname = talloc_strdup ( c , io - > in . hostname ) ;
if ( composite_nomem ( s - > hostname , c ) ) return c ;
2007-05-07 09:42:26 +04:00
/* check whether samr pipe has already been opened */
if ( ctx - > samr . pipe = = NULL ) {
/* prepare rpc connect call */
s - > rpcconn . level = LIBNET_RPC_CONNECT_SERVER ;
s - > rpcconn . in . name = s - > hostname ;
s - > rpcconn . in . dcerpc_iface = & dcerpc_table_samr ;
2007-07-19 01:24:37 +04:00
rpcconn_req = libnet_RpcConnect_send ( ctx , c , & s - > rpcconn , s - > monitor_fn ) ;
2007-05-07 09:42:26 +04:00
if ( composite_nomem ( rpcconn_req , c ) ) return c ;
composite_continue ( c , rpcconn_req , continue_rpc_connect , c ) ;
2007-04-29 16:31:09 +04:00
2007-05-07 09:42:26 +04:00
} else {
/* prepare samr_Connect call */
s - > samrconn . in . system_name = 0 ;
s - > samrconn . in . access_mask = SEC_GENERIC_READ ;
s - > samrconn . out . connect_handle = & s - > connect_handle ;
samrconn_req = dcerpc_samr_Connect_send ( s - > ctx - > samr . pipe , c , & s - > samrconn ) ;
if ( composite_nomem ( samrconn_req , c ) ) return c ;
composite_continue_rpc ( c , samrconn_req , continue_samr_connect , c ) ;
}
2007-04-29 16:31:09 +04:00
return c ;
}
/**
* Receive result of domain list request
*
* @ param c composite context returned by DomainList_send function
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of the call
* @ param io results and arguments of the call
*/
NTSTATUS libnet_DomainList_recv ( struct composite_context * c , struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx , struct libnet_DomainList * io )
{
NTSTATUS status ;
struct domain_list_state * s ;
status = composite_wait ( c ) ;
s = talloc_get_type ( c - > private_data , struct domain_list_state ) ;
if ( NT_STATUS_IS_OK ( status ) & & ctx & & mem_ctx & & io ) {
/* fetch the results to be returned by io structure */
io - > out . count = s - > count ;
io - > out . domains = talloc_steal ( mem_ctx , s - > domains ) ;
io - > out . error_string = talloc_asprintf ( mem_ctx , " Success " ) ;
} else if ( ! NT_STATUS_IS_OK ( status ) ) {
/* there was an error, so return description of the status code */
io - > out . error_string = talloc_asprintf ( mem_ctx , " Error: %s " , nt_errstr ( status ) ) ;
}
talloc_free ( c ) ;
return status ;
}
/**
* Synchronous version of DomainList call
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context for the call
* @ param io arguments and results of the call
* @ return nt status code of execution
*/
NTSTATUS libnet_DomainList ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_DomainList * io )
{
struct composite_context * c ;
c = libnet_DomainList_send ( ctx , mem_ctx , io , NULL ) ;
return libnet_DomainList_recv ( c , ctx , mem_ctx , io ) ;
}