2005-02-13 03:48:21 +03:00
/*
Unix SMB / CIFS implementation .
2007-09-20 14:23:02 +04:00
Copyright ( C ) Rafal Szczesniak 2005
2005-02-13 03:48:21 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-02-13 03:48:21 +03: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-02-13 03:48:21 +03:00
*/
# include "includes.h"
# include "libnet/libnet.h"
2006-05-16 01:49:27 +04:00
# include "libcli/composite/composite.h"
# include "auth/credentials/credentials.h"
# include "librpc/ndr/libndr.h"
2006-06-27 01:18:45 +04:00
# include "librpc/gen_ndr/samr.h"
2006-11-28 00:55:24 +03:00
# include "librpc/gen_ndr/ndr_samr_c.h"
2006-11-07 01:03:22 +03:00
# include "librpc/gen_ndr/lsa.h"
# include "librpc/gen_ndr/ndr_lsa_c.h"
# include "libcli/security/security.h"
2005-02-13 03:48:21 +03:00
2006-05-16 01:49:27 +04:00
struct create_user_state {
struct libnet_CreateUser r ;
struct libnet_DomainOpen domain_open ;
struct libnet_rpc_useradd user_add ;
struct libnet_context * ctx ;
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_rpc_useradd ( struct composite_context * ctx ) ;
2006-05-18 01:41:59 +04:00
static void continue_domain_open_create ( struct composite_context * ctx ) ;
2006-05-16 01:49:27 +04:00
2006-06-28 00:46:23 +04:00
/**
* Sends request to create user account
*
* @ param ctx initialised libnet context
2006-06-30 00:23:42 +04:00
* @ param mem_ctx memory context of this call
* @ param r pointer to a structure containing arguments and results of this call
* @ param monitor function pointer for receiving monitor messages
* @ return compostite context of this request
2006-06-28 00:46:23 +04:00
*/
2006-05-16 01:49:27 +04:00
struct composite_context * libnet_CreateUser_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_CreateUser * r ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct create_user_state * s ;
struct composite_context * create_req ;
2007-10-07 02:28:14 +04:00
bool prereq_met = false ;
2006-05-16 01:49:27 +04:00
2006-06-28 00:46:23 +04:00
/* composite context allocation and setup */
2006-11-28 00:55:24 +03:00
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
2006-05-16 01:49:27 +04:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct create_user_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2006-06-28 00:46:23 +04:00
/* store arguments in the state structure */
2006-05-16 01:49:27 +04:00
s - > ctx = ctx ;
s - > r = * r ;
2006-05-24 09:17:03 +04:00
ZERO_STRUCT ( s - > r . out ) ;
2006-05-16 01:49:27 +04:00
2006-06-28 00:46:23 +04:00
/* prerequisite: make sure the domain is opened */
2006-12-11 02:43:32 +03:00
prereq_met = samr_domain_opened ( ctx , s - > r . in . domain_name , & c , & s - > domain_open ,
2006-11-28 00:55:24 +03:00
continue_domain_open_create , monitor ) ;
2006-12-11 02:43:32 +03:00
if ( ! prereq_met ) return c ;
2006-06-28 00:46:23 +04:00
/* prepare arguments for useradd call */
2006-05-16 01:49:27 +04:00
s - > user_add . in . username = r - > in . user_name ;
2006-08-22 00:52:14 +04:00
s - > user_add . in . domain_handle = ctx - > samr . handle ;
2006-05-16 01:49:27 +04:00
2006-06-28 00:46:23 +04:00
/* send the request */
2006-08-22 00:52:14 +04:00
create_req = libnet_rpc_useradd_send ( ctx - > samr . pipe , & s - > user_add , monitor ) ;
2006-05-16 01:49:27 +04:00
if ( composite_nomem ( create_req , c ) ) return c ;
2006-06-28 00:46:23 +04:00
/* set the next stage */
2006-05-16 01:49:27 +04:00
composite_continue ( c , create_req , continue_rpc_useradd , c ) ;
return c ;
}
2006-06-28 00:46:23 +04:00
/*
* Stage 0.5 ( optional ) : receive result of domain open request
* and send useradd request
*/
2006-05-18 01:41:59 +04:00
static void continue_domain_open_create ( struct composite_context * ctx )
2006-05-16 01:49:27 +04:00
{
struct composite_context * c ;
struct create_user_state * s ;
struct composite_context * create_req ;
struct monitor_msg msg ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct create_user_state ) ;
2006-06-28 00:46:23 +04:00
/* receive result of DomainOpen call */
2006-05-16 01:49:27 +04:00
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domain_open ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-06-28 00:46:23 +04:00
/* send monitor message */
2006-05-16 01:49:27 +04:00
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
2006-06-28 00:46:23 +04:00
/* prepare arguments for useradd call */
2006-05-16 01:49:27 +04:00
s - > user_add . in . username = s - > r . in . user_name ;
2006-08-22 00:52:14 +04:00
s - > user_add . in . domain_handle = s - > ctx - > samr . handle ;
2006-05-16 01:49:27 +04:00
2006-06-28 00:46:23 +04:00
/* send the request */
2006-08-22 00:52:14 +04:00
create_req = libnet_rpc_useradd_send ( s - > ctx - > samr . pipe , & s - > user_add , s - > monitor_fn ) ;
2006-05-16 01:49:27 +04:00
if ( composite_nomem ( create_req , c ) ) return ;
2006-06-28 00:46:23 +04:00
/* set the next stage */
2006-05-16 01:49:27 +04:00
composite_continue ( c , create_req , continue_rpc_useradd , c ) ;
}
2006-06-28 00:46:23 +04:00
/*
* Stage 1 : receive result of useradd call
*/
2006-05-16 01:49:27 +04:00
static void continue_rpc_useradd ( struct composite_context * ctx )
{
struct composite_context * c ;
struct create_user_state * s ;
struct monitor_msg msg ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct create_user_state ) ;
2006-06-28 00:46:23 +04:00
/* receive result of the call */
2006-05-16 01:49:27 +04:00
c - > status = libnet_rpc_useradd_recv ( ctx , c , & s - > user_add ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-06-28 00:46:23 +04:00
/* send monitor message */
2006-05-16 01:49:27 +04:00
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
2006-06-28 00:46:23 +04:00
/* we're done */
2006-05-16 01:49:27 +04:00
composite_done ( c ) ;
}
2006-06-28 00:46:23 +04:00
/**
* Receive result of CreateUser call
*
* @ param c composite context returned by send request routine
2006-06-30 00:23:42 +04:00
* @ param mem_ctx memory context of this call
* @ param r pointer to a structure containing arguments and result of this call
2006-06-28 00:46:23 +04:00
* @ return nt status
*/
2006-05-16 01:49:27 +04:00
NTSTATUS libnet_CreateUser_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct libnet_CreateUser * r )
{
NTSTATUS status ;
struct create_user_state * s ;
2006-05-28 14:43:48 +04:00
r - > out . error_string = NULL ;
2006-06-30 00:23:42 +04:00
/* wait for result of async request and check status code */
2006-05-16 01:49:27 +04:00
status = composite_wait ( c ) ;
2006-06-28 00:46:23 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-05-16 01:49:27 +04:00
s = talloc_get_type ( c - > private_data , struct create_user_state ) ;
2006-05-28 14:43:48 +04:00
r - > out . error_string = talloc_strdup ( mem_ctx , nt_errstr ( status ) ) ;
2006-05-16 01:49:27 +04:00
}
return status ;
}
2006-06-28 00:46:23 +04:00
/**
* Synchronous version of CreateUser call
*
* @ param ctx initialised libnet context
2006-06-30 00:23:42 +04:00
* @ param mem_ctx memory context of this call
* @ param r pointer to a structure containing arguments and result of this call
2006-06-28 00:46:23 +04:00
* @ return nt status
*/
2006-05-16 01:49:27 +04:00
NTSTATUS libnet_CreateUser ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_CreateUser * r )
{
struct composite_context * c ;
c = libnet_CreateUser_send ( ctx , mem_ctx , r , NULL ) ;
return libnet_CreateUser_recv ( c , mem_ctx , r ) ;
}
2006-05-18 01:41:59 +04:00
struct delete_user_state {
struct libnet_DeleteUser r ;
struct libnet_context * ctx ;
struct libnet_DomainOpen domain_open ;
struct libnet_rpc_userdel user_del ;
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_rpc_userdel ( struct composite_context * ctx ) ;
static void continue_domain_open_delete ( struct composite_context * ctx ) ;
2006-06-30 00:23:42 +04:00
/**
* Sends request to delete user account
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param r pointer to structure containing arguments and result of this call
* @ param monitor function pointer for receiving monitor messages
*/
2006-05-18 01:41:59 +04:00
struct composite_context * libnet_DeleteUser_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_DeleteUser * r ,
void ( * monitor ) ( struct monitor_msg * ) )
2005-02-13 03:48:21 +03:00
{
2006-05-18 01:41:59 +04:00
struct composite_context * c ;
struct delete_user_state * s ;
struct composite_context * delete_req ;
2007-10-07 02:28:14 +04:00
bool prereq_met = false ;
2006-05-18 01:41:59 +04:00
2006-06-30 00:23:42 +04:00
/* composite context allocation and setup */
2006-11-28 00:55:24 +03:00
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
2006-05-18 01:41:59 +04:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct delete_user_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2006-06-30 00:23:42 +04:00
/* store arguments in state structure */
2006-05-18 01:41:59 +04:00
s - > ctx = ctx ;
2006-06-30 00:23:42 +04:00
s - > r = * r ;
2006-05-24 09:18:55 +04:00
ZERO_STRUCT ( s - > r . out ) ;
2005-02-13 03:48:21 +03:00
2006-06-30 00:23:42 +04:00
/* prerequisite: make sure the domain is opened before proceeding */
2006-12-11 02:43:32 +03:00
prereq_met = samr_domain_opened ( ctx , s - > r . in . domain_name , & c , & s - > domain_open ,
2006-11-28 00:55:24 +03:00
continue_domain_open_delete , monitor ) ;
2006-12-11 02:43:32 +03:00
if ( ! prereq_met ) return c ;
2005-02-13 03:48:21 +03:00
2006-06-30 00:23:42 +04:00
/* prepare arguments for userdel call */
2006-05-18 01:41:59 +04:00
s - > user_del . in . username = r - > in . user_name ;
2006-08-22 00:52:14 +04:00
s - > user_del . in . domain_handle = ctx - > samr . handle ;
2006-06-30 00:23:42 +04:00
/* send request */
2006-08-22 00:52:14 +04:00
delete_req = libnet_rpc_userdel_send ( ctx - > samr . pipe , & s - > user_del , monitor ) ;
2006-05-18 01:41:59 +04:00
if ( composite_nomem ( delete_req , c ) ) return c ;
2006-06-30 00:23:42 +04:00
/* set the next stage */
2006-05-18 01:41:59 +04:00
composite_continue ( c , delete_req , continue_rpc_userdel , c ) ;
return c ;
}
2005-02-13 03:48:21 +03:00
2005-06-08 03:24:10 +04:00
2006-06-30 00:23:42 +04:00
/*
* Stage 0.5 ( optional ) : receive result of domain open request
* and send useradd request
*/
2006-05-18 01:41:59 +04:00
static void continue_domain_open_delete ( struct composite_context * ctx )
{
struct composite_context * c ;
struct delete_user_state * s ;
struct composite_context * delete_req ;
struct monitor_msg msg ;
2005-02-13 03:48:21 +03:00
2006-05-18 01:41:59 +04:00
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct delete_user_state ) ;
2005-06-08 03:24:10 +04:00
2006-06-30 00:23:42 +04:00
/* receive result of DomainOpen call */
2006-05-18 01:41:59 +04:00
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domain_open ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-06-30 00:23:42 +04:00
/* send monitor message */
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
/* prepare arguments for userdel call */
2006-05-18 01:41:59 +04:00
s - > user_del . in . username = s - > r . in . user_name ;
2006-08-22 00:52:14 +04:00
s - > user_del . in . domain_handle = s - > ctx - > samr . handle ;
2006-05-18 01:41:59 +04:00
2006-06-30 00:23:42 +04:00
/* send request */
2006-08-22 00:52:14 +04:00
delete_req = libnet_rpc_userdel_send ( s - > ctx - > samr . pipe , & s - > user_del , s - > monitor_fn ) ;
2006-05-18 01:41:59 +04:00
if ( composite_nomem ( delete_req , c ) ) return ;
2006-06-30 00:23:42 +04:00
/* set the next stage */
2006-05-18 01:41:59 +04:00
composite_continue ( c , delete_req , continue_rpc_userdel , c ) ;
2005-02-13 03:48:21 +03:00
}
2006-05-16 01:49:27 +04:00
2006-01-13 06:39:49 +03:00
2006-10-19 01:21:28 +04:00
/*
* Stage 1 : receive result of userdel call and finish the composite function
*/
2006-05-18 01:41:59 +04:00
static void continue_rpc_userdel ( struct composite_context * ctx )
2006-01-13 06:39:49 +03:00
{
2006-05-18 01:41:59 +04:00
struct composite_context * c ;
struct delete_user_state * s ;
struct monitor_msg msg ;
2006-01-13 06:39:49 +03:00
2006-05-18 01:41:59 +04:00
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct delete_user_state ) ;
2006-01-13 06:39:49 +03:00
2006-06-30 00:23:42 +04:00
/* receive result of userdel call */
2006-05-18 01:41:59 +04:00
c - > status = libnet_rpc_userdel_recv ( ctx , c , & s - > user_del ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-06-30 00:23:42 +04:00
/* send monitor message */
2006-05-18 01:41:59 +04:00
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
2006-06-30 00:23:42 +04:00
/* we're done */
2006-05-18 01:41:59 +04:00
composite_done ( c ) ;
}
2006-01-13 06:39:49 +03:00
2006-06-30 00:23:42 +04:00
/**
* Receives result of asynchronous DeleteUser call
*
* @ param c composite context returned by async DeleteUser call
* @ param mem_ctx memory context of this call
* @ param r pointer to structure containing arguments and result
*/
2006-05-18 01:41:59 +04:00
NTSTATUS libnet_DeleteUser_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
2006-05-18 02:07:32 +04:00
struct libnet_DeleteUser * r )
2006-05-18 01:41:59 +04:00
{
NTSTATUS status ;
struct delete_user_state * s ;
2006-06-30 00:23:42 +04:00
r - > out . error_string = NULL ;
/* wait for result of async request and check status code */
2006-05-18 01:41:59 +04:00
status = composite_wait ( c ) ;
2006-06-30 00:23:42 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2006-05-18 01:41:59 +04:00
s = talloc_get_type ( c - > private_data , struct delete_user_state ) ;
r - > out . error_string = talloc_steal ( mem_ctx , s - > r . out . error_string ) ;
2006-01-13 06:39:49 +03:00
}
2006-05-18 01:41:59 +04:00
2006-01-13 06:39:49 +03:00
return status ;
}
2006-05-18 01:41:59 +04:00
2006-06-30 00:23:42 +04:00
/**
* Synchronous version of DeleteUser call
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param r pointer to structure containing arguments and result
*/
2006-05-18 01:41:59 +04:00
NTSTATUS libnet_DeleteUser ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_DeleteUser * r )
{
struct composite_context * c ;
c = libnet_DeleteUser_send ( ctx , mem_ctx , r , NULL ) ;
return libnet_DeleteUser_recv ( c , mem_ctx , r ) ;
}
2006-05-28 14:43:48 +04:00
struct modify_user_state {
struct libnet_ModifyUser r ;
struct libnet_context * ctx ;
struct libnet_DomainOpen domain_open ;
2006-06-14 01:57:44 +04:00
struct libnet_rpc_userinfo user_info ;
2006-05-28 14:43:48 +04:00
struct libnet_rpc_usermod user_mod ;
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_rpc_usermod ( struct composite_context * ctx ) ;
static void continue_domain_open_modify ( struct composite_context * ctx ) ;
2006-06-27 01:18:45 +04:00
static NTSTATUS set_user_changes ( TALLOC_CTX * mem_ctx , struct usermod_change * mod ,
struct libnet_rpc_userinfo * info , struct libnet_ModifyUser * r ) ;
2006-06-14 01:57:44 +04:00
static void continue_rpc_userinfo ( struct composite_context * ctx ) ;
2006-05-28 14:43:48 +04:00
2006-10-19 01:21:28 +04:00
/**
* Sends request to modify user account
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param r pointer to structure containing arguments and result of this call
* @ param monitor function pointer for receiving monitor messages
*/
2006-05-28 14:43:48 +04:00
struct composite_context * libnet_ModifyUser_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_ModifyUser * r ,
void ( * monitor ) ( struct monitor_msg * ) )
{
2006-09-19 04:24:41 +04:00
const uint16_t level = 21 ;
2006-05-28 14:43:48 +04:00
struct composite_context * c ;
struct modify_user_state * s ;
2006-06-14 01:57:44 +04:00
struct composite_context * userinfo_req ;
2007-10-07 02:28:14 +04:00
bool prereq_met = false ;
2006-05-28 14:43:48 +04:00
2006-11-28 00:55:24 +03:00
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
2006-05-28 14:43:48 +04:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct modify_user_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
s - > ctx = ctx ;
s - > r = * r ;
2006-12-11 02:43:32 +03:00
prereq_met = samr_domain_opened ( ctx , s - > r . in . domain_name , & c , & s - > domain_open ,
2006-11-28 00:55:24 +03:00
continue_domain_open_modify , monitor ) ;
2006-12-11 02:43:32 +03:00
if ( ! prereq_met ) return c ;
2006-05-28 14:43:48 +04:00
2006-09-19 04:24:41 +04:00
s - > user_info . in . username = r - > in . user_name ;
s - > user_info . in . domain_handle = ctx - > samr . handle ;
s - > user_info . in . level = level ;
2006-05-28 14:43:48 +04:00
2006-08-22 00:52:14 +04:00
userinfo_req = libnet_rpc_userinfo_send ( ctx - > samr . pipe , & s - > user_info , monitor ) ;
2006-06-14 01:57:44 +04:00
if ( composite_nomem ( userinfo_req , c ) ) return c ;
2006-05-28 14:43:48 +04:00
2006-06-14 01:57:44 +04:00
composite_continue ( c , userinfo_req , continue_rpc_userinfo , c ) ;
2006-05-28 14:43:48 +04:00
return c ;
}
2006-10-19 01:21:28 +04:00
/*
* Stage 0.5 ( optional ) : receive result of domain open request
* and send userinfo request
*/
2006-05-28 14:43:48 +04:00
static void continue_domain_open_modify ( struct composite_context * ctx )
{
2006-06-14 01:57:44 +04:00
const uint16_t level = 21 ;
2006-05-28 14:43:48 +04:00
struct composite_context * c ;
struct modify_user_state * s ;
2006-06-14 01:57:44 +04:00
struct composite_context * userinfo_req ;
2006-05-28 14:43:48 +04:00
struct monitor_msg msg ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct modify_user_state ) ;
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domain_open ) ;
if ( ! composite_is_ok ( c ) ) return ;
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
2006-08-22 00:52:14 +04:00
s - > user_info . in . domain_handle = s - > ctx - > samr . handle ;
2006-06-14 01:57:44 +04:00
s - > user_info . in . username = s - > r . in . user_name ;
s - > user_info . in . level = level ;
2006-05-28 14:43:48 +04:00
2006-08-22 00:52:14 +04:00
userinfo_req = libnet_rpc_userinfo_send ( s - > ctx - > samr . pipe , & s - > user_info , s - > monitor_fn ) ;
2006-06-14 01:57:44 +04:00
if ( composite_nomem ( userinfo_req , c ) ) return ;
2006-05-28 14:43:48 +04:00
2006-06-14 01:57:44 +04:00
composite_continue ( c , userinfo_req , continue_rpc_userinfo , c ) ;
}
2006-10-19 01:21:28 +04:00
/*
* Stage 1 : receive result of userinfo call , prepare user changes
* ( set the fields a caller required to change ) and send usermod request
*/
2006-06-14 01:57:44 +04:00
static void continue_rpc_userinfo ( struct composite_context * ctx )
{
struct composite_context * c ;
struct modify_user_state * s ;
struct composite_context * usermod_req ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct modify_user_state ) ;
c - > status = libnet_rpc_userinfo_recv ( ctx , c , & s - > user_info ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-08-22 00:52:14 +04:00
s - > user_mod . in . domain_handle = s - > ctx - > samr . handle ;
2006-06-27 01:18:45 +04:00
s - > user_mod . in . username = s - > r . in . user_name ;
c - > status = set_user_changes ( c , & s - > user_mod . in . change , & s - > user_info , & s - > r ) ;
2006-06-14 01:57:44 +04:00
2006-08-22 00:52:14 +04:00
usermod_req = libnet_rpc_usermod_send ( s - > ctx - > samr . pipe , & s - > user_mod , s - > monitor_fn ) ;
2006-06-14 01:57:44 +04:00
if ( composite_nomem ( usermod_req , c ) ) return ;
composite_continue ( c , usermod_req , continue_rpc_usermod , c ) ;
2006-05-28 14:43:48 +04:00
}
2006-10-19 01:21:28 +04:00
/*
* Prepare user changes : compare userinfo result to requested changes and
* set the field values and flags accordingly for user modify call
*/
2006-06-27 01:18:45 +04:00
static NTSTATUS set_user_changes ( TALLOC_CTX * mem_ctx , struct usermod_change * mod ,
struct libnet_rpc_userinfo * info , struct libnet_ModifyUser * r )
{
struct samr_UserInfo21 * user ;
if ( mod = = NULL | | info = = NULL | | r = = NULL | | info - > in . level ! = 21 ) {
return NT_STATUS_INVALID_PARAMETER ;
}
user = & info - > out . info . info21 ;
mod - > fields = 0 ; /* reset flag field before setting individual flags */
2006-08-08 00:29:18 +04:00
/* account name change */
SET_FIELD_LSA_STRING ( r - > in , user , mod , account_name , USERMOD_FIELD_ACCOUNT_NAME ) ;
2006-06-27 01:18:45 +04:00
2006-08-08 00:29:18 +04:00
/* full name change */
SET_FIELD_LSA_STRING ( r - > in , user , mod , full_name , USERMOD_FIELD_FULL_NAME ) ;
2006-06-27 01:18:45 +04:00
2006-08-08 00:29:18 +04:00
/* description change */
2006-09-18 21:33:23 +04:00
SET_FIELD_LSA_STRING ( r - > in , user , mod , description , USERMOD_FIELD_DESCRIPTION ) ;
2006-06-27 01:18:45 +04:00
2006-08-08 00:29:18 +04:00
/* comment change */
SET_FIELD_LSA_STRING ( r - > in , user , mod , comment , USERMOD_FIELD_COMMENT ) ;
2006-06-27 01:18:45 +04:00
2006-08-08 00:29:18 +04:00
/* home directory change */
SET_FIELD_LSA_STRING ( r - > in , user , mod , home_directory , USERMOD_FIELD_HOME_DIRECTORY ) ;
2006-06-27 01:18:45 +04:00
2006-08-08 00:29:18 +04:00
/* home drive change */
SET_FIELD_LSA_STRING ( r - > in , user , mod , home_drive , USERMOD_FIELD_HOME_DRIVE ) ;
2006-06-30 00:23:42 +04:00
2006-08-08 00:29:18 +04:00
/* logon script change */
SET_FIELD_LSA_STRING ( r - > in , user , mod , logon_script , USERMOD_FIELD_LOGON_SCRIPT ) ;
2006-06-30 00:23:42 +04:00
2006-08-08 00:29:18 +04:00
/* profile path change */
SET_FIELD_LSA_STRING ( r - > in , user , mod , profile_path , USERMOD_FIELD_PROFILE_PATH ) ;
/* account expiry change */
SET_FIELD_NTTIME ( r - > in , user , mod , acct_expiry , USERMOD_FIELD_ACCT_EXPIRY ) ;
2006-06-30 00:23:42 +04:00
2007-09-20 14:23:02 +04:00
/* account flags change */
2008-02-28 02:43:57 +03:00
SET_FIELD_ACCT_FLAGS ( r - > in , user , mod , acct_flags , USERMOD_FIELD_ACCT_FLAGS ) ;
2007-09-20 14:23:02 +04:00
2006-06-27 01:18:45 +04:00
return NT_STATUS_OK ;
}
2006-10-19 01:21:28 +04:00
/*
* Stage 2 : receive result of usermod request and finish the composite function
*/
2006-05-28 14:43:48 +04:00
static void continue_rpc_usermod ( struct composite_context * ctx )
{
struct composite_context * c ;
struct modify_user_state * s ;
struct monitor_msg msg ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct modify_user_state ) ;
c - > status = libnet_rpc_usermod_recv ( ctx , c , & s - > user_mod ) ;
if ( ! composite_is_ok ( c ) ) return ;
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
composite_done ( c ) ;
}
2006-10-19 01:21:28 +04:00
/**
* Receive result of ModifyUser 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
*/
2006-05-28 14:43:48 +04:00
NTSTATUS libnet_ModifyUser_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct libnet_ModifyUser * r )
{
NTSTATUS status = composite_wait ( c ) ;
return status ;
}
2006-10-19 01:21:28 +04:00
/**
* Synchronous version of ModifyUser call
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param r pointer to a structure containing arguments and result of this call
* @ return nt status
*/
2006-05-28 14:43:48 +04:00
NTSTATUS libnet_ModifyUser ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_ModifyUser * r )
{
struct composite_context * c ;
c = libnet_ModifyUser_send ( ctx , mem_ctx , r , NULL ) ;
return libnet_ModifyUser_recv ( c , mem_ctx , r ) ;
}
2006-08-28 00:37:23 +04:00
struct user_info_state {
struct libnet_context * ctx ;
const char * domain_name ;
2008-04-19 16:09:18 +04:00
enum libnet_UserInfo_level level ;
2006-10-02 09:53:45 +04:00
const char * user_name ;
2008-04-19 16:09:18 +04:00
const char * sid_string ;
2006-08-28 00:37:23 +04:00
struct libnet_LookupName lookup ;
struct libnet_DomainOpen domopen ;
struct libnet_rpc_userinfo userinfo ;
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
static void continue_name_found ( struct composite_context * ctx ) ;
2006-10-02 09:53:45 +04:00
static void continue_domain_open_info ( struct composite_context * ctx ) ;
2006-08-28 00:37:23 +04:00
static void continue_info_received ( struct composite_context * ctx ) ;
2006-10-19 01:21:28 +04:00
/**
* Sends request to get user account information
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param r pointer to a structure containing arguments and results of this call
* @ param monitor function pointer for receiving monitor messages
* @ return compostite context of this request
*/
2006-08-28 00:37:23 +04:00
struct composite_context * libnet_UserInfo_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_UserInfo * r ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct user_info_state * s ;
2008-04-19 16:09:18 +04:00
struct composite_context * lookup_req , * info_req ;
2007-10-07 02:28:14 +04:00
bool prereq_met = false ;
2006-08-28 00:37:23 +04:00
2006-10-19 01:21:28 +04:00
/* composite context allocation and setup */
2006-08-28 00:37:23 +04:00
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct user_info_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2006-10-19 01:21:28 +04:00
/* store arguments in the state structure */
2006-08-28 00:37:23 +04:00
s - > monitor_fn = monitor ;
s - > ctx = ctx ;
s - > domain_name = talloc_strdup ( c , r - > in . domain_name ) ;
2008-04-19 16:09:18 +04:00
s - > level = r - > in . level ;
switch ( s - > level ) {
case USER_INFO_BY_NAME :
s - > user_name = talloc_strdup ( c , r - > in . data . user_name ) ;
s - > sid_string = NULL ;
break ;
case USER_INFO_BY_SID :
s - > user_name = NULL ;
s - > sid_string = dom_sid_string ( c , r - > in . data . user_sid ) ;
break ;
}
2006-10-02 09:53:45 +04:00
2006-10-19 01:21:28 +04:00
/* prerequisite: make sure the domain is opened */
2006-12-11 02:43:32 +03:00
prereq_met = samr_domain_opened ( ctx , s - > domain_name , & c , & s - > domopen ,
2006-11-28 00:55:24 +03:00
continue_domain_open_info , monitor ) ;
2006-12-11 02:43:32 +03:00
if ( ! prereq_met ) return c ;
2006-08-28 00:37:23 +04:00
2008-04-19 16:09:18 +04:00
switch ( s - > level ) {
case USER_INFO_BY_NAME :
/* prepare arguments for LookupName call */
s - > lookup . in . domain_name = s - > domain_name ;
s - > lookup . in . name = s - > user_name ;
/* send the request */
lookup_req = libnet_LookupName_send ( 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 USER_INFO_BY_SID :
/* prepare arguments for UserInfo call */
s - > userinfo . in . domain_handle = s - > ctx - > samr . handle ;
s - > userinfo . in . sid = s - > sid_string ;
s - > userinfo . in . level = 21 ;
/* send the request */
info_req = libnet_rpc_userinfo_send ( s - > ctx - > samr . pipe ,
& s - > userinfo ,
s - > monitor_fn ) ;
if ( composite_nomem ( info_req , c ) ) return c ;
/* set the next stage */
composite_continue ( c , info_req , continue_info_received , c ) ;
break ;
}
2006-08-28 00:37:23 +04:00
return c ;
}
2006-10-19 01:21:28 +04:00
/*
* Stage 0.5 ( optional ) : receive result of domain open request
* and send LookupName request
*/
2006-10-02 09:53:45 +04:00
static void continue_domain_open_info ( struct composite_context * ctx )
2006-08-28 00:37:23 +04:00
{
struct composite_context * c ;
struct user_info_state * s ;
2008-04-19 16:09:18 +04:00
struct composite_context * lookup_req , * info_req ;
2006-10-02 09:53:45 +04:00
struct monitor_msg msg ;
2006-08-28 00:37:23 +04:00
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct user_info_state ) ;
2006-10-19 01:21:28 +04:00
/* receive result of DomainOpen call */
2006-10-02 09:53:45 +04:00
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domopen ) ;
2006-08-28 00:37:23 +04:00
if ( ! composite_is_ok ( c ) ) return ;
2006-10-19 01:21:28 +04:00
/* send monitor message */
2006-10-02 09:53:45 +04:00
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
2006-08-28 00:37:23 +04:00
2008-04-19 16:09:18 +04:00
switch ( s - > level ) {
case USER_INFO_BY_NAME :
/* prepare arguments for LookupName call */
s - > lookup . in . domain_name = s - > domain_name ;
s - > lookup . in . name = s - > user_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 USER_INFO_BY_SID :
/* prepare arguments for UserInfo call */
s - > userinfo . in . domain_handle = s - > ctx - > samr . handle ;
s - > userinfo . in . sid = s - > sid_string ;
s - > userinfo . in . level = 21 ;
/* send the request */
info_req = libnet_rpc_userinfo_send ( s - > ctx - > samr . pipe ,
& s - > userinfo ,
s - > monitor_fn ) ;
if ( composite_nomem ( info_req , c ) ) return ;
/* set the next stage */
composite_continue ( c , info_req , continue_info_received , c ) ;
break ;
}
2006-08-28 00:37:23 +04:00
}
2006-10-19 01:21:28 +04:00
/*
* Stage 1 : receive the name ( if found ) and send userinfo request
*/
2006-10-02 09:53:45 +04:00
static void continue_name_found ( struct composite_context * ctx )
2006-08-28 00:37:23 +04:00
{
struct composite_context * c ;
struct user_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 user_info_state ) ;
2006-10-19 01:21:28 +04:00
/* receive result of LookupName call */
2006-10-02 09:53:45 +04:00
c - > status = libnet_LookupName_recv ( ctx , c , & s - > lookup ) ;
2006-08-28 00:37:23 +04:00
if ( ! composite_is_ok ( c ) ) return ;
2006-10-19 01:21:28 +04:00
/* we're only interested in user accounts this time */
2006-10-02 09:53:45 +04:00
if ( s - > lookup . out . sid_type ! = SID_NAME_USER ) {
composite_error ( c , NT_STATUS_NO_SUCH_USER ) ;
return ;
}
2006-10-19 01:21:28 +04:00
/* prepare arguments for UserInfo call */
2006-08-28 00:37:23 +04:00
s - > userinfo . in . domain_handle = s - > ctx - > samr . handle ;
s - > userinfo . in . sid = s - > lookup . out . sidstr ;
s - > userinfo . in . level = 21 ;
2006-10-19 01:21:28 +04:00
/* send the request */
2006-08-28 00:37:23 +04:00
info_req = libnet_rpc_userinfo_send ( s - > ctx - > samr . pipe , & s - > userinfo , s - > monitor_fn ) ;
if ( composite_nomem ( info_req , c ) ) return ;
2006-10-19 01:21:28 +04:00
/* set the next stage */
2006-08-28 00:37:23 +04:00
composite_continue ( c , info_req , continue_info_received , c ) ;
}
2006-10-19 01:21:28 +04:00
/*
* Stage 2 : receive user account information and finish the composite function
*/
2006-08-28 00:37:23 +04:00
static void continue_info_received ( struct composite_context * ctx )
{
struct composite_context * c ;
struct user_info_state * s ;
c = talloc_get_type ( ctx - > async . private_data , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct user_info_state ) ;
2006-10-19 01:21:28 +04:00
/* receive result of userinfo call */
2006-08-28 00:37:23 +04:00
c - > status = libnet_rpc_userinfo_recv ( ctx , c , & s - > userinfo ) ;
if ( ! composite_is_ok ( c ) ) return ;
composite_done ( c ) ;
}
2006-10-19 01:21:28 +04:00
/**
* Receive result of UserInfo 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
*/
2006-08-28 00:37:23 +04:00
NTSTATUS libnet_UserInfo_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct libnet_UserInfo * r )
{
NTSTATUS status ;
struct user_info_state * s ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & r ! = NULL ) {
struct samr_UserInfo21 * info ;
s = talloc_get_type ( c - > private_data , struct user_info_state ) ;
info = & s - > userinfo . out . info . info21 ;
2007-08-02 17:08:39 +04:00
r - > out . user_sid = dom_sid_add_rid ( mem_ctx , s - > ctx - > samr . sid , info - > rid ) ;
r - > out . primary_group_sid = dom_sid_add_rid ( mem_ctx , s - > ctx - > samr . sid , info - > primary_gid ) ;
2006-09-18 21:33:23 +04:00
/* string fields */
2006-08-28 00:37:23 +04:00
r - > out . account_name = talloc_steal ( mem_ctx , info - > account_name . string ) ;
r - > out . full_name = talloc_steal ( mem_ctx , info - > full_name . string ) ;
r - > out . description = talloc_steal ( mem_ctx , info - > description . string ) ;
r - > out . home_directory = talloc_steal ( mem_ctx , info - > home_directory . string ) ;
r - > out . home_drive = talloc_steal ( mem_ctx , info - > home_drive . string ) ;
r - > out . comment = talloc_steal ( mem_ctx , info - > comment . string ) ;
r - > out . logon_script = talloc_steal ( mem_ctx , info - > logon_script . string ) ;
r - > out . profile_path = talloc_steal ( mem_ctx , info - > profile_path . string ) ;
2006-09-18 21:33:23 +04:00
/* time fields (allocation) */
r - > out . acct_expiry = talloc ( mem_ctx , struct timeval ) ;
r - > out . allow_password_change = talloc ( mem_ctx , struct timeval ) ;
r - > out . force_password_change = talloc ( mem_ctx , struct timeval ) ;
r - > out . last_logon = talloc ( mem_ctx , struct timeval ) ;
r - > out . last_logoff = talloc ( mem_ctx , struct timeval ) ;
r - > out . last_password_change = talloc ( mem_ctx , struct timeval ) ;
/* time fields (converting) */
nttime_to_timeval ( r - > out . acct_expiry , info - > acct_expiry ) ;
nttime_to_timeval ( r - > out . allow_password_change , info - > allow_password_change ) ;
nttime_to_timeval ( r - > out . force_password_change , info - > force_password_change ) ;
nttime_to_timeval ( r - > out . last_logon , info - > last_logon ) ;
nttime_to_timeval ( r - > out . last_logoff , info - > last_logoff ) ;
nttime_to_timeval ( r - > out . last_password_change , info - > last_password_change ) ;
/* flag and number fields */
r - > out . acct_flags = info - > acct_flags ;
2006-08-28 00:37:23 +04:00
r - > out . error_string = talloc_strdup ( mem_ctx , " Success " ) ;
2006-12-14 02:36:34 +03:00
} else {
r - > out . error_string = talloc_asprintf ( mem_ctx , " Error: %s " , nt_errstr ( status ) ) ;
2006-08-28 00:37:23 +04:00
}
talloc_free ( c ) ;
return status ;
}
2006-10-19 01:21:28 +04:00
/**
* Synchronous version of UserInfo call
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
* @ param r pointer to a structure containing arguments and result of this call
* @ return nt status
*/
2006-08-28 00:37:23 +04:00
NTSTATUS libnet_UserInfo ( struct libnet_context * ctx , TALLOC_CTX * mem_ctx ,
struct libnet_UserInfo * r )
{
struct composite_context * c ;
c = libnet_UserInfo_send ( ctx , mem_ctx , r , NULL ) ;
return libnet_UserInfo_recv ( c , mem_ctx , r ) ;
}
2006-11-07 01:03:22 +03:00
struct userlist_state {
struct libnet_context * ctx ;
2006-11-28 00:55:24 +03:00
const char * domain_name ;
struct lsa_DomainInfo dominfo ;
2006-11-07 01:03:22 +03:00
int page_size ;
2006-11-28 00:55:24 +03:00
uint32_t resume_index ;
2006-11-07 01:03:22 +03:00
struct userlist * users ;
2006-11-28 00:55:24 +03:00
uint32_t count ;
2006-11-07 01:03:22 +03:00
struct libnet_DomainOpen domain_open ;
2006-11-28 00:55:24 +03:00
struct lsa_QueryInfoPolicy query_domain ;
struct samr_EnumDomainUsers user_list ;
2006-11-07 01:03:22 +03:00
void ( * monitor_fn ) ( struct monitor_msg * ) ;
} ;
2006-11-28 00:55:24 +03:00
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 ) ;
2006-11-07 01:03:22 +03:00
static void continue_users_enumerated ( struct rpc_request * req ) ;
2006-11-09 00:40:11 +03:00
/**
* Sends request to list ( enumerate ) user accounts
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
2007-12-31 04:14:43 +03:00
* @ param r pointer to structure containing arguments and results of this call
2006-11-09 00:40:11 +03:00
* @ param monitor function pointer for receiving monitor messages
* @ return compostite context of this request
*/
2006-11-07 01:03:22 +03:00
struct composite_context * libnet_UserList_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_UserList * r ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct userlist_state * s ;
2006-11-28 00:55:24 +03:00
struct rpc_request * query_req ;
2007-10-07 02:28:14 +04:00
bool prereq_met = false ;
2006-11-09 00:40:11 +03:00
/* composite context allocation and setup */
2006-11-28 00:55:24 +03:00
c = composite_create ( mem_ctx , ctx - > event_ctx ) ;
2006-11-07 01:03:22 +03:00
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct userlist_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
2006-11-09 00:40:11 +03:00
/* store the arguments in the state structure */
2006-11-28 00:55:24 +03:00
s - > ctx = ctx ;
s - > page_size = r - > in . page_size ;
s - > resume_index = ( uint32_t ) r - > in . resume_index ;
s - > domain_name = talloc_strdup ( c , r - > in . domain_name ) ;
s - > monitor_fn = monitor ;
2006-11-07 01:03:22 +03:00
2006-11-09 00:40:11 +03:00
/* make sure we have lsa domain handle before doing anything */
2006-12-11 02:43:32 +03:00
prereq_met = lsa_domain_opened ( ctx , s - > domain_name , & c , & s - > domain_open ,
2006-11-28 00:55:24 +03:00
continue_lsa_domain_opened , monitor ) ;
2006-12-11 02:43:32 +03:00
if ( ! prereq_met ) return c ;
2006-11-07 01:03:22 +03:00
2006-11-30 22:51:58 +03:00
/* prepare arguments of QueryDomainInfo call */
2006-11-28 00:55:24 +03:00
s - > query_domain . in . handle = & ctx - > lsa . handle ;
s - > query_domain . in . level = LSA_POLICY_INFO_DOMAIN ;
2006-11-30 22:51:58 +03:00
/* send the request */
2006-11-28 00:55:24 +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 ;
}
/*
2006-11-30 22:51:58 +03:00
* Stage 0.5 ( optional ) : receive lsa domain handle and send
* request to query domain info
2006-11-28 00:55:24 +03:00
*/
static void continue_lsa_domain_opened ( struct composite_context * ctx )
{
struct composite_context * c ;
struct userlist_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 userlist_state ) ;
2006-11-30 22:51:58 +03:00
2006-11-28 00:55:24 +03:00
/* receive lsa domain handle */
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domain_open ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-11-30 22:51:58 +03:00
/* prepare arguments of QueryDomainInfo call */
2006-11-28 00:55:24 +03:00
s - > query_domain . in . handle = & s - > ctx - > lsa . handle ;
s - > query_domain . in . level = LSA_POLICY_INFO_DOMAIN ;
2006-11-30 22:51:58 +03:00
/* send the request */
2006-11-28 00:55:24 +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 ) ;
}
/*
2006-11-30 22:51:58 +03:00
* Stage 1 : receive domain info and request to enum users ,
* provided a valid samr handle is opened
2006-11-28 00:55:24 +03:00
*/
static void continue_domain_queried ( struct rpc_request * req )
{
struct composite_context * c ;
struct userlist_state * s ;
struct rpc_request * enum_req ;
2007-10-07 02:28:14 +04:00
bool prereq_met = false ;
2006-11-28 00:55:24 +03:00
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2006-11-28 00:55:24 +03:00
s = talloc_get_type ( c - > private_data , struct userlist_state ) ;
2006-11-30 22:51:58 +03:00
/* receive result of rpc request */
2006-11-28 00:55:24 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
if ( ! composite_is_ok ( c ) ) return ;
2006-11-30 22:51:58 +03:00
/* get the returned domain info */
2006-11-28 00:55:24 +03:00
s - > dominfo = s - > query_domain . out . info - > domain ;
2006-11-30 22:51:58 +03:00
/* make sure we have samr domain handle before continuing */
2006-12-11 02:43:32 +03:00
prereq_met = samr_domain_opened ( s - > ctx , s - > domain_name , & c , & s - > domain_open ,
2006-11-28 00:55:24 +03:00
continue_samr_domain_opened , s - > monitor_fn ) ;
2006-12-11 02:43:32 +03:00
if ( ! prereq_met ) return ;
2006-11-28 00:55:24 +03:00
2007-12-31 04:14:43 +03:00
/* prepare arguments of EnumDomainUsers call */
2006-11-28 00:55:24 +03:00
s - > user_list . in . domain_handle = & s - > ctx - > samr . handle ;
s - > user_list . in . max_size = s - > page_size ;
s - > user_list . in . resume_handle = & s - > resume_index ;
s - > user_list . in . acct_flags = ACB_NORMAL ;
s - > user_list . out . resume_handle = & s - > resume_index ;
2006-11-07 01:03:22 +03:00
2006-11-30 22:51:58 +03:00
/* send the request */
2006-11-28 00:55:24 +03:00
enum_req = dcerpc_samr_EnumDomainUsers_send ( s - > ctx - > samr . pipe , c , & s - > user_list ) ;
if ( composite_nomem ( enum_req , c ) ) return ;
2006-11-07 01:03:22 +03:00
composite_continue_rpc ( c , enum_req , continue_users_enumerated , c ) ;
}
2006-11-09 00:40:11 +03:00
/*
2006-11-30 22:51:58 +03:00
* Stage 1.5 ( optional ) : receive samr domain handle
* and request to enumerate accounts
2006-11-09 00:40:11 +03:00
*/
2006-11-28 00:55:24 +03:00
static void continue_samr_domain_opened ( struct composite_context * ctx )
2006-11-07 01:03:22 +03:00
{
struct composite_context * c ;
struct userlist_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 userlist_state ) ;
2006-11-30 22:51:58 +03:00
/* receive samr domain handle */
2006-11-07 01:03:22 +03:00
c - > status = libnet_DomainOpen_recv ( ctx , s - > ctx , c , & s - > domain_open ) ;
2006-11-17 02:40:35 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2006-11-07 01:03:22 +03:00
2007-12-31 04:14:43 +03:00
/* prepare arguments of EnumDomainUsers call */
2006-11-28 00:55:24 +03:00
s - > user_list . in . domain_handle = & s - > ctx - > samr . handle ;
s - > user_list . in . max_size = s - > page_size ;
s - > user_list . in . resume_handle = & s - > resume_index ;
s - > user_list . in . acct_flags = ACB_NORMAL ;
s - > user_list . out . resume_handle = & s - > resume_index ;
2006-11-09 00:40:11 +03:00
2006-11-30 22:51:58 +03:00
/* send the request */
2006-11-28 00:55:24 +03:00
enum_req = dcerpc_samr_EnumDomainUsers_send ( s - > ctx - > samr . pipe , c , & s - > user_list ) ;
2006-11-07 01:03:22 +03:00
if ( composite_nomem ( enum_req , c ) ) return ;
composite_continue_rpc ( c , enum_req , continue_users_enumerated , c ) ;
}
2006-11-09 00:40:11 +03:00
/*
2006-11-30 22:51:58 +03:00
* Stage 2 : receive enumerated users and their rids
2006-11-09 00:40:11 +03:00
*/
2006-11-07 01:03:22 +03:00
static void continue_users_enumerated ( struct rpc_request * req )
{
struct composite_context * c ;
struct userlist_state * s ;
2006-11-28 00:55:24 +03:00
int i ;
2006-11-07 01:03:22 +03:00
2007-05-16 18:52:54 +04:00
c = talloc_get_type ( req - > async . private_data , struct composite_context ) ;
2006-11-07 01:03:22 +03:00
s = talloc_get_type ( c - > private_data , struct userlist_state ) ;
2006-11-09 00:40:11 +03:00
2006-11-30 22:51:58 +03:00
/* receive result of rpc request */
2006-11-07 01:03:22 +03:00
c - > status = dcerpc_ndr_request_recv ( req ) ;
2006-11-29 00:03:39 +03:00
if ( ! composite_is_ok ( c ) ) return ;
2007-12-31 04:14:43 +03:00
/* get the actual status of the rpc call result
( instead of rpc layer status ) */
2006-11-29 00:03:39 +03:00
c - > status = s - > user_list . out . result ;
2006-11-07 01:03:22 +03:00
2007-12-31 04:14:43 +03:00
/* we're interested in status "ok" as well as two
enum - specific status codes */
2006-11-07 01:03:22 +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 ) ) {
2006-11-09 00:40:11 +03:00
2006-11-30 22:51:58 +03:00
/* get enumerated accounts counter and resume handle (the latter allows
making subsequent call to continue enumeration ) */
2006-11-28 00:55:24 +03:00
s - > resume_index = * s - > user_list . out . resume_handle ;
s - > count = s - > user_list . out . num_entries ;
2006-11-30 22:51:58 +03:00
/* prepare returned user accounts array */
2006-11-28 00:55:24 +03:00
s - > users = talloc_array ( c , struct userlist , s - > user_list . out . sam - > count ) ;
if ( composite_nomem ( s - > users , c ) ) return ;
2006-11-30 22:51:58 +03:00
2006-11-28 00:55:24 +03:00
for ( i = 0 ; i < s - > user_list . out . sam - > count ; i + + ) {
struct dom_sid * user_sid ;
struct samr_SamEntry * entry = & s - > user_list . out . sam - > entries [ i ] ;
struct dom_sid * domain_sid = s - > query_domain . out . info - > domain . sid ;
2006-11-30 22:51:58 +03:00
/* construct user sid from returned rid and queried domain sid */
2006-11-28 00:55:24 +03:00
user_sid = dom_sid_add_rid ( c , domain_sid , entry - > idx ) ;
if ( composite_nomem ( user_sid , c ) ) return ;
2006-11-30 22:51:58 +03:00
/* username */
2006-11-28 00:55:24 +03:00
s - > users [ i ] . username = talloc_strdup ( c , entry - > name . string ) ;
if ( composite_nomem ( s - > users [ i ] . username , c ) ) return ;
2006-11-07 01:03:22 +03:00
2006-11-30 22:51:58 +03:00
/* sid string */
2006-11-28 00:55:24 +03:00
s - > users [ i ] . sid = dom_sid_string ( c , user_sid ) ;
if ( composite_nomem ( s - > users [ i ] . sid , c ) ) return ;
}
2006-11-30 22:51:58 +03:00
/* that's it */
2006-11-28 00:55:24 +03:00
composite_done ( c ) ;
2006-11-09 00:40:11 +03:00
2006-11-28 00:55:24 +03:00
} else {
2006-11-30 22:51:58 +03:00
/* something went wrong */
2006-11-28 00:55:24 +03:00
composite_error ( c , c - > status ) ;
2006-11-07 01:03:22 +03:00
}
}
2006-11-09 00:40:11 +03:00
/**
* Receive result of UserList call
*
* @ param c composite context returned by send request routine
* @ param mem_ctx memory context of this call
2007-12-31 04:14:43 +03:00
* @ param r pointer to structure containing arguments and result of this call
2006-11-09 00:40:11 +03:00
* @ return nt status
*/
2006-11-07 01:03:22 +03:00
NTSTATUS libnet_UserList_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct libnet_UserList * r )
{
NTSTATUS status ;
struct userlist_state * s ;
if ( c = = NULL | | mem_ctx = = NULL | | r = = 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 userlist_state ) ;
2006-11-09 00:40:11 +03:00
/* get results from composite context */
2006-11-28 00:55:24 +03:00
r - > out . count = s - > count ;
r - > out . resume_index = s - > resume_index ;
2006-11-07 01:03:22 +03:00
r - > out . users = talloc_steal ( mem_ctx , s - > users ) ;
2006-11-28 00:55:24 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
r - > out . error_string = talloc_strdup ( mem_ctx , " Success " ) ;
} else {
2006-11-30 22:51:58 +03:00
/* success, but we're not done yet */
2006-11-28 00:55:24 +03:00
r - > out . error_string = talloc_asprintf ( mem_ctx , " Success (status: %s) " ,
nt_errstr ( status ) ) ;
}
2006-11-07 01:03:22 +03:00
} else {
r - > out . error_string = talloc_asprintf ( mem_ctx , " Error: %s " , nt_errstr ( status ) ) ;
}
return status ;
}
2006-11-09 00:40:11 +03:00
/**
* Synchronous version of UserList call
*
* @ param ctx initialised libnet context
* @ param mem_ctx memory context of this call
2007-12-31 04:14:43 +03:00
* @ param r pointer to structure containing arguments and result of this call
2006-11-09 00:40:11 +03:00
* @ return nt status
*/
2006-11-07 01:03:22 +03:00
NTSTATUS libnet_UserList ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_UserList * r )
{
struct composite_context * c ;
c = libnet_UserList_send ( ctx , mem_ctx , r , NULL ) ;
return libnet_UserList_recv ( c , mem_ctx , r ) ;
}