2007-08-27 00:25:39 +04:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Rafal Szczesniak 2007
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 "libnet/libnet.h"
# include "libcli/composite/composite.h"
# include "librpc/gen_ndr/lsa.h"
2007-12-18 02:59:21 +03:00
# include "librpc/gen_ndr/ndr_lsa_c.h"
# include "librpc/gen_ndr/samr.h"
# include "librpc/gen_ndr/ndr_samr_c.h"
# include "libcli/security/security.h"
2007-08-27 00:25:39 +04:00
2007-12-31 04:13:50 +03:00
struct create_group_state {
struct libnet_context * ctx ;
struct libnet_CreateGroup r ;
struct libnet_DomainOpen domain_open ;
struct libnet_rpc_groupadd group_add ;
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_domain_opened ( struct composite_context * ctx ) ;
static void continue_rpc_group_added ( struct composite_context * ctx ) ;
struct composite_context * libnet_CreateGroup_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_CreateGroup * r ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct create_group_state * s ;
struct composite_context * create_req ;
bool prereq_met = false ;
/* composite context allocation and setup */
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct create_group_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
s - > ctx = ctx ;
s - > r = * r ;
ZERO_STRUCT ( s - > r . out ) ;
/* prerequisite: make sure we have a valid samr domain handle */
prereq_met = samr_domain_opened ( ctx , s - > r . in . domain_name , & c , & s - > domain_open ,
continue_domain_opened , monitor ) ;
if ( ! prereq_met ) return c ;
/* prepare arguments of rpc group add call */
s - > group_add . in . groupname = r - > in . group_name ;
s - > group_add . in . domain_handle = ctx - > samr . handle ;
/* send the request */
create_req = libnet_rpc_groupadd_send ( ctx - > samr . pipe , & s - > group_add , monitor ) ;
if ( composite_nomem ( create_req , c ) ) return c ;
composite_continue ( c , create_req , continue_rpc_group_added , c ) ;
return c ;
}
static void continue_domain_opened ( struct composite_context * ctx )
{
struct composite_context * c ;
struct create_group_state * s ;
struct composite_context * create_req ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct create_group_state ) ;
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domain_open ) ;
if ( ! composite_is_ok ( c ) ) return ;
/* prepare arguments of groupadd call */
s - > group_add . in . groupname = s - > r . in . group_name ;
s - > group_add . in . domain_handle = s - > ctx - > samr . handle ;
/* send the request */
create_req = libnet_rpc_groupadd_send ( s - > ctx - > samr . pipe , & s - > group_add ,
s - > monitor_fn ) ;
if ( composite_nomem ( create_req , c ) ) return ;
composite_continue ( c , create_req , continue_rpc_group_added , c ) ;
}
static void continue_rpc_group_added ( struct composite_context * ctx )
{
struct composite_context * c ;
struct create_group_state * s ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct create_group_state ) ;
/* receive result of group add call */
c - > status = libnet_rpc_groupadd_recv ( ctx , c , & s - > group_add ) ;
if ( ! composite_is_ok ( c ) ) return ;
/* we're done */
composite_done ( c ) ;
}
/**
* Receive result of CreateGroup call
*
* @ param c composite context returned by send request routine
* @ param mem_ctx memory context of this call
* @ param r pointer to a structure containing arguments and result of this call
* @ return nt status
*/
NTSTATUS libnet_CreateGroup_recv ( struct composite_context * c ,
TALLOC_CTX * mem_ctx ,
struct libnet_CreateGroup * r )
{
NTSTATUS status ;
struct create_group_state * s ;
status = composite_wait ( c ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
s = talloc_get_type ( c - > private_data , struct create_group_state ) ;
r - > out . error_string = talloc_strdup ( mem_ctx , nt_errstr ( status ) ) ;
}
return status ;
}
/**
* Create domain group
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param io pointer to structure containing arguments and result of this call
* @ return nt status
*/
NTSTATUS libnet_CreateGroup ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_CreateGroup * io )
{
struct composite_context * c ;
c = libnet_CreateGroup_send ( ctx , mem_ctx , io , NULL ) ;
return libnet_CreateGroup_recv ( c , mem_ctx , io ) ;
}
2007-08-27 00:25:39 +04:00
struct group_info_state {
struct libnet_context * ctx ;
const char * domain_name ;
2008-12-26 13:32:09 +03:00
enum libnet_GroupInfo_level level ;
2007-08-27 00:25:39 +04:00
const char * group_name ;
2008-12-26 13:32:09 +03:00
const char * sid_string ;
2007-08-27 00:25:39 +04:00
struct libnet_LookupName lookup ;
struct libnet_DomainOpen domopen ;
struct libnet_rpc_groupinfo info ;
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_domain_open_info ( struct composite_context * ctx ) ;
static void continue_name_found ( struct composite_context * ctx ) ;
2007-08-27 01:47:16 +04:00
static void continue_group_info ( struct composite_context * ctx ) ;
2007-08-27 00:25:39 +04:00
2007-08-28 13:57:47 +04:00
/**
* Sends request to get group information
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param io pointer to structure containing arguments the call
* @ param monitor function pointer for receiving monitor messages
* @ return composite context of this request
*/
2007-08-27 00:25:39 +04:00
struct composite_context * libnet_GroupInfo_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_GroupInfo * io ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct group_info_state * s ;
2007-10-07 02:28:14 +04:00
bool prereq_met = false ;
2008-12-26 13:32:09 +03:00
struct composite_context * lookup_req , * info_req ;
2007-08-27 00:25:39 +04:00
/* composite context allocation and setup */
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct group_info_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2007-08-28 13:57:47 +04:00
/* store arguments in the state structure */
2007-08-27 00:25:39 +04:00
s - > monitor_fn = monitor ;
2008-12-26 13:32:09 +03:00
s - > ctx = ctx ;
2007-08-27 00:25:39 +04:00
s - > domain_name = talloc_strdup ( c , io - > in . domain_name ) ;
2008-12-26 13:32:09 +03:00
s - > level = io - > in . level ;
switch ( s - > level ) {
case GROUP_INFO_BY_NAME :
s - > group_name = talloc_strdup ( c , io - > in . data . group_name ) ;
s - > sid_string = NULL ;
break ;
case GROUP_INFO_BY_SID :
s - > group_name = NULL ;
s - > sid_string = dom_sid_string ( c , io - > in . data . group_sid ) ;
break ;
}
2007-08-27 00:25:39 +04:00
/* prerequisite: make sure the domain is opened */
prereq_met = samr_domain_opened ( ctx , s - > domain_name , & c , & s - > domopen ,
continue_domain_open_info , monitor ) ;
if ( ! prereq_met ) return c ;
2008-12-26 13:32:09 +03:00
switch ( s - > level ) {
case GROUP_INFO_BY_NAME :
/* prepare arguments for LookupName call */
s - > lookup . in . name = s - > group_name ;
s - > lookup . in . domain_name = s - > domain_name ;
/* send the request */
lookup_req = libnet_LookupName_send ( s - > ctx , c , & s - > lookup , s - > monitor_fn ) ;
if ( composite_nomem ( lookup_req , c ) ) return c ;
/* set the next stage */
composite_continue ( c , lookup_req , continue_name_found , c ) ;
break ;
case GROUP_INFO_BY_SID :
/* prepare arguments for groupinfo call */
s - > info . in . domain_handle = s - > ctx - > samr . handle ;
s - > info . in . sid = s - > sid_string ;
/* we're looking for all information available */
s - > info . in . level = GROUPINFOALL ;
/* send the request */
info_req = libnet_rpc_groupinfo_send ( s - > ctx - > samr . pipe , & s - > info , s - > monitor_fn ) ;
if ( composite_nomem ( info_req , c ) ) return c ;
/* set the next stage */
composite_continue ( c , info_req , continue_group_info , c ) ;
break ;
}
2007-08-27 00:25:39 +04:00
return c ;
}
2007-08-28 13:57:47 +04:00
/*
* Stage 0.5 ( optional ) : receive opened domain and send lookup name request
*/
2007-08-27 00:25:39 +04:00
static void continue_domain_open_info ( struct composite_context * ctx )
{
struct composite_context * c ;
struct group_info_state * s ;
2008-12-26 13:32:09 +03:00
struct composite_context * lookup_req , * info_req ;
2007-08-27 00:25:39 +04:00
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct group_info_state ) ;
2007-08-28 13:57:47 +04:00
/* receive domain handle */
2007-08-27 00:25:39 +04:00
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domopen ) ;
if ( ! composite_is_ok ( c ) ) return ;
2008-12-26 13:32:09 +03:00
switch ( s - > level ) {
case GROUP_INFO_BY_NAME :
/* prepare arguments for LookupName call */
s - > lookup . in . name = s - > group_name ;
s - > lookup . in . domain_name = s - > domain_name ;
/* send the request */
lookup_req = libnet_LookupName_send ( s - > ctx , c , & s - > lookup , s - > monitor_fn ) ;
if ( composite_nomem ( lookup_req , c ) ) return ;
/* set the next stage */
composite_continue ( c , lookup_req , continue_name_found , c ) ;
break ;
case GROUP_INFO_BY_SID :
/* prepare arguments for groupinfo call */
s - > info . in . domain_handle = s - > ctx - > samr . handle ;
s - > info . in . sid = s - > sid_string ;
/* we're looking for all information available */
s - > info . in . level = GROUPINFOALL ;
/* send the request */
info_req = libnet_rpc_groupinfo_send ( s - > ctx - > samr . pipe , & s - > info , s - > monitor_fn ) ;
if ( composite_nomem ( info_req , c ) ) return ;
/* set the next stage */
composite_continue ( c , info_req , continue_group_info , c ) ;
break ;
2007-08-28 13:57:47 +04:00
2008-12-26 13:32:09 +03:00
}
2007-08-27 00:25:39 +04:00
}
2007-08-28 13:57:47 +04:00
/*
* Stage 1 : Receive SID found and send request for group info
*/
2007-08-27 00:25:39 +04:00
static void continue_name_found ( struct composite_context * ctx )
{
struct composite_context * c ;
struct group_info_state * s ;
struct composite_context * info_req ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct group_info_state ) ;
2007-08-28 13:57:47 +04:00
/* receive SID assiociated with name found */
2007-08-27 00:25:39 +04:00
c - > status = libnet_LookupName_recv ( ctx , c , & s - > lookup ) ;
if ( ! composite_is_ok ( c ) ) return ;
2008-12-26 13:32:09 +03:00
2007-08-28 13:57:47 +04:00
/* Is is a group SID actually ? */
2007-08-27 01:47:16 +04:00
if ( s - > lookup . out . sid_type ! = SID_NAME_DOM_GRP & &
2007-08-27 00:25:39 +04:00
s - > lookup . out . sid_type ! = SID_NAME_ALIAS ) {
composite_error ( c , NT_STATUS_NO_SUCH_GROUP ) ;
}
2007-08-28 13:57:47 +04:00
/* prepare arguments for groupinfo call */
2007-08-27 00:25:39 +04:00
s - > info . in . domain_handle = s - > ctx - > samr . handle ;
s - > info . in . groupname = s - > group_name ;
s - > info . in . sid = s - > lookup . out . sidstr ;
2007-08-28 13:57:47 +04:00
/* we're looking for all information available */
2007-08-27 00:25:39 +04:00
s - > info . in . level = GROUPINFOALL ;
2007-08-28 13:57:47 +04:00
/* send the request */
2007-08-27 00:25:39 +04:00
info_req = libnet_rpc_groupinfo_send ( s - > ctx - > samr . pipe , & s - > info , s - > monitor_fn ) ;
if ( composite_nomem ( info_req , c ) ) return ;
2007-08-28 13:57:47 +04:00
/* set the next stage */
2007-08-27 01:47:16 +04:00
composite_continue ( c , info_req , continue_group_info , c ) ;
2007-08-27 00:25:39 +04:00
}
2007-08-28 13:57:47 +04:00
/*
* Stage 2 : Receive group information
*/
2007-08-27 01:47:16 +04:00
static void continue_group_info ( struct composite_context * ctx )
2007-08-27 00:25:39 +04:00
{
struct composite_context * c ;
struct group_info_state * s ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct group_info_state ) ;
2007-08-28 13:57:47 +04:00
/* receive group information */
2007-08-27 00:25:39 +04:00
c - > status = libnet_rpc_groupinfo_recv ( ctx , c , & s - > info ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-08-28 13:57:47 +04:00
/* we're done */
2007-08-27 00:25:39 +04:00
composite_done ( c ) ;
}
2007-08-28 13:57:47 +04:00
/*
* Receive group information
*
* @ param c composite context returned by libnet_GroupInfo_send
* @ param mem_ctx memory context of this call
2007-12-31 04:13:50 +03:00
* @ param io pointer to structure receiving results of the call
2007-08-28 13:57:47 +04:00
* @ result nt status
*/
2007-08-27 00:25:39 +04:00
NTSTATUS libnet_GroupInfo_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct libnet_GroupInfo * io )
{
NTSTATUS status ;
struct group_info_state * s ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
2007-08-28 13:57:47 +04:00
/* put the results into io structure if everything went fine */
2007-08-27 00:25:39 +04:00
s = talloc_get_type ( c - > private_data , struct group_info_state ) ;
2008-12-26 12:17:38 +03:00
io - > out . group_name = talloc_steal ( mem_ctx ,
s - > info . out . info . all . name . string ) ;
2007-08-27 00:25:39 +04:00
io - > out . group_sid = talloc_steal ( mem_ctx , s - > lookup . out . sid ) ;
io - > out . num_members = s - > info . out . info . all . num_members ;
io - > out . description = talloc_steal ( mem_ctx , s - > info . out . info . all . description . string ) ;
io - > out . error_string = talloc_strdup ( mem_ctx , " Success " ) ;
2007-08-28 13:57:47 +04:00
} else {
io - > out . error_string = talloc_asprintf ( mem_ctx , " Error: %s " , nt_errstr ( status ) ) ;
2007-08-27 00:25:39 +04:00
}
2007-08-28 13:57:47 +04:00
talloc_free ( c ) ;
2007-08-27 00:25:39 +04:00
return status ;
}
2007-08-28 13:57:47 +04:00
/**
* Obtains specified group information
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of the call
* @ param io pointer to a structure containing arguments and results of the call
*/
2007-08-27 00:25:39 +04:00
NTSTATUS libnet_GroupInfo ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_GroupInfo * io )
{
struct composite_context * c = libnet_GroupInfo_send ( ctx , mem_ctx ,
io , NULL ) ;
return libnet_GroupInfo_recv ( c , mem_ctx , io ) ;
}
2007-12-18 02:59:21 +03:00
struct grouplist_state {
struct libnet_context * ctx ;
const char * domain_name ;
struct lsa_DomainInfo dominfo ;
int page_size ;
uint32_t resume_index ;
struct grouplist * groups ;
uint32_t count ;
struct libnet_DomainOpen domain_open ;
struct lsa_QueryInfoPolicy query_domain ;
struct samr_EnumDomainGroups group_list ;
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_lsa_domain_opened ( struct composite_context * ctx ) ;
static void continue_domain_queried ( struct rpc_request * req ) ;
static void continue_samr_domain_opened ( struct composite_context * ctx ) ;
static void continue_domain_queried ( struct rpc_request * req ) ;
static void continue_groups_enumerated ( struct rpc_request * req ) ;
2007-12-31 04:13:50 +03:00
/**
* Sends request to list ( enumerate ) group accounts
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param io pointer to structure containing arguments and results of this call
* @ param monitor function pointer for receiving monitor messages
* @ return compostite context of this request
*/
2007-12-18 02:59:21 +03:00
struct composite_context * libnet_GroupList_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_GroupList * io ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct grouplist_state * s ;
struct rpc_request * query_req ;
bool prereq_met = false ;
2007-12-31 04:13:50 +03:00
/* composite context allocation and setup */
2007-12-18 02:59:21 +03:00
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct grouplist_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2007-12-31 04:13:50 +03:00
/* store the arguments in the state structure */
2007-12-18 02:59:21 +03:00
s - > ctx = ctx ;
s - > page_size = io - > in . page_size ;
s - > resume_index = ( uint32_t ) io - > in . resume_index ;
s - > domain_name = talloc_strdup ( c , io - > in . domain_name ) ;
s - > monitor_fn = monitor ;
2007-12-31 04:13:50 +03:00
/* make sure we have lsa domain handle before doing anything */
2007-12-18 02:59:21 +03:00
prereq_met = lsa_domain_opened ( ctx , s - > domain_name , & c , & s - > domain_open ,
continue_lsa_domain_opened , monitor ) ;
if ( ! prereq_met ) return c ;
2007-12-31 04:13:50 +03:00
/* prepare arguments of QueryDomainInfo call */
2007-12-18 02:59:21 +03:00
s - > query_domain . in . handle = & ctx - > lsa . handle ;
s - > query_domain . in . level = LSA_POLICY_INFO_DOMAIN ;
2008-10-24 17:05:57 +04:00
s - > query_domain . out . info = talloc_zero ( c , union lsa_PolicyInformation * ) ;
if ( composite_nomem ( s - > query_domain . out . info , c ) ) return c ;
2007-12-31 04:13:50 +03:00
/* send the request */
2007-12-18 02:59:21 +03:00
query_req = dcerpc_lsa_QueryInfoPolicy_send ( ctx - > lsa . pipe , c , & s - > query_domain ) ;
if ( composite_nomem ( query_req , c ) ) return c ;
composite_continue_rpc ( c , query_req , continue_domain_queried , c ) ;
return c ;
}
2007-12-31 04:13:50 +03:00
/*
* Stage 0.5 ( optional ) : receive lsa domain handle and send
* request to query domain info
*/
2007-12-18 02:59:21 +03:00
static void continue_lsa_domain_opened ( struct composite_context * ctx )
{
struct composite_context * c ;
struct grouplist_state * s ;
struct rpc_request * query_req ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct grouplist_state ) ;
2007-12-31 04:13:50 +03:00
/* receive lsa domain handle */
2007-12-18 02:59:21 +03:00
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domain_open ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-12-31 04:13:50 +03:00
/* prepare arguments of QueryDomainInfo call */
2007-12-18 02:59:21 +03:00
s - > query_domain . in . handle = & s - > ctx - > lsa . handle ;
s - > query_domain . in . level = LSA_POLICY_INFO_DOMAIN ;
2008-10-27 23:46:50 +03:00
s - > query_domain . out . info = talloc_zero ( c , union lsa_PolicyInformation * ) ;
if ( composite_nomem ( s - > query_domain . out . info , c ) ) return ;
2007-12-31 04:13:50 +03:00
/* send the request */
2007-12-18 02:59:21 +03:00
query_req = dcerpc_lsa_QueryInfoPolicy_send ( s - > ctx - > lsa . pipe , c , & s - > query_domain ) ;
if ( composite_nomem ( query_req , c ) ) return ;
composite_continue_rpc ( c , query_req , continue_domain_queried , c ) ;
}
2007-12-31 04:13:50 +03:00
/*
* Stage 1 : receive domain info and request to enum groups
* provided a valid samr handle is opened
*/
2007-12-18 02:59:21 +03:00
static void continue_domain_queried ( struct rpc_request * req )
{
struct composite_context * c ;
struct grouplist_state * s ;
struct rpc_request * enum_req ;
bool prereq_met = false ;
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct grouplist_state ) ;
/* receive result of rpc request */
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
/* get the returned domain info */
2008-10-24 17:05:57 +04:00
s - > dominfo = ( * s - > query_domain . out . info ) - > domain ;
2007-12-18 02:59:21 +03:00
/* make sure we have samr domain handle before continuing */
prereq_met = samr_domain_opened ( s - > ctx , s - > domain_name , & c , & s - > domain_open ,
continue_samr_domain_opened , s - > monitor_fn ) ;
if ( ! prereq_met ) return ;
/* prepare arguments od EnumDomainGroups call */
2007-12-31 04:13:50 +03:00
s - > group_list . in . domain_handle = & s - > ctx - > samr . handle ;
s - > group_list . in . max_size = s - > page_size ;
s - > group_list . in . resume_handle = & s - > resume_index ;
2007-12-18 02:59:21 +03:00
s - > group_list . out . resume_handle = & s - > resume_index ;
2008-11-07 16:51:21 +03:00
s - > group_list . out . num_entries = talloc ( s , uint32_t ) ;
if ( composite_nomem ( s - > group_list . out . num_entries , c ) ) return ;
s - > group_list . out . sam = talloc ( s , struct samr_SamArray * ) ;
if ( composite_nomem ( s - > group_list . out . sam , c ) ) return ;
2007-12-18 02:59:21 +03:00
/* send the request */
enum_req = dcerpc_samr_EnumDomainGroups_send ( s - > ctx - > samr . pipe , c , & s - > group_list ) ;
if ( composite_nomem ( enum_req , c ) ) return ;
composite_continue_rpc ( c , enum_req , continue_groups_enumerated , c ) ;
}
2007-12-31 04:13:50 +03:00
/*
* Stage 1.5 ( optional ) : receive samr domain handle
* and request to enumerate accounts
*/
2007-12-18 02:59:21 +03:00
static void continue_samr_domain_opened ( struct composite_context * ctx )
{
struct composite_context * c ;
struct grouplist_state * s ;
struct rpc_request * enum_req ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct grouplist_state ) ;
/* receive samr domain handle */
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domain_open ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-12-31 04:13:50 +03:00
/* prepare arguments of EnumDomainGroups call */
2007-12-18 02:59:21 +03:00
s - > group_list . in . domain_handle = & s - > ctx - > samr . handle ;
s - > group_list . in . max_size = s - > page_size ;
s - > group_list . in . resume_handle = & s - > resume_index ;
s - > group_list . out . resume_handle = & s - > resume_index ;
2008-11-07 16:51:21 +03:00
s - > group_list . out . num_entries = talloc ( s , uint32_t ) ;
if ( composite_nomem ( s - > group_list . out . num_entries , c ) ) return ;
s - > group_list . out . sam = talloc ( s , struct samr_SamArray * ) ;
if ( composite_nomem ( s - > group_list . out . sam , c ) ) return ;
2007-12-18 02:59:21 +03:00
2007-12-31 04:13:50 +03:00
/* send the request */
2007-12-18 02:59:21 +03:00
enum_req = dcerpc_samr_EnumDomainGroups_send ( s - > ctx - > samr . pipe , c , & s - > group_list ) ;
if ( composite_nomem ( enum_req , c ) ) return ;
composite_continue_rpc ( c , enum_req , continue_groups_enumerated , c ) ;
}
2007-12-31 04:13:50 +03:00
/*
* Stage 2 : receive enumerated groups and their rids
*/
2007-12-18 02:59:21 +03:00
static void continue_groups_enumerated ( struct rpc_request * req )
{
struct composite_context * c ;
struct grouplist_state * s ;
int i ;
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct grouplist_state ) ;
2007-12-31 04:13:50 +03:00
/* receive result of rpc request */
2007-12-18 02:59:21 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2007-12-31 04:13:50 +03:00
/* get the actual status of the rpc call result
( instead of rpc layer ) */
2007-12-18 02:59:21 +03:00
c - > status = s - > group_list . out . result ;
2007-12-31 04:13:50 +03:00
/* we're interested in status "ok" as well as two
enum - specific status codes */
2007-12-18 02:59:21 +03:00
if ( NT_STATUS_IS_OK ( c - > status ) | |
NT_STATUS_EQUAL ( c - > status , STATUS_MORE_ENTRIES ) | |
NT_STATUS_EQUAL ( c - > status , NT_STATUS_NO_MORE_ENTRIES ) ) {
2007-12-31 04:13:50 +03:00
/* get enumerated accounts counter and resume handle (the latter allows
making subsequent call to continue enumeration ) */
2007-12-18 02:59:21 +03:00
s - > resume_index = * s - > group_list . out . resume_handle ;
2008-11-07 16:51:21 +03:00
s - > count = * s - > group_list . out . num_entries ;
2007-12-18 02:59:21 +03:00
2007-12-31 04:13:50 +03:00
/* prepare returned group accounts array */
2008-11-07 16:51:21 +03:00
s - > groups = talloc_array ( c , struct grouplist , ( * s - > group_list . out . sam ) - > count ) ;
2007-12-18 02:59:21 +03:00
if ( composite_nomem ( s - > groups , c ) ) return ;
2008-11-07 16:51:21 +03:00
for ( i = 0 ; i < ( * s - > group_list . out . sam ) - > count ; i + + ) {
2007-12-18 02:59:21 +03:00
struct dom_sid * group_sid ;
2008-11-07 16:51:21 +03:00
struct samr_SamEntry * entry = & ( * s - > group_list . out . sam ) - > entries [ i ] ;
2008-10-24 17:05:57 +04:00
struct dom_sid * domain_sid = ( * s - > query_domain . out . info ) - > domain . sid ;
2007-12-18 02:59:21 +03:00
2007-12-31 04:13:50 +03:00
/* construct group sid from returned rid and queried domain sid */
2007-12-18 02:59:21 +03:00
group_sid = dom_sid_add_rid ( c , domain_sid , entry - > idx ) ;
if ( composite_nomem ( group_sid , c ) ) return ;
2007-12-31 04:13:50 +03:00
/* groupname */
2007-12-19 02:46:43 +03:00
s - > groups [ i ] . groupname = talloc_strdup ( c , entry - > name . string ) ;
2007-12-18 02:59:21 +03:00
if ( composite_nomem ( s - > groups [ i ] . groupname , c ) ) return ;
2007-12-31 04:13:50 +03:00
/* sid string */
2007-12-18 02:59:21 +03:00
s - > groups [ i ] . sid = dom_sid_string ( c , group_sid ) ;
if ( composite_nomem ( s - > groups [ i ] . sid , c ) ) return ;
}
2007-12-31 04:13:50 +03:00
/* that's it */
2007-12-18 02:59:21 +03:00
composite_done ( c ) ;
} else {
2007-12-31 04:13:50 +03:00
/* something went wrong */
2007-12-18 02:59:21 +03:00
composite_error ( c , c - > status ) ;
}
}
2007-12-31 04:13:50 +03:00
/**
* Receive result of GroupList call
*
* @ param c composite context returned by send request routine
* @ param mem_ctx memory context of this call
* @ param io pointer to structure containing arguments and result of this call
* @ param nt status
*/
2007-12-18 02:59:21 +03:00
NTSTATUS libnet_GroupList_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct libnet_GroupList * io )
{
NTSTATUS status ;
struct grouplist_state * s ;
if ( c = = NULL | | mem_ctx = = NULL | | io = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) | |
NT_STATUS_EQUAL ( status , STATUS_MORE_ENTRIES ) | |
NT_STATUS_EQUAL ( status , NT_STATUS_NO_MORE_ENTRIES ) ) {
s = talloc_get_type ( c - > private_data , struct grouplist_state ) ;
2007-12-31 04:13:50 +03:00
/* get results from composite context */
io - > out . count = s - > count ;
2007-12-18 02:59:21 +03:00
io - > out . resume_index = s - > resume_index ;
2007-12-31 04:13:50 +03:00
io - > out . groups = talloc_steal ( mem_ctx , s - > groups ) ;
2007-12-18 02:59:21 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
io - > out . error_string = talloc_asprintf ( mem_ctx , " Success " ) ;
} else {
2007-12-31 04:13:50 +03:00
/* success, but we're not done yet */
2007-12-18 02:59:21 +03:00
io - > out . error_string = talloc_asprintf ( mem_ctx , " Success (status: %s) " ,
nt_errstr ( status ) ) ;
}
} else {
io - > out . error_string = talloc_asprintf ( mem_ctx , " Error: %s " , nt_errstr ( status ) ) ;
}
return status ;
}
/**
2007-12-31 04:13:50 +03:00
* Enumerate domain groups
2007-12-18 02:59:21 +03:00
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
2007-12-31 04:13:50 +03:00
* @ param io pointer to structure containing arguments and result of this call
2007-12-18 02:59:21 +03:00
* @ return nt status
*/
NTSTATUS libnet_GroupList ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_GroupList * io )
{
2007-12-31 04:13:50 +03:00
struct composite_context * c ;
c = libnet_GroupList_send ( ctx , mem_ctx , io , NULL ) ;
2007-12-18 02:59:21 +03:00
return libnet_GroupList_recv ( c , mem_ctx , io ) ;
}