2005-04-19 07:55:58 +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-04-19 07:55:58 +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-04-19 07:55:58 +04:00
*/
/*
a composite functions for user management operations ( add / del / chg )
*/
# include "includes.h"
# include "libcli/composite/composite.h"
2008-12-24 00:11:21 +03:00
# include "libnet/libnet.h"
2006-03-15 02:35:30 +03:00
# include "librpc/gen_ndr/ndr_samr_c.h"
2005-04-19 07:55:58 +04:00
2005-04-21 11:24:16 +04:00
/*
2005-10-02 23:59:24 +04:00
* Composite USER ADD functionality
2005-04-21 11:24:16 +04:00
*/
2005-04-19 07:55:58 +04:00
struct useradd_state {
2014-01-14 15:11:17 +04:00
struct dcerpc_binding_handle * binding_handle ;
2005-04-19 07:55:58 +04:00
struct policy_handle domain_handle ;
struct samr_CreateUser createuser ;
2005-04-19 19:13:18 +04:00
struct policy_handle user_handle ;
uint32_t user_rid ;
2005-10-02 23:59:24 +04:00
2005-09-26 15:47:55 +04:00
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
2005-04-19 07:55:58 +04:00
} ;
2010-03-10 11:43:13 +03:00
static void continue_useradd_create ( struct tevent_req * subreq ) ;
2007-09-26 23:05:51 +04:00
2005-04-19 07:55:58 +04:00
/**
* Stage 1 ( and the only one for now ) : Create user account .
*/
2010-03-10 11:43:13 +03:00
static void continue_useradd_create ( struct tevent_req * subreq )
2005-04-19 07:55:58 +04:00
{
2007-09-26 23:05:51 +04:00
struct composite_context * c ;
struct useradd_state * s ;
2010-03-10 11:43:13 +03:00
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
2007-09-26 23:05:51 +04:00
s = talloc_get_type ( c - > private_data , struct useradd_state ) ;
/* check rpc layer status code */
2010-03-10 11:43:13 +03:00
c - > status = dcerpc_samr_CreateUser_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2007-09-26 23:05:51 +04:00
if ( ! composite_is_ok ( c ) ) return ;
2006-12-13 01:28:33 +03:00
2007-09-26 23:05:51 +04:00
/* check create user call status code */
2006-12-13 01:28:33 +03:00
c - > status = s - > createuser . out . result ;
2005-04-19 07:55:58 +04:00
2007-09-26 23:05:51 +04:00
/* get created user account data */
s - > user_handle = * s - > createuser . out . user_handle ;
s - > user_rid = * s - > createuser . out . rid ;
2005-04-19 07:55:58 +04:00
2007-09-26 23:05:51 +04:00
/* issue a monitor message */
if ( s - > monitor_fn ) {
struct monitor_msg msg ;
struct msg_rpc_create_user rpc_create ;
2005-04-19 07:55:58 +04:00
2007-09-26 23:05:51 +04:00
rpc_create . rid = * s - > createuser . out . rid ;
2005-04-19 07:55:58 +04:00
2007-09-26 23:05:51 +04:00
msg . type = mon_SamrCreateUser ;
msg . data = ( void * ) & rpc_create ;
msg . data_size = sizeof ( rpc_create ) ;
2005-09-26 15:47:55 +04:00
s - > monitor_fn ( & msg ) ;
2005-05-10 17:05:40 +04:00
}
2007-09-26 23:05:51 +04:00
composite_done ( c ) ;
2005-04-19 07:55:58 +04:00
}
/**
* Sends asynchronous useradd request
*
* @ param p dce / rpc call pipe
* @ param io arguments and results of the call
2006-05-20 01:28:28 +04:00
* @ param monitor monitor function for providing information about the progress
2005-04-19 07:55:58 +04:00
*/
2005-04-22 03:25:38 +04:00
2014-01-14 15:11:17 +04:00
struct composite_context * libnet_rpc_useradd_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dcerpc_binding_handle * b ,
2005-07-22 02:32:04 +04:00
struct libnet_rpc_useradd * io ,
void ( * monitor ) ( struct monitor_msg * ) )
2005-04-19 07:55:58 +04:00
{
struct composite_context * c ;
struct useradd_state * s ;
2010-03-10 11:43:13 +03:00
struct tevent_req * subreq ;
2006-05-20 01:28:28 +04:00
2014-01-14 15:11:17 +04:00
if ( ! b | | ! io ) return NULL ;
2007-05-09 02:04:28 +04:00
2006-05-20 01:28:28 +04:00
/* composite allocation and setup */
2014-01-14 15:11:17 +04:00
c = composite_create ( mem_ctx , ev ) ;
2006-05-20 01:28:28 +04:00
if ( c = = NULL ) return NULL ;
2005-04-19 07:55:58 +04:00
s = talloc_zero ( c , struct useradd_state ) ;
2006-05-20 01:28:28 +04:00
if ( composite_nomem ( s , c ) ) return c ;
2005-04-19 07:55:58 +04:00
2005-12-06 22:48:47 +03:00
c - > private_data = s ;
2005-04-19 07:55:58 +04:00
2006-05-20 01:28:28 +04:00
/* put passed arguments to the state structure */
s - > domain_handle = io - > in . domain_handle ;
2014-01-14 15:11:17 +04:00
s - > binding_handle = b ;
2006-05-20 01:28:28 +04:00
s - > monitor_fn = monitor ;
2005-04-19 07:55:58 +04:00
/* preparing parameters to send rpc request */
s - > createuser . in . domain_handle = & io - > in . domain_handle ;
2007-05-09 02:04:28 +04:00
2005-07-08 12:09:02 +04:00
s - > createuser . in . account_name = talloc_zero ( c , struct lsa_String ) ;
2007-05-09 02:04:28 +04:00
if ( composite_nomem ( s - > createuser . in . account_name , c ) ) return c ;
2005-04-19 07:55:58 +04:00
s - > createuser . in . account_name - > string = talloc_strdup ( c , io - > in . username ) ;
2007-05-09 02:04:28 +04:00
if ( composite_nomem ( s - > createuser . in . account_name - > string , c ) ) return c ;
2005-04-19 19:13:18 +04:00
s - > createuser . out . user_handle = & s - > user_handle ;
s - > createuser . out . rid = & s - > user_rid ;
2005-04-19 07:55:58 +04:00
2006-05-20 01:28:28 +04:00
/* send the request */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_CreateUser_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > createuser ) ;
if ( composite_nomem ( subreq , c ) ) return c ;
2005-04-19 07:55:58 +04:00
2010-03-10 11:43:13 +03:00
tevent_req_set_callback ( subreq , continue_useradd_create , c ) ;
2005-04-19 07:55:58 +04:00
return c ;
}
/**
* Waits for and receives result of asynchronous useradd call
*
2005-04-22 03:25:38 +04:00
* @ param c composite context returned by asynchronous useradd call
2005-04-19 07:55:58 +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
*/
2005-06-11 14:31:33 +04:00
NTSTATUS libnet_rpc_useradd_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
2005-09-30 02:34:21 +04:00
struct libnet_rpc_useradd * io )
2005-04-19 07:55:58 +04:00
{
NTSTATUS status ;
struct useradd_state * s ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & io ) {
2005-04-19 19:13:18 +04:00
/* get and return result of the call */
2005-09-26 15:47:55 +04:00
s = talloc_get_type ( c - > private_data , struct useradd_state ) ;
2005-04-19 19:13:18 +04:00
io - > out . user_handle = s - > user_handle ;
2005-04-19 07:55:58 +04:00
}
talloc_free ( c ) ;
return status ;
}
/**
* Synchronous version of useradd call
*
* @ param pipe dce / rpc call pipe
* @ param mem_ctx memory context for the call
* @ param io arguments and results of the call
* @ return nt status code of execution
*/
2014-01-14 15:11:17 +04:00
NTSTATUS libnet_rpc_useradd ( struct tevent_context * ev ,
struct dcerpc_binding_handle * b ,
2005-09-30 02:34:21 +04:00
TALLOC_CTX * mem_ctx ,
struct libnet_rpc_useradd * io )
2005-04-19 07:55:58 +04:00
{
2014-01-14 15:11:17 +04:00
struct composite_context * c = libnet_rpc_useradd_send ( mem_ctx , ev , b , io , NULL ) ;
2005-06-11 14:31:33 +04:00
return libnet_rpc_useradd_recv ( c , mem_ctx , io ) ;
2005-04-19 07:55:58 +04:00
}
2005-04-21 11:24:16 +04:00
2005-10-02 23:59:24 +04:00
2005-04-21 11:24:16 +04:00
/*
2005-10-02 23:59:24 +04:00
* Composite USER DELETE functionality
2005-04-21 11:24:16 +04:00
*/
struct userdel_state {
2014-01-14 15:11:17 +04:00
struct dcerpc_binding_handle * binding_handle ;
2005-04-21 11:24:16 +04:00
struct policy_handle domain_handle ;
struct policy_handle user_handle ;
struct samr_LookupNames lookupname ;
struct samr_OpenUser openuser ;
struct samr_DeleteUser deleteuser ;
2005-10-02 23:59:24 +04:00
2005-09-26 15:47:55 +04:00
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
2005-04-21 11:24:16 +04:00
} ;
2010-03-10 11:43:13 +03:00
static void continue_userdel_name_found ( struct tevent_req * subreq ) ;
static void continue_userdel_user_opened ( struct tevent_req * subreq ) ;
static void continue_userdel_deleted ( struct tevent_req * subreq ) ;
2007-09-26 23:05:51 +04:00
2005-04-22 03:25:38 +04:00
/**
* Stage 1 : Lookup the user name and resolve it to rid
*/
2010-03-10 11:43:13 +03:00
static void continue_userdel_name_found ( struct tevent_req * subreq )
2005-04-21 11:24:16 +04:00
{
2007-09-26 23:05:51 +04:00
struct composite_context * c ;
struct userdel_state * s ;
struct monitor_msg msg ;
2007-09-25 08:24:39 +04:00
2010-03-10 11:43:13 +03:00
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
2007-09-26 23:05:51 +04:00
s = talloc_get_type ( c - > private_data , struct userdel_state ) ;
2007-09-25 09:59:57 +04:00
2007-09-26 23:05:51 +04:00
/* receive samr_LookupNames result */
2010-03-10 11:43:13 +03:00
c - > status = dcerpc_samr_LookupNames_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2007-09-26 23:05:51 +04:00
if ( ! composite_is_ok ( c ) ) return ;
c - > status = s - > lookupname . out . result ;
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
composite_error ( c , c - > status ) ;
return ;
}
2007-06-01 16:29:22 +04:00
2006-05-20 01:28:28 +04:00
/* what to do when there's no user account to delete
and what if there ' s more than one rid resolved */
2013-11-08 09:40:55 +04:00
if ( s - > lookupname . out . rids - > count ! = s - > lookupname . in . num_names ) {
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
2007-09-26 23:05:51 +04:00
return ;
2013-11-08 09:40:55 +04:00
}
if ( s - > lookupname . out . types - > count ! = s - > lookupname . in . num_names ) {
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
2007-09-26 23:05:51 +04:00
return ;
2005-04-21 11:24:16 +04:00
}
2006-05-20 01:28:28 +04:00
2007-09-26 23:05:51 +04:00
/* issue a monitor message */
if ( s - > monitor_fn ) {
struct msg_rpc_lookup_name msg_lookup ;
2008-11-05 16:28:17 +03:00
msg_lookup . rid = s - > lookupname . out . rids - > ids ;
msg_lookup . count = s - > lookupname . out . rids - > count ;
2007-09-26 23:05:51 +04:00
msg . type = mon_SamrLookupName ;
msg . data = ( void * ) & msg_lookup ;
msg . data_size = sizeof ( msg_lookup ) ;
s - > monitor_fn ( & msg ) ;
}
/* prepare the arguments for rpc call */
2005-04-21 11:24:16 +04:00
s - > openuser . in . domain_handle = & s - > domain_handle ;
2008-11-05 16:28:17 +03:00
s - > openuser . in . rid = s - > lookupname . out . rids - > ids [ 0 ] ;
2005-04-21 11:24:16 +04:00
s - > openuser . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
s - > openuser . out . user_handle = & s - > user_handle ;
2006-05-20 01:28:28 +04:00
/* send rpc request */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_OpenUser_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > openuser ) ;
if ( composite_nomem ( subreq , c ) ) return ;
2006-05-20 01:28:28 +04:00
2010-03-10 11:43:13 +03:00
tevent_req_set_callback ( subreq , continue_userdel_user_opened , c ) ;
2005-04-21 11:24:16 +04:00
}
2005-04-22 03:25:38 +04:00
/**
* Stage 2 : Open user account .
*/
2010-03-10 11:43:13 +03:00
static void continue_userdel_user_opened ( struct tevent_req * subreq )
2005-04-21 11:24:16 +04:00
{
2007-09-26 23:05:51 +04:00
struct composite_context * c ;
struct userdel_state * s ;
struct monitor_msg msg ;
2010-03-10 11:43:13 +03:00
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
2007-09-26 23:05:51 +04:00
s = talloc_get_type ( c - > private_data , struct userdel_state ) ;
2006-05-20 01:28:28 +04:00
/* receive samr_OpenUser result */
2010-03-10 11:43:13 +03:00
c - > status = dcerpc_samr_OpenUser_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2007-09-26 23:05:51 +04:00
if ( ! composite_is_ok ( c ) ) return ;
c - > status = s - > openuser . out . result ;
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
composite_error ( c , c - > status ) ;
return ;
}
/* issue a monitor message */
if ( s - > monitor_fn ) {
struct msg_rpc_open_user msg_open ;
msg_open . rid = s - > openuser . in . rid ;
msg_open . access_mask = s - > openuser . in . access_mask ;
msg . type = mon_SamrOpenUser ;
msg . data = ( void * ) & msg_open ;
msg . data_size = sizeof ( msg_open ) ;
s - > monitor_fn ( & msg ) ;
}
2006-05-20 01:28:28 +04:00
/* prepare the final rpc call arguments */
2005-04-21 11:24:16 +04:00
s - > deleteuser . in . user_handle = & s - > user_handle ;
s - > deleteuser . out . user_handle = & s - > user_handle ;
2006-05-20 01:28:28 +04:00
/* send rpc request */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_DeleteUser_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > deleteuser ) ;
if ( composite_nomem ( subreq , c ) ) return ;
2006-05-20 01:28:28 +04:00
/* callback handler setup */
2010-03-10 11:43:13 +03:00
tevent_req_set_callback ( subreq , continue_userdel_deleted , c ) ;
2005-04-21 11:24:16 +04:00
}
2005-04-22 03:25:38 +04:00
/**
* Stage 3 : Delete user account
*/
2010-03-10 11:43:13 +03:00
static void continue_userdel_deleted ( struct tevent_req * subreq )
2005-04-21 11:24:16 +04:00
{
2006-05-20 01:28:28 +04:00
struct composite_context * c ;
struct userdel_state * s ;
2005-07-22 21:45:42 +04:00
struct monitor_msg msg ;
2006-05-20 01:28:28 +04:00
2010-03-10 11:43:13 +03:00
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
2006-05-20 01:28:28 +04:00
s = talloc_get_type ( c - > private_data , struct userdel_state ) ;
2005-04-21 11:24:16 +04:00
2007-09-26 23:05:51 +04:00
/* receive samr_DeleteUser result */
2010-03-10 11:43:13 +03:00
c - > status = dcerpc_samr_DeleteUser_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2007-09-26 23:05:51 +04:00
if ( ! composite_is_ok ( c ) ) return ;
/* return the actual function call status */
c - > status = s - > deleteuser . out . result ;
2005-04-21 11:24:16 +04:00
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2007-09-26 23:05:51 +04:00
composite_error ( c , c - > status ) ;
return ;
2005-04-21 11:24:16 +04:00
}
2007-09-26 23:05:51 +04:00
/* issue a monitor message */
2005-09-26 15:47:55 +04:00
if ( s - > monitor_fn ) {
2007-09-26 23:05:51 +04:00
msg . type = mon_SamrDeleteUser ;
msg . data = NULL ;
msg . data_size = 0 ;
2005-09-26 15:47:55 +04:00
s - > monitor_fn ( & msg ) ;
2005-07-22 21:45:42 +04:00
}
2007-09-26 23:05:51 +04:00
composite_done ( c ) ;
2005-04-21 11:24:16 +04:00
}
2005-04-22 03:25:38 +04:00
/**
* Sends asynchronous userdel request
*
* @ param p dce / rpc call pipe
* @ param io arguments and results of the call
2006-05-20 01:28:28 +04:00
* @ param monitor monitor function for providing information about the progress
2005-04-22 03:25:38 +04:00
*/
2014-01-14 15:11:17 +04:00
struct composite_context * libnet_rpc_userdel_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dcerpc_binding_handle * b ,
2006-05-18 01:41:59 +04:00
struct libnet_rpc_userdel * io ,
void ( * monitor ) ( struct monitor_msg * ) )
2005-04-21 11:24:16 +04:00
{
struct composite_context * c ;
struct userdel_state * s ;
2010-03-10 11:43:13 +03:00
struct tevent_req * subreq ;
2006-05-20 01:28:28 +04:00
/* composite context allocation and setup */
2014-01-14 15:11:17 +04:00
c = composite_create ( mem_ctx , ev ) ;
2006-05-20 01:28:28 +04:00
if ( c = = NULL ) return NULL ;
2005-04-21 11:24:16 +04:00
s = talloc_zero ( c , struct userdel_state ) ;
2006-05-20 01:28:28 +04:00
if ( composite_nomem ( s , c ) ) return c ;
2005-04-21 11:24:16 +04:00
2005-10-02 23:59:24 +04:00
c - > private_data = s ;
2005-04-21 11:24:16 +04:00
2006-05-20 01:28:28 +04:00
/* store function parameters in the state structure */
2014-01-14 15:11:17 +04:00
s - > binding_handle = b ;
2005-04-21 16:21:14 +04:00
s - > domain_handle = io - > in . domain_handle ;
2006-05-20 01:28:28 +04:00
s - > monitor_fn = monitor ;
2005-04-22 03:25:38 +04:00
/* preparing parameters to send rpc request */
2005-04-21 11:24:16 +04:00
s - > lookupname . in . domain_handle = & io - > in . domain_handle ;
s - > lookupname . in . num_names = 1 ;
2005-07-08 12:09:02 +04:00
s - > lookupname . in . names = talloc_zero ( s , struct lsa_String ) ;
2005-04-21 11:24:16 +04:00
s - > lookupname . in . names - > string = io - > in . username ;
2008-11-05 16:28:17 +03:00
s - > lookupname . out . rids = talloc_zero ( s , struct samr_Ids ) ;
s - > lookupname . out . types = talloc_zero ( s , struct samr_Ids ) ;
if ( composite_nomem ( s - > lookupname . out . rids , c ) ) return c ;
if ( composite_nomem ( s - > lookupname . out . types , c ) ) return c ;
2005-04-21 11:24:16 +04:00
2005-04-22 03:25:38 +04:00
/* send the request */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_LookupNames_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > lookupname ) ;
if ( composite_nomem ( subreq , c ) ) return c ;
2005-04-21 11:24:16 +04:00
2007-09-26 23:05:51 +04:00
/* set the next stage */
2010-03-10 11:43:13 +03:00
tevent_req_set_callback ( subreq , continue_userdel_name_found , c ) ;
2005-04-21 11:24:16 +04:00
return c ;
}
2005-04-22 03:25:38 +04:00
/**
2005-10-02 23:59:24 +04:00
* Waits for and receives results of asynchronous userdel call
2005-04-22 03:25:38 +04:00
*
* @ param c composite context returned by asynchronous userdel call
* @ param mem_ctx memory context of the call
* @ param io pointer to results ( and arguments ) of the call
* @ return nt status code of execution
*/
2005-06-11 14:31:33 +04:00
NTSTATUS libnet_rpc_userdel_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
2005-07-22 02:32:04 +04:00
struct libnet_rpc_userdel * io )
2005-04-21 11:24:16 +04:00
{
NTSTATUS status ;
struct userdel_state * s ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & io ) {
2005-09-26 15:47:55 +04:00
s = talloc_get_type ( c - > private_data , struct userdel_state ) ;
2005-04-21 11:24:16 +04:00
io - > out . user_handle = s - > user_handle ;
}
talloc_free ( c ) ;
return status ;
}
2005-04-22 04:22:11 +04:00
/**
* Synchronous version of userdel call
*
* @ param pipe dce / rpc call pipe
* @ param mem_ctx memory context for the call
* @ param io arguments and results of the call
* @ return nt status code of execution
*/
2014-01-14 15:11:17 +04:00
NTSTATUS libnet_rpc_userdel ( struct tevent_context * ev ,
struct dcerpc_binding_handle * b ,
2005-07-22 02:32:04 +04:00
TALLOC_CTX * mem_ctx ,
struct libnet_rpc_userdel * io )
2005-04-21 11:24:16 +04:00
{
2014-01-14 15:11:17 +04:00
struct composite_context * c = libnet_rpc_userdel_send ( mem_ctx , ev , b , io , NULL ) ;
2005-06-11 14:31:33 +04:00
return libnet_rpc_userdel_recv ( c , mem_ctx , io ) ;
2005-04-21 11:24:16 +04:00
}
2005-07-22 02:32:04 +04:00
2005-10-02 23:59:24 +04:00
/*
* USER MODIFY functionality
*/
2010-03-10 11:43:13 +03:00
static void continue_usermod_name_found ( struct tevent_req * subreq ) ;
static void continue_usermod_user_opened ( struct tevent_req * subreq ) ;
static void continue_usermod_user_queried ( struct tevent_req * subreq ) ;
static void continue_usermod_user_changed ( struct tevent_req * subreq ) ;
2005-07-22 02:32:04 +04:00
struct usermod_state {
2014-01-14 15:11:17 +04:00
struct dcerpc_binding_handle * binding_handle ;
2005-08-02 00:47:26 +04:00
struct policy_handle domain_handle ;
struct policy_handle user_handle ;
struct usermod_change change ;
union samr_UserInfo info ;
struct samr_LookupNames lookupname ;
struct samr_OpenUser openuser ;
struct samr_SetUserInfo setuser ;
struct samr_QueryUserInfo queryuser ;
2005-10-02 23:59:24 +04:00
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
2005-07-22 02:32:04 +04:00
} ;
2005-07-28 01:59:16 +04:00
/**
* Step 1 : Lookup user name
*/
2010-03-10 11:43:13 +03:00
static void continue_usermod_name_found ( struct tevent_req * subreq )
2005-07-22 02:32:04 +04:00
{
2007-09-26 23:05:51 +04:00
struct composite_context * c ;
struct usermod_state * s ;
struct monitor_msg msg ;
2010-03-10 11:43:13 +03:00
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
2007-09-26 23:05:51 +04:00
s = talloc_get_type ( c - > private_data , struct usermod_state ) ;
2006-05-20 01:28:28 +04:00
/* receive samr_LookupNames result */
2010-03-10 11:43:13 +03:00
c - > status = dcerpc_samr_LookupNames_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2007-09-26 23:05:51 +04:00
if ( ! composite_is_ok ( c ) ) return ;
c - > status = s - > lookupname . out . result ;
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
composite_error ( c , c - > status ) ;
return ;
}
2005-07-22 02:32:04 +04:00
2006-05-20 01:28:28 +04:00
/* what to do when there's no user account to delete
and what if there ' s more than one rid resolved */
2013-11-08 09:40:55 +04:00
if ( s - > lookupname . out . rids - > count ! = s - > lookupname . in . num_names ) {
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
2007-09-26 23:05:51 +04:00
return ;
2013-11-08 09:40:55 +04:00
}
if ( s - > lookupname . out . types - > count ! = s - > lookupname . in . num_names ) {
composite_error ( c , NT_STATUS_INVALID_NETWORK_RESPONSE ) ;
2007-09-26 23:05:51 +04:00
return ;
}
/* issue a monitor message */
if ( s - > monitor_fn ) {
struct msg_rpc_lookup_name msg_lookup ;
2008-11-05 16:28:17 +03:00
msg_lookup . rid = s - > lookupname . out . rids - > ids ;
msg_lookup . count = s - > lookupname . out . rids - > count ;
2007-09-26 23:05:51 +04:00
msg . type = mon_SamrLookupName ;
msg . data = ( void * ) & msg_lookup ;
msg . data_size = sizeof ( msg_lookup ) ;
s - > monitor_fn ( & msg ) ;
2005-07-22 02:32:04 +04:00
}
2006-05-20 01:28:28 +04:00
/* prepare the next rpc call */
2005-07-22 02:32:04 +04:00
s - > openuser . in . domain_handle = & s - > domain_handle ;
2008-11-05 16:28:17 +03:00
s - > openuser . in . rid = s - > lookupname . out . rids - > ids [ 0 ] ;
2005-07-22 02:32:04 +04:00
s - > openuser . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
s - > openuser . out . user_handle = & s - > user_handle ;
2006-05-20 01:28:28 +04:00
/* send the rpc request */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_OpenUser_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > openuser ) ;
if ( composite_nomem ( subreq , c ) ) return ;
2005-07-22 02:32:04 +04:00
2010-03-10 11:43:13 +03:00
tevent_req_set_callback ( subreq , continue_usermod_user_opened , c ) ;
2005-07-22 02:32:04 +04:00
}
2006-05-20 01:28:28 +04:00
/**
* Choose a proper level of samr_UserInfo structure depending on required
* change specified by means of flags field . Subsequent calls of this
* function are made until there ' s no flags set meaning that all of the
* changes have been made .
*/
2007-09-26 23:05:51 +04:00
static bool usermod_setfields ( struct usermod_state * s , uint16_t * level ,
union samr_UserInfo * i , bool queried )
2005-07-22 02:32:04 +04:00
{
2006-09-19 23:10:14 +04:00
if ( s - > change . fields = = 0 ) return s - > change . fields ;
2005-07-26 02:00:56 +04:00
2006-09-21 03:39:15 +04:00
* level = 0 ;
if ( ( s - > change . fields & USERMOD_FIELD_ACCOUNT_NAME ) & &
( * level = = 0 | | * level = = 7 ) ) {
2006-09-19 23:10:14 +04:00
* level = 7 ;
i - > info7 . account_name . string = s - > change . account_name ;
s - > change . fields ^ = USERMOD_FIELD_ACCOUNT_NAME ;
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_FULL_NAME ) & &
( * level = = 0 | | * level = = 8 ) ) {
2006-09-19 23:10:14 +04:00
* level = 8 ;
i - > info8 . full_name . string = s - > change . full_name ;
s - > change . fields ^ = USERMOD_FIELD_FULL_NAME ;
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_DESCRIPTION ) & &
( * level = = 0 | | * level = = 13 ) ) {
2006-09-19 23:10:14 +04:00
* level = 13 ;
i - > info13 . description . string = s - > change . description ;
2006-10-02 09:53:45 +04:00
s - > change . fields ^ = USERMOD_FIELD_DESCRIPTION ;
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_COMMENT ) & &
( * level = = 0 | | * level = = 2 ) ) {
2006-09-19 23:10:14 +04:00
* level = 2 ;
2007-09-26 23:05:51 +04:00
if ( queried ) {
2006-09-19 23:10:14 +04:00
/* the user info is obtained, so now set the required field */
i - > info2 . comment . string = s - > change . comment ;
s - > change . fields ^ = USERMOD_FIELD_COMMENT ;
2005-07-26 02:00:56 +04:00
2006-09-19 23:10:14 +04:00
} else {
/* we need to query the user info before setting one field in it */
2007-09-26 23:05:51 +04:00
return false ;
2006-09-19 23:10:14 +04:00
}
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_LOGON_SCRIPT ) & &
( * level = = 0 | | * level = = 11 ) ) {
2006-09-19 23:10:14 +04:00
* level = 11 ;
i - > info11 . logon_script . string = s - > change . logon_script ;
s - > change . fields ^ = USERMOD_FIELD_LOGON_SCRIPT ;
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_PROFILE_PATH ) & &
( * level = = 0 | | * level = = 12 ) ) {
2006-09-19 23:10:14 +04:00
* level = 12 ;
i - > info12 . profile_path . string = s - > change . profile_path ;
s - > change . fields ^ = USERMOD_FIELD_PROFILE_PATH ;
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_HOME_DIRECTORY ) & &
2006-10-02 09:53:45 +04:00
( * level = = 0 | | * level = = 10 ) ) {
* level = 10 ;
2006-09-19 23:10:14 +04:00
2007-09-26 23:05:51 +04:00
if ( queried ) {
2006-10-02 09:53:45 +04:00
i - > info10 . home_directory . string = s - > change . home_directory ;
2006-09-19 23:10:14 +04:00
s - > change . fields ^ = USERMOD_FIELD_HOME_DIRECTORY ;
} else {
2007-09-26 23:05:51 +04:00
return false ;
2006-09-19 23:10:14 +04:00
}
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_HOME_DRIVE ) & &
2006-10-02 09:53:45 +04:00
( * level = = 0 | | * level = = 10 ) ) {
* level = 10 ;
2006-09-19 23:10:14 +04:00
2007-09-26 23:05:51 +04:00
if ( queried ) {
2006-10-02 09:53:45 +04:00
i - > info10 . home_drive . string = s - > change . home_drive ;
2006-09-19 23:10:14 +04:00
s - > change . fields ^ = USERMOD_FIELD_HOME_DRIVE ;
} else {
2007-09-26 23:05:51 +04:00
return false ;
2005-07-23 14:27:45 +04:00
}
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_ACCT_EXPIRY ) & &
( * level = = 0 | | * level = = 17 ) ) {
2006-09-19 23:10:14 +04:00
* level = 17 ;
i - > info17 . acct_expiry = timeval_to_nttime ( s - > change . acct_expiry ) ;
s - > change . fields ^ = USERMOD_FIELD_ACCT_EXPIRY ;
2006-09-21 03:39:15 +04:00
}
if ( ( s - > change . fields & USERMOD_FIELD_ACCT_FLAGS ) & &
( * level = = 0 | | * level = = 16 ) ) {
2006-09-19 23:10:14 +04:00
* level = 16 ;
i - > info16 . acct_flags = s - > change . acct_flags ;
s - > change . fields ^ = USERMOD_FIELD_ACCT_FLAGS ;
2005-07-23 14:27:45 +04:00
}
2006-09-19 04:23:55 +04:00
/* We're going to be here back again soon unless all fields have been set */
2007-09-26 23:05:51 +04:00
return true ;
2005-08-02 00:47:26 +04:00
}
2006-09-21 03:39:15 +04:00
static NTSTATUS usermod_change ( struct composite_context * c ,
struct usermod_state * s )
2005-08-02 00:47:26 +04:00
{
2007-09-26 23:05:51 +04:00
bool do_set ;
2005-08-02 00:47:26 +04:00
union samr_UserInfo * i = & s - > info ;
2010-03-10 11:43:13 +03:00
struct tevent_req * subreq ;
2006-09-21 03:39:15 +04:00
2006-09-19 04:23:55 +04:00
/* set the level to invalid value, so that unless setfields routine
gives it a valid value we report the error correctly */
uint16_t level = 27 ;
2005-08-02 00:47:26 +04:00
2006-05-20 01:28:28 +04:00
/* prepare UserInfo level and data based on bitmask field */
2007-10-07 02:28:14 +04:00
do_set = usermod_setfields ( s , & level , i , false ) ;
2005-08-02 00:47:26 +04:00
2006-09-21 03:39:15 +04:00
if ( level < 1 | | level > 26 ) {
2006-09-19 04:23:55 +04:00
/* apparently there's a field that the setfields routine
does not know how to set */
return NT_STATUS_INVALID_PARAMETER ;
}
2006-05-20 01:28:28 +04:00
/* If some specific level is used to set user account data and the change
itself does not cover all fields then we need to query the user info
first , right before changing the data . Otherwise we could set required
fields and accidentally reset the others .
*/
2007-09-26 23:05:51 +04:00
if ( ! do_set ) {
2005-08-02 00:47:26 +04:00
s - > queryuser . in . user_handle = & s - > user_handle ;
s - > queryuser . in . level = level ;
2008-11-10 16:42:27 +03:00
s - > queryuser . out . info = talloc ( s , union samr_UserInfo * ) ;
2008-12-24 00:11:21 +03:00
if ( composite_nomem ( s - > queryuser . out . info , c ) ) return NT_STATUS_NO_MEMORY ;
2008-11-10 16:42:27 +03:00
2005-08-02 00:47:26 +04:00
2006-05-20 01:28:28 +04:00
/* send query user info request to retrieve complete data of
a particular info level */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_QueryUserInfo_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > queryuser ) ;
if ( composite_nomem ( subreq , c ) ) return NT_STATUS_NO_MEMORY ;
tevent_req_set_callback ( subreq , continue_usermod_user_queried , c ) ;
2005-08-02 00:47:26 +04:00
} else {
s - > setuser . in . user_handle = & s - > user_handle ;
s - > setuser . in . level = level ;
s - > setuser . in . info = i ;
2006-05-20 01:28:28 +04:00
/* send set user info request after making required change */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_SetUserInfo_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > setuser ) ;
if ( composite_nomem ( subreq , c ) ) return NT_STATUS_NO_MEMORY ;
tevent_req_set_callback ( subreq , continue_usermod_user_changed , c ) ;
2005-08-02 00:47:26 +04:00
}
2007-09-26 23:05:51 +04:00
2005-07-22 02:32:04 +04:00
return NT_STATUS_OK ;
}
2006-09-21 03:39:15 +04:00
/**
* Stage 2 : Open user account
*/
2010-03-10 11:43:13 +03:00
static void continue_usermod_user_opened ( struct tevent_req * subreq )
2006-09-21 03:39:15 +04:00
{
2007-09-26 23:05:51 +04:00
struct composite_context * c ;
struct usermod_state * s ;
2010-03-10 11:43:13 +03:00
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
2007-09-26 23:05:51 +04:00
s = talloc_get_type ( c - > private_data , struct usermod_state ) ;
2010-03-10 11:43:13 +03:00
c - > status = dcerpc_samr_OpenUser_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2007-09-26 23:05:51 +04:00
if ( ! composite_is_ok ( c ) ) return ;
c - > status = s - > openuser . out . result ;
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
composite_error ( c , c - > status ) ;
return ;
}
c - > status = usermod_change ( c , s ) ;
2006-09-21 03:39:15 +04:00
}
2005-08-02 05:12:58 +04:00
/**
* Stage 2 a ( optional ) : Query the user information
*/
2010-03-10 11:43:13 +03:00
static void continue_usermod_user_queried ( struct tevent_req * subreq )
2005-08-02 05:12:58 +04:00
{
2007-09-26 23:05:51 +04:00
struct composite_context * c ;
struct usermod_state * s ;
union samr_UserInfo * i ;
2015-03-03 10:48:00 +03:00
uint16_t level = 0 ;
2007-09-26 23:05:51 +04:00
2010-03-10 11:43:13 +03:00
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
2007-09-26 23:05:51 +04:00
s = talloc_get_type ( c - > private_data , struct usermod_state ) ;
i = & s - > info ;
2005-08-02 05:12:58 +04:00
2006-05-20 01:28:28 +04:00
/* receive samr_QueryUserInfo result */
2010-03-10 11:43:13 +03:00
c - > status = dcerpc_samr_QueryUserInfo_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2007-09-26 23:05:51 +04:00
if ( ! composite_is_ok ( c ) ) return ;
c - > status = s - > queryuser . out . result ;
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
composite_error ( c , c - > status ) ;
return ;
}
2005-08-02 05:12:58 +04:00
2006-05-20 01:28:28 +04:00
/* get returned user data and make a change (potentially one
of many ) */
2008-11-10 16:42:27 +03:00
s - > info = * ( * s - > queryuser . out . info ) ;
2005-08-02 05:12:58 +04:00
2007-10-07 02:28:14 +04:00
usermod_setfields ( s , & level , i , true ) ;
2005-08-02 05:12:58 +04:00
2006-05-20 01:28:28 +04:00
/* prepare rpc call arguments */
2005-08-02 05:12:58 +04:00
s - > setuser . in . user_handle = & s - > user_handle ;
s - > setuser . in . level = level ;
s - > setuser . in . info = i ;
2006-05-20 01:28:28 +04:00
/* send the rpc request */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_SetUserInfo_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > setuser ) ;
if ( composite_nomem ( subreq , c ) ) return ;
tevent_req_set_callback ( subreq , continue_usermod_user_changed , c ) ;
2005-08-02 05:12:58 +04:00
}
2005-07-28 01:59:16 +04:00
/**
* Stage 3 : Set new user account data
*/
2010-03-10 11:43:13 +03:00
static void continue_usermod_user_changed ( struct tevent_req * subreq )
2005-07-22 02:32:04 +04:00
{
2006-05-20 01:28:28 +04:00
struct composite_context * c ;
struct usermod_state * s ;
2007-09-26 23:05:51 +04:00
2010-03-10 11:43:13 +03:00
c = tevent_req_callback_data ( subreq , struct composite_context ) ;
2006-05-20 01:28:28 +04:00
s = talloc_get_type ( c - > private_data , struct usermod_state ) ;
2007-09-26 23:05:51 +04:00
/* receive samr_SetUserInfo result */
2010-03-10 11:43:13 +03:00
c - > status = dcerpc_samr_SetUserInfo_r_recv ( subreq , s ) ;
TALLOC_FREE ( subreq ) ;
2007-09-26 23:05:51 +04:00
if ( ! composite_is_ok ( c ) ) return ;
2007-09-25 09:59:57 +04:00
2007-09-26 23:05:51 +04:00
/* return the actual function call status */
c - > status = s - > setuser . out . result ;
2005-07-22 02:32:04 +04:00
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2007-09-26 23:05:51 +04:00
composite_error ( c , c - > status ) ;
return ;
2005-07-22 21:45:42 +04:00
}
2007-09-26 23:05:51 +04:00
if ( s - > change . fields = = 0 ) {
/* all fields have been set - we're done */
composite_done ( c ) ;
2005-10-02 23:59:24 +04:00
2007-09-26 23:05:51 +04:00
} else {
/* something's still not changed - repeat the procedure */
c - > status = usermod_change ( c , s ) ;
2005-07-22 02:32:04 +04:00
}
}
2005-07-28 01:59:16 +04:00
/**
* Sends asynchronous usermod request
*
* @ param p dce / rpc call pipe
* @ param io arguments and results of the call
2006-05-20 01:28:28 +04:00
* @ param monitor monitor function for providing information about the progress
2005-07-28 01:59:16 +04:00
*/
2014-01-14 15:11:17 +04:00
struct composite_context * libnet_rpc_usermod_send ( TALLOC_CTX * mem_ctx ,
struct tevent_context * ev ,
struct dcerpc_binding_handle * b ,
2006-05-20 01:28:28 +04:00
struct libnet_rpc_usermod * io ,
void ( * monitor ) ( struct monitor_msg * ) )
2005-07-22 02:32:04 +04:00
{
struct composite_context * c ;
struct usermod_state * s ;
2010-03-10 11:43:13 +03:00
struct tevent_req * subreq ;
2006-05-20 01:28:28 +04:00
/* composite context allocation and setup */
2014-01-14 15:11:17 +04:00
c = composite_create ( mem_ctx , ev ) ;
2006-05-20 01:28:28 +04:00
if ( c = = NULL ) return NULL ;
2005-07-22 02:32:04 +04:00
s = talloc_zero ( c , struct usermod_state ) ;
2006-05-20 01:28:28 +04:00
if ( composite_nomem ( s , c ) ) return c ;
2005-07-22 02:32:04 +04:00
2005-09-26 15:47:55 +04:00
c - > private_data = s ;
2005-07-22 02:32:04 +04:00
2006-05-20 01:28:28 +04:00
/* store parameters in the call structure */
2014-01-14 15:11:17 +04:00
s - > binding_handle = b ;
2005-07-22 02:32:04 +04:00
s - > domain_handle = io - > in . domain_handle ;
2005-07-23 14:27:45 +04:00
s - > change = io - > in . change ;
2006-05-20 01:28:28 +04:00
s - > monitor_fn = monitor ;
2005-07-22 02:32:04 +04:00
2006-05-20 01:28:28 +04:00
/* prepare rpc call arguments */
2005-07-22 02:32:04 +04:00
s - > lookupname . in . domain_handle = & io - > in . domain_handle ;
s - > lookupname . in . num_names = 1 ;
s - > lookupname . in . names = talloc_zero ( s , struct lsa_String ) ;
s - > lookupname . in . names - > string = io - > in . username ;
2008-11-05 16:28:17 +03:00
s - > lookupname . out . rids = talloc_zero ( s , struct samr_Ids ) ;
s - > lookupname . out . types = talloc_zero ( s , struct samr_Ids ) ;
if ( composite_nomem ( s - > lookupname . out . rids , c ) ) return c ;
if ( composite_nomem ( s - > lookupname . out . types , c ) ) return c ;
2006-05-20 01:28:28 +04:00
/* send the rpc request */
2010-03-10 11:43:13 +03:00
subreq = dcerpc_samr_LookupNames_r_send ( s , c - > event_ctx ,
2014-01-14 15:11:17 +04:00
s - > binding_handle ,
2010-03-10 11:43:13 +03:00
& s - > lookupname ) ;
if ( composite_nomem ( subreq , c ) ) return c ;
2005-07-22 02:32:04 +04:00
2006-05-20 01:28:28 +04:00
/* callback handler setup */
2010-03-10 11:43:13 +03:00
tevent_req_set_callback ( subreq , continue_usermod_name_found , c ) ;
2005-07-22 02:32:04 +04:00
return c ;
}
2005-07-28 01:59:16 +04:00
/**
* Waits for and receives results of asynchronous usermod call
*
* @ param c composite context returned by asynchronous usermod call
* @ param mem_ctx memory context of the call
* @ param io pointer to results ( and arguments ) of the call
* @ return nt status code of execution
*/
2005-07-22 02:32:04 +04:00
NTSTATUS libnet_rpc_usermod_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct libnet_rpc_usermod * io )
{
NTSTATUS status ;
status = composite_wait ( c ) ;
talloc_free ( c ) ;
return status ;
}
2005-07-28 01:59:16 +04:00
/**
* Synchronous version of usermod call
*
* @ param pipe dce / rpc call pipe
* @ param mem_ctx memory context for the call
* @ param io arguments and results of the call
* @ return nt status code of execution
*/
2014-01-14 15:11:17 +04:00
NTSTATUS libnet_rpc_usermod ( struct tevent_context * ev ,
struct dcerpc_binding_handle * b ,
2005-07-22 02:32:04 +04:00
TALLOC_CTX * mem_ctx ,
struct libnet_rpc_usermod * io )
{
2014-01-14 15:11:17 +04:00
struct composite_context * c = libnet_rpc_usermod_send ( mem_ctx , ev , b , io , NULL ) ;
2005-07-22 02:32:04 +04:00
return libnet_rpc_usermod_recv ( c , mem_ctx , io ) ;
}