2005-04-19 03:55:58 +00: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
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
a composite functions for user management operations ( add / del / chg )
*/
# include "includes.h"
# include "libcli/composite/composite.h"
# include "libnet/composite.h"
2005-07-25 22:57:14 +00:00
# include "libnet/userman.h"
2005-07-26 23:03:37 +00:00
# include "libnet/userinfo.h"
2006-03-14 23:35:30 +00:00
# include "librpc/gen_ndr/ndr_samr_c.h"
2005-04-19 03:55:58 +00:00
2005-04-21 07:24:16 +00:00
/*
2005-10-02 19:59:24 +00:00
* Composite USER ADD functionality
2005-04-21 07:24:16 +00:00
*/
static void useradd_handler ( struct rpc_request * ) ;
2005-04-19 03:55:58 +00:00
enum useradd_stage { USERADD_CREATE } ;
struct useradd_state {
enum useradd_stage stage ;
struct dcerpc_pipe * pipe ;
struct rpc_request * req ;
struct policy_handle domain_handle ;
struct samr_CreateUser createuser ;
2005-04-19 15:13:18 +00:00
struct policy_handle user_handle ;
uint32_t user_rid ;
2005-10-02 19:59:24 +00:00
2005-09-26 11:47:55 +00:00
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
2005-04-19 03:55:58 +00:00
} ;
/**
* Stage 1 ( and the only one for now ) : Create user account .
*/
static NTSTATUS useradd_create ( struct composite_context * c ,
struct useradd_state * s )
{
c - > status = dcerpc_ndr_request_recv ( s - > req ) ;
NT_STATUS_NOT_OK_RETURN ( c - > status ) ;
2006-12-12 22:28:33 +00:00
/* return the actual function call status */
c - > status = s - > createuser . out . result ;
2005-04-19 03:55:58 +00:00
2005-09-26 11:47:55 +00:00
c - > state = COMPOSITE_STATE_DONE ;
2006-12-12 22:28:33 +00:00
return c - > status ;
2005-04-19 03:55:58 +00:00
}
/**
* Event handler for asynchronous request . Handles transition through
* intermediate stages of the call .
*
* @ param req rpc call context
*/
static void useradd_handler ( struct rpc_request * req )
{
struct composite_context * c = req - > async . private ;
2005-09-26 11:47:55 +00:00
struct useradd_state * s = talloc_get_type ( c - > private_data , struct useradd_state ) ;
2005-05-10 13:05:40 +00:00
struct monitor_msg msg ;
2005-07-25 22:57:14 +00:00
struct msg_rpc_create_user * rpc_create ;
2005-04-19 03:55:58 +00:00
switch ( s - > stage ) {
case USERADD_CREATE :
c - > status = useradd_create ( c , s ) ;
2006-05-19 21:28:28 +00:00
/* prepare a message to pass to monitor function */
2005-05-10 13:05:40 +00:00
msg . type = rpc_create_user ;
2005-07-25 22:57:14 +00:00
rpc_create = talloc ( s , struct msg_rpc_create_user ) ;
rpc_create - > rid = * s - > createuser . out . rid ;
msg . data = ( void * ) rpc_create ;
msg . data_size = sizeof ( * rpc_create ) ;
2005-04-19 03:55:58 +00:00
break ;
}
2006-05-19 21:28:28 +00:00
/* are we ok so far ? */
2005-04-19 03:55:58 +00:00
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2005-09-26 11:47:55 +00:00
c - > state = COMPOSITE_STATE_ERROR ;
2005-04-19 03:55:58 +00:00
}
2006-05-19 21:28:28 +00:00
/* call monitor function provided the pointer has been passed */
2005-09-26 11:47:55 +00:00
if ( s - > monitor_fn ) {
s - > monitor_fn ( & msg ) ;
2005-05-10 13:05:40 +00:00
}
2006-05-19 21:28:28 +00:00
/* are we done yet ? */
2005-09-26 11:47:55 +00:00
if ( c - > state > = COMPOSITE_STATE_DONE & &
2005-04-19 03:55:58 +00:00
c - > async . fn ) {
c - > async . fn ( c ) ;
}
}
/**
* Sends asynchronous useradd request
*
* @ param p dce / rpc call pipe
* @ param io arguments and results of the call
2006-05-19 21:28:28 +00:00
* @ param monitor monitor function for providing information about the progress
2005-04-19 03:55:58 +00:00
*/
2005-04-21 23:25:38 +00:00
2005-06-11 10:31:33 +00:00
struct composite_context * libnet_rpc_useradd_send ( struct dcerpc_pipe * p ,
2005-07-21 22:32:04 +00:00
struct libnet_rpc_useradd * io ,
void ( * monitor ) ( struct monitor_msg * ) )
2005-04-19 03:55:58 +00:00
{
struct composite_context * c ;
struct useradd_state * s ;
2006-05-19 21:28:28 +00:00
/* composite allocation and setup */
2005-04-19 03:55:58 +00:00
c = talloc_zero ( p , struct composite_context ) ;
2006-05-19 21:28:28 +00:00
if ( c = = NULL ) return NULL ;
2005-04-19 03:55:58 +00:00
s = talloc_zero ( c , struct useradd_state ) ;
2006-05-19 21:28:28 +00:00
if ( composite_nomem ( s , c ) ) return c ;
2005-04-19 03:55:58 +00:00
2005-12-06 19:48:47 +00:00
c - > state = COMPOSITE_STATE_IN_PROGRESS ;
c - > private_data = s ;
c - > event_ctx = dcerpc_event_context ( p ) ;
2005-04-19 03:55:58 +00:00
2006-05-19 21:28:28 +00:00
/* put passed arguments to the state structure */
s - > domain_handle = io - > in . domain_handle ;
s - > pipe = p ;
s - > monitor_fn = monitor ;
2005-04-19 03:55:58 +00:00
/* preparing parameters to send rpc request */
s - > createuser . in . domain_handle = & io - > in . domain_handle ;
2005-07-08 08:09:02 +00:00
s - > createuser . in . account_name = talloc_zero ( c , struct lsa_String ) ;
2005-04-19 03:55:58 +00:00
s - > createuser . in . account_name - > string = talloc_strdup ( c , io - > in . username ) ;
2005-04-19 15:13:18 +00:00
s - > createuser . out . user_handle = & s - > user_handle ;
s - > createuser . out . rid = & s - > user_rid ;
2005-04-19 03:55:58 +00:00
2006-05-19 21:28:28 +00:00
/* send the request */
2005-04-19 03:55:58 +00:00
s - > req = dcerpc_samr_CreateUser_send ( p , c , & s - > createuser ) ;
2006-05-19 21:28:28 +00:00
if ( composite_nomem ( s - > req , c ) ) return c ;
2005-04-19 03:55:58 +00:00
2006-05-19 21:28:28 +00:00
/* callback handler for continuation */
2005-04-19 03:55:58 +00:00
s - > req - > async . callback = useradd_handler ;
s - > req - > async . private = c ;
s - > stage = USERADD_CREATE ;
return c ;
}
/**
* Waits for and receives result of asynchronous useradd call
*
2005-04-21 23:25:38 +00:00
* @ param c composite context returned by asynchronous useradd call
2005-04-19 03:55:58 +00: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 10:31:33 +00:00
NTSTATUS libnet_rpc_useradd_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
2005-09-29 22:34:21 +00:00
struct libnet_rpc_useradd * io )
2005-04-19 03:55:58 +00:00
{
NTSTATUS status ;
struct useradd_state * s ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & io ) {
2005-04-19 15:13:18 +00:00
/* get and return result of the call */
2005-09-26 11:47:55 +00:00
s = talloc_get_type ( c - > private_data , struct useradd_state ) ;
2005-04-19 15:13:18 +00:00
io - > out . user_handle = s - > user_handle ;
2005-04-19 03:55:58 +00: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
*/
2005-12-30 16:39:14 +00:00
NTSTATUS libnet_rpc_useradd ( struct dcerpc_pipe * p ,
2005-09-29 22:34:21 +00:00
TALLOC_CTX * mem_ctx ,
struct libnet_rpc_useradd * io )
2005-04-19 03:55:58 +00:00
{
2005-12-30 16:39:14 +00:00
struct composite_context * c = libnet_rpc_useradd_send ( p , io , NULL ) ;
2005-06-11 10:31:33 +00:00
return libnet_rpc_useradd_recv ( c , mem_ctx , io ) ;
2005-04-19 03:55:58 +00:00
}
2005-04-21 07:24:16 +00:00
2005-10-02 19:59:24 +00:00
2005-04-21 07:24:16 +00:00
/*
2005-10-02 19:59:24 +00:00
* Composite USER DELETE functionality
2005-04-21 07:24:16 +00:00
*/
static void userdel_handler ( struct rpc_request * ) ;
enum userdel_stage { USERDEL_LOOKUP , USERDEL_OPEN , USERDEL_DELETE } ;
struct userdel_state {
enum userdel_stage stage ;
struct dcerpc_pipe * pipe ;
struct rpc_request * req ;
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 19:59:24 +00:00
2005-09-26 11:47:55 +00:00
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
2005-04-21 07:24:16 +00:00
} ;
2005-04-21 23:25:38 +00:00
/**
* Stage 1 : Lookup the user name and resolve it to rid
*/
2005-04-21 07:24:16 +00:00
static NTSTATUS userdel_lookup ( struct composite_context * c ,
struct userdel_state * s )
{
2006-05-19 21:28:28 +00:00
/* receive samr_LookupNames result */
2005-04-21 07:24:16 +00:00
c - > status = dcerpc_ndr_request_recv ( s - > req ) ;
NT_STATUS_NOT_OK_RETURN ( c - > status ) ;
2006-05-19 21:28:28 +00:00
/* what to do when there's no user account to delete
and what if there ' s more than one rid resolved */
2005-04-21 07:24:16 +00:00
if ( ! s - > lookupname . out . rids . count ) {
2006-05-19 21:28:28 +00:00
c - > status = NT_STATUS_NO_SUCH_USER ;
composite_error ( c , c - > status ) ;
2005-04-21 07:24:16 +00:00
} else if ( ! s - > lookupname . out . rids . count > 1 ) {
2006-05-19 21:28:28 +00:00
c - > status = NT_STATUS_INVALID_ACCOUNT_NAME ;
composite_error ( c , c - > status ) ;
2005-04-21 07:24:16 +00:00
}
2006-05-19 21:28:28 +00:00
/* prepare the next rpc call arguments */
2005-04-21 07:24:16 +00:00
s - > openuser . in . domain_handle = & s - > domain_handle ;
s - > openuser . in . rid = s - > lookupname . out . rids . ids [ 0 ] ;
s - > openuser . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
s - > openuser . out . user_handle = & s - > user_handle ;
2006-05-19 21:28:28 +00:00
/* send rpc request */
2005-04-21 07:24:16 +00:00
s - > req = dcerpc_samr_OpenUser_send ( s - > pipe , c , & s - > openuser ) ;
2006-05-19 21:28:28 +00:00
if ( s - > req = = NULL ) return NT_STATUS_NO_MEMORY ;
/* callback handler setup */
2005-04-21 07:24:16 +00:00
s - > req - > async . callback = userdel_handler ;
s - > req - > async . private = c ;
s - > stage = USERDEL_OPEN ;
return NT_STATUS_OK ;
}
2005-04-21 23:25:38 +00:00
/**
* Stage 2 : Open user account .
*/
2005-04-21 07:24:16 +00:00
static NTSTATUS userdel_open ( struct composite_context * c ,
struct userdel_state * s )
{
2006-05-19 21:28:28 +00:00
/* receive samr_OpenUser result */
2005-04-21 07:24:16 +00:00
c - > status = dcerpc_ndr_request_recv ( s - > req ) ;
NT_STATUS_NOT_OK_RETURN ( c - > status ) ;
2006-05-19 21:28:28 +00:00
/* prepare the final rpc call arguments */
2005-04-21 07:24:16 +00:00
s - > deleteuser . in . user_handle = & s - > user_handle ;
s - > deleteuser . out . user_handle = & s - > user_handle ;
2006-05-19 21:28:28 +00:00
/* send rpc request */
2005-04-21 07:24:16 +00:00
s - > req = dcerpc_samr_DeleteUser_send ( s - > pipe , c , & s - > deleteuser ) ;
2006-05-19 21:28:28 +00:00
if ( s - > req = = NULL ) return NT_STATUS_NO_MEMORY ;
/* callback handler setup */
2005-04-21 07:24:16 +00:00
s - > req - > async . callback = userdel_handler ;
s - > req - > async . private = c ;
s - > stage = USERDEL_DELETE ;
return NT_STATUS_OK ;
}
2005-04-21 23:25:38 +00:00
/**
* Stage 3 : Delete user account
*/
2005-04-21 07:24:16 +00:00
static NTSTATUS userdel_delete ( struct composite_context * c ,
struct userdel_state * s )
{
2006-05-19 21:28:28 +00:00
/* receive samr_DeleteUser result */
2005-04-21 07:24:16 +00:00
c - > status = dcerpc_ndr_request_recv ( s - > req ) ;
NT_STATUS_NOT_OK_RETURN ( c - > status ) ;
2006-12-12 22:34:35 +00:00
/* return the actual function call status */
c - > status = s - > deleteuser . out . result ;
2006-05-19 21:28:28 +00:00
2005-09-26 11:47:55 +00:00
c - > state = COMPOSITE_STATE_DONE ;
2005-04-21 07:24:16 +00:00
2006-12-12 22:34:35 +00:00
return c - > status ;
2005-04-21 07:24:16 +00:00
}
2005-04-21 23:25:38 +00:00
/**
* Event handler for asynchronous request . Handles transition through
* intermediate stages of the call .
*
* @ param req rpc call context
*/
2005-04-21 07:24:16 +00:00
static void userdel_handler ( struct rpc_request * req )
{
2006-05-19 21:28:28 +00:00
struct composite_context * c ;
struct userdel_state * s ;
2005-07-22 17:45:42 +00:00
struct monitor_msg msg ;
2005-07-26 23:03:37 +00:00
struct msg_rpc_lookup_name * msg_lookup ;
struct msg_rpc_open_user * msg_open ;
2006-05-19 21:28:28 +00:00
c = talloc_get_type ( req - > async . private , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct userdel_state ) ;
2005-04-21 07:24:16 +00:00
switch ( s - > stage ) {
case USERDEL_LOOKUP :
c - > status = userdel_lookup ( c , s ) ;
2005-07-26 23:03:37 +00:00
2006-05-19 21:28:28 +00:00
/* monitor message */
2005-07-26 23:03:37 +00:00
msg . type = rpc_lookup_name ;
msg_lookup = talloc ( s , struct msg_rpc_lookup_name ) ;
2005-10-02 19:59:24 +00:00
msg_lookup - > rid = s - > lookupname . out . rids . ids ;
2005-07-26 23:03:37 +00:00
msg_lookup - > count = s - > lookupname . out . rids . count ;
msg . data = ( void * ) msg_lookup ;
msg . data_size = sizeof ( * msg_lookup ) ;
2005-04-21 07:24:16 +00:00
break ;
2005-07-26 23:03:37 +00:00
2005-04-21 07:24:16 +00:00
case USERDEL_OPEN :
c - > status = userdel_open ( c , s ) ;
2005-07-26 23:03:37 +00:00
2006-05-19 21:28:28 +00:00
/* monitor message */
2005-07-26 23:03:37 +00:00
msg . type = rpc_open_user ;
msg_open = talloc ( s , struct msg_rpc_open_user ) ;
2005-10-02 19:59:24 +00:00
msg_open - > rid = s - > openuser . in . rid ;
2005-07-26 23:03:37 +00:00
msg_open - > access_mask = s - > openuser . in . rid ;
msg . data = ( void * ) msg_open ;
msg . data_size = sizeof ( * msg_open ) ;
2005-04-21 07:24:16 +00:00
break ;
2005-07-26 23:03:37 +00:00
2005-04-21 07:24:16 +00:00
case USERDEL_DELETE :
c - > status = userdel_delete ( c , s ) ;
2005-07-26 23:03:37 +00:00
2006-05-19 21:28:28 +00:00
/* monitor message */
2005-07-26 23:03:37 +00:00
msg . type = rpc_delete_user ;
msg . data = NULL ;
msg . data_size = 0 ;
2005-04-21 07:24:16 +00:00
break ;
}
2006-05-19 21:28:28 +00:00
/* are we ok, so far ? */
2005-04-21 07:24:16 +00:00
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2005-09-26 11:47:55 +00:00
c - > state = COMPOSITE_STATE_ERROR ;
2005-04-21 07:24:16 +00:00
}
2006-05-19 21:28:28 +00:00
/* call monitor function provided the pointer has been passed */
2005-09-26 11:47:55 +00:00
if ( s - > monitor_fn ) {
s - > monitor_fn ( & msg ) ;
2005-07-22 17:45:42 +00:00
}
2006-05-19 21:28:28 +00:00
/* are we done yet */
2005-09-26 11:47:55 +00:00
if ( c - > state > = COMPOSITE_STATE_DONE & &
2005-04-21 07:24:16 +00:00
c - > async . fn ) {
c - > async . fn ( c ) ;
}
}
2005-04-21 23:25:38 +00:00
/**
* Sends asynchronous userdel request
*
* @ param p dce / rpc call pipe
* @ param io arguments and results of the call
2006-05-19 21:28:28 +00:00
* @ param monitor monitor function for providing information about the progress
2005-04-21 23:25:38 +00:00
*/
2005-06-11 10:31:33 +00:00
struct composite_context * libnet_rpc_userdel_send ( struct dcerpc_pipe * p ,
2006-05-17 21:41:59 +00:00
struct libnet_rpc_userdel * io ,
void ( * monitor ) ( struct monitor_msg * ) )
2005-04-21 07:24:16 +00:00
{
struct composite_context * c ;
struct userdel_state * s ;
2006-05-19 21:28:28 +00:00
/* composite context allocation and setup */
2005-04-21 07:24:16 +00:00
c = talloc_zero ( p , struct composite_context ) ;
2006-05-19 21:28:28 +00:00
if ( c = = NULL ) return NULL ;
2005-04-21 07:24:16 +00:00
s = talloc_zero ( c , struct userdel_state ) ;
2006-05-19 21:28:28 +00:00
if ( composite_nomem ( s , c ) ) return c ;
2005-04-21 07:24:16 +00:00
2005-10-02 19:59:24 +00:00
c - > state = COMPOSITE_STATE_IN_PROGRESS ;
c - > private_data = s ;
c - > event_ctx = dcerpc_event_context ( p ) ;
2005-04-21 07:24:16 +00:00
2006-05-19 21:28:28 +00:00
/* store function parameters in the state structure */
2005-04-21 12:21:14 +00:00
s - > pipe = p ;
s - > domain_handle = io - > in . domain_handle ;
2006-05-19 21:28:28 +00:00
s - > monitor_fn = monitor ;
2005-04-21 23:25:38 +00:00
/* preparing parameters to send rpc request */
2005-04-21 07:24:16 +00:00
s - > lookupname . in . domain_handle = & io - > in . domain_handle ;
s - > lookupname . in . num_names = 1 ;
2005-07-08 08:09:02 +00:00
s - > lookupname . in . names = talloc_zero ( s , struct lsa_String ) ;
2005-04-21 07:24:16 +00:00
s - > lookupname . in . names - > string = io - > in . username ;
2005-04-21 23:25:38 +00:00
/* send the request */
2005-04-21 07:24:16 +00:00
s - > req = dcerpc_samr_LookupNames_send ( p , c , & s - > lookupname ) ;
2005-04-21 23:25:38 +00:00
2006-05-19 21:28:28 +00:00
/* callback handler setup */
2005-04-21 07:24:16 +00:00
s - > req - > async . callback = userdel_handler ;
s - > req - > async . private = c ;
s - > stage = USERDEL_LOOKUP ;
return c ;
}
2005-04-21 23:25:38 +00:00
/**
2005-10-02 19:59:24 +00:00
* Waits for and receives results of asynchronous userdel call
2005-04-21 23:25:38 +00: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 10:31:33 +00:00
NTSTATUS libnet_rpc_userdel_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
2005-07-21 22:32:04 +00:00
struct libnet_rpc_userdel * io )
2005-04-21 07:24:16 +00:00
{
NTSTATUS status ;
struct userdel_state * s ;
status = composite_wait ( c ) ;
if ( NT_STATUS_IS_OK ( status ) & & io ) {
2005-09-26 11:47:55 +00:00
s = talloc_get_type ( c - > private_data , struct userdel_state ) ;
2005-04-21 07:24:16 +00:00
io - > out . user_handle = s - > user_handle ;
}
talloc_free ( c ) ;
return status ;
}
2005-04-22 00:22:11 +00: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
*/
2005-12-30 16:39:14 +00:00
NTSTATUS libnet_rpc_userdel ( struct dcerpc_pipe * p ,
2005-07-21 22:32:04 +00:00
TALLOC_CTX * mem_ctx ,
struct libnet_rpc_userdel * io )
2005-04-21 07:24:16 +00:00
{
2006-05-17 21:41:59 +00:00
struct composite_context * c = libnet_rpc_userdel_send ( p , io , NULL ) ;
2005-06-11 10:31:33 +00:00
return libnet_rpc_userdel_recv ( c , mem_ctx , io ) ;
2005-04-21 07:24:16 +00:00
}
2005-07-21 22:32:04 +00:00
2005-10-02 19:59:24 +00:00
/*
* USER MODIFY functionality
*/
2005-07-21 22:32:04 +00:00
static void usermod_handler ( struct rpc_request * ) ;
2005-08-01 20:47:26 +00:00
enum usermod_stage { USERMOD_LOOKUP , USERMOD_OPEN , USERMOD_QUERY , USERMOD_MODIFY } ;
2005-07-21 22:32:04 +00:00
struct usermod_state {
2005-08-01 20:47:26 +00:00
enum usermod_stage stage ;
struct dcerpc_pipe * pipe ;
struct rpc_request * req ;
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 19:59:24 +00:00
/* information about the progress */
void ( * monitor_fn ) ( struct monitor_msg * ) ;
2005-07-21 22:32:04 +00:00
} ;
2005-07-27 21:59:16 +00:00
/**
* Step 1 : Lookup user name
*/
2005-07-21 22:32:04 +00:00
static NTSTATUS usermod_lookup ( struct composite_context * c ,
struct usermod_state * s )
{
2006-05-19 21:28:28 +00:00
/* receive samr_LookupNames result */
2005-07-21 22:32:04 +00:00
c - > status = dcerpc_ndr_request_recv ( s - > req ) ;
NT_STATUS_NOT_OK_RETURN ( c - > status ) ;
2006-05-19 21:28:28 +00:00
/* what to do when there's no user account to delete
and what if there ' s more than one rid resolved */
2005-07-21 22:32:04 +00:00
if ( ! s - > lookupname . out . rids . count ) {
2006-05-19 21:28:28 +00:00
c - > status = NT_STATUS_NO_SUCH_USER ;
2006-06-22 21:29:21 +00:00
c - > state = COMPOSITE_STATE_ERROR ;
return c - > status ;
2005-07-21 22:32:04 +00:00
} else if ( ! s - > lookupname . out . rids . count > 1 ) {
2006-05-19 21:28:28 +00:00
c - > status = NT_STATUS_INVALID_ACCOUNT_NAME ;
2006-06-22 21:29:21 +00:00
c - > state = COMPOSITE_STATE_ERROR ;
return c - > status ;
2005-07-21 22:32:04 +00:00
}
2006-05-19 21:28:28 +00:00
/* prepare the next rpc call */
2005-07-21 22:32:04 +00:00
s - > openuser . in . domain_handle = & s - > domain_handle ;
s - > openuser . in . rid = s - > lookupname . out . rids . ids [ 0 ] ;
s - > openuser . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
s - > openuser . out . user_handle = & s - > user_handle ;
2006-05-19 21:28:28 +00:00
/* send the rpc request */
2005-07-21 22:32:04 +00:00
s - > req = dcerpc_samr_OpenUser_send ( s - > pipe , c , & s - > openuser ) ;
2006-05-19 21:28:28 +00:00
/* callback handler setup */
2005-07-21 22:32:04 +00:00
s - > req - > async . callback = usermod_handler ;
s - > req - > async . private = c ;
s - > stage = USERMOD_OPEN ;
return NT_STATUS_OK ;
}
2006-05-19 21:28:28 +00: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 .
*/
2005-08-01 20:47:26 +00:00
static uint32_t usermod_setfields ( struct usermod_state * s , uint16_t * level ,
union samr_UserInfo * i )
2005-07-21 22:32:04 +00:00
{
2006-09-19 19:10:14 +00:00
if ( s - > change . fields = = 0 ) return s - > change . fields ;
2005-07-25 22:00:56 +00:00
2006-09-20 23:39:15 +00:00
* level = 0 ;
if ( ( s - > change . fields & USERMOD_FIELD_ACCOUNT_NAME ) & &
( * level = = 0 | | * level = = 7 ) ) {
2006-09-19 19:10:14 +00:00
* level = 7 ;
i - > info7 . account_name . string = s - > change . account_name ;
s - > change . fields ^ = USERMOD_FIELD_ACCOUNT_NAME ;
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_FULL_NAME ) & &
( * level = = 0 | | * level = = 8 ) ) {
2006-09-19 19:10:14 +00:00
* level = 8 ;
i - > info8 . full_name . string = s - > change . full_name ;
s - > change . fields ^ = USERMOD_FIELD_FULL_NAME ;
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_DESCRIPTION ) & &
( * level = = 0 | | * level = = 13 ) ) {
2006-09-19 19:10:14 +00:00
* level = 13 ;
i - > info13 . description . string = s - > change . description ;
2006-10-02 05:53:45 +00:00
s - > change . fields ^ = USERMOD_FIELD_DESCRIPTION ;
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_COMMENT ) & &
( * level = = 0 | | * level = = 2 ) ) {
2006-09-19 19:10:14 +00:00
* level = 2 ;
if ( s - > stage = = USERMOD_QUERY ) {
/* 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-25 22:00:56 +00:00
2006-09-19 19:10:14 +00:00
} else {
/* we need to query the user info before setting one field in it */
s - > stage = USERMOD_QUERY ;
return s - > change . fields ;
}
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_LOGON_SCRIPT ) & &
( * level = = 0 | | * level = = 11 ) ) {
2006-09-19 19:10:14 +00:00
* level = 11 ;
i - > info11 . logon_script . string = s - > change . logon_script ;
s - > change . fields ^ = USERMOD_FIELD_LOGON_SCRIPT ;
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_PROFILE_PATH ) & &
( * level = = 0 | | * level = = 12 ) ) {
2006-09-19 19:10:14 +00:00
* level = 12 ;
i - > info12 . profile_path . string = s - > change . profile_path ;
s - > change . fields ^ = USERMOD_FIELD_PROFILE_PATH ;
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_HOME_DIRECTORY ) & &
2006-10-02 05:53:45 +00:00
( * level = = 0 | | * level = = 10 ) ) {
* level = 10 ;
2006-09-19 19:10:14 +00:00
if ( s - > stage = = USERMOD_QUERY ) {
2006-10-02 05:53:45 +00:00
i - > info10 . home_directory . string = s - > change . home_directory ;
2006-09-19 19:10:14 +00:00
s - > change . fields ^ = USERMOD_FIELD_HOME_DIRECTORY ;
} else {
s - > stage = USERMOD_QUERY ;
return s - > change . fields ;
}
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_HOME_DRIVE ) & &
2006-10-02 05:53:45 +00:00
( * level = = 0 | | * level = = 10 ) ) {
* level = 10 ;
2006-09-19 19:10:14 +00:00
if ( s - > stage = = USERMOD_QUERY ) {
2006-10-02 05:53:45 +00:00
i - > info10 . home_drive . string = s - > change . home_drive ;
2006-09-19 19:10:14 +00:00
s - > change . fields ^ = USERMOD_FIELD_HOME_DRIVE ;
} else {
s - > stage = USERMOD_QUERY ;
return s - > change . fields ;
2005-07-23 10:27:45 +00:00
}
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_ACCT_EXPIRY ) & &
( * level = = 0 | | * level = = 17 ) ) {
2006-09-19 19:10:14 +00:00
* level = 17 ;
i - > info17 . acct_expiry = timeval_to_nttime ( s - > change . acct_expiry ) ;
s - > change . fields ^ = USERMOD_FIELD_ACCT_EXPIRY ;
2006-09-20 23:39:15 +00:00
}
if ( ( s - > change . fields & USERMOD_FIELD_ACCT_FLAGS ) & &
( * level = = 0 | | * level = = 16 ) ) {
2006-09-19 19:10:14 +00:00
* level = 16 ;
i - > info16 . acct_flags = s - > change . acct_flags ;
s - > change . fields ^ = USERMOD_FIELD_ACCT_FLAGS ;
2005-07-23 10:27:45 +00:00
}
2006-09-19 00:23:55 +00:00
/* We're going to be here back again soon unless all fields have been set */
2005-07-23 10:27:45 +00:00
if ( s - > change . fields ) {
s - > stage = USERMOD_OPEN ;
} else {
s - > stage = USERMOD_MODIFY ;
}
2005-07-21 22:32:04 +00:00
2005-08-01 20:47:26 +00:00
return s - > change . fields ;
}
2006-09-20 23:39:15 +00:00
static NTSTATUS usermod_change ( struct composite_context * c ,
struct usermod_state * s )
2005-08-01 20:47:26 +00:00
{
union samr_UserInfo * i = & s - > info ;
2006-09-20 23:39:15 +00:00
2006-09-19 00:23:55 +00: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-01 20:47:26 +00:00
2006-05-19 21:28:28 +00:00
/* prepare UserInfo level and data based on bitmask field */
2005-08-01 20:47:26 +00:00
s - > change . fields = usermod_setfields ( s , & level , i ) ;
2006-09-20 23:39:15 +00:00
if ( level < 1 | | level > 26 ) {
2006-09-19 00:23:55 +00:00
/* apparently there's a field that the setfields routine
does not know how to set */
c - > state = COMPOSITE_STATE_ERROR ;
return NT_STATUS_INVALID_PARAMETER ;
}
2006-05-19 21:28:28 +00: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 .
*/
2005-08-01 20:47:26 +00:00
if ( s - > stage = = USERMOD_QUERY ) {
s - > queryuser . in . user_handle = & s - > user_handle ;
s - > queryuser . in . level = level ;
2006-05-19 21:28:28 +00:00
/* send query user info request to retrieve complete data of
a particular info level */
2005-08-01 20:47:26 +00:00
s - > req = dcerpc_samr_QueryUserInfo_send ( s - > pipe , c , & s - > queryuser ) ;
} else {
s - > setuser . in . user_handle = & s - > user_handle ;
s - > setuser . in . level = level ;
s - > setuser . in . info = i ;
2006-05-19 21:28:28 +00:00
/* send set user info request after making required change */
2005-08-01 20:47:26 +00:00
s - > req = dcerpc_samr_SetUserInfo_send ( s - > pipe , c , & s - > setuser ) ;
}
2006-05-19 21:28:28 +00:00
/* callback handler setup */
2005-08-01 20:47:26 +00:00
s - > req - > async . callback = usermod_handler ;
s - > req - > async . private = c ;
2005-07-21 22:32:04 +00:00
return NT_STATUS_OK ;
}
2006-09-20 23:39:15 +00:00
/**
* Stage 2 : Open user account
*/
static NTSTATUS usermod_open ( struct composite_context * c ,
struct usermod_state * s )
{
c - > status = dcerpc_ndr_request_recv ( s - > req ) ;
NT_STATUS_NOT_OK_RETURN ( c - > status ) ;
return usermod_change ( c , s ) ;
}
2005-08-02 01:12:58 +00:00
/**
* Stage 2 a ( optional ) : Query the user information
*/
static NTSTATUS usermod_query ( struct composite_context * c ,
struct usermod_state * s )
{
union samr_UserInfo * i = & s - > info ;
uint16_t level ;
2006-05-19 21:28:28 +00:00
/* receive samr_QueryUserInfo result */
2005-08-02 01:12:58 +00:00
c - > status = dcerpc_ndr_request_recv ( s - > req ) ;
NT_STATUS_NOT_OK_RETURN ( c - > status ) ;
2006-05-19 21:28:28 +00:00
/* get returned user data and make a change (potentially one
of many ) */
2005-08-02 01:12:58 +00:00
s - > info = * s - > queryuser . out . info ;
s - > change . fields = usermod_setfields ( s , & level , i ) ;
2006-05-19 21:28:28 +00:00
/* prepare rpc call arguments */
2005-08-02 01:12:58 +00:00
s - > setuser . in . user_handle = & s - > user_handle ;
s - > setuser . in . level = level ;
s - > setuser . in . info = i ;
2006-05-19 21:28:28 +00:00
/* send the rpc request */
2005-08-02 01:12:58 +00:00
s - > req = dcerpc_samr_SetUserInfo_send ( s - > pipe , c , & s - > setuser ) ;
2006-05-19 21:28:28 +00:00
/* callback handler setup */
2005-08-02 01:12:58 +00:00
s - > req - > async . callback = usermod_handler ;
s - > req - > async . private = c ;
return NT_STATUS_OK ;
}
2005-07-27 21:59:16 +00:00
/**
* Stage 3 : Set new user account data
*/
2005-07-21 22:32:04 +00:00
static NTSTATUS usermod_modify ( struct composite_context * c ,
struct usermod_state * s )
{
2006-05-19 21:28:28 +00:00
/* receive samr_SetUserInfo result */
2005-07-21 22:32:04 +00:00
c - > status = dcerpc_ndr_request_recv ( s - > req ) ;
NT_STATUS_NOT_OK_RETURN ( c - > status ) ;
2006-12-12 22:34:35 +00:00
/* return the actual function call status */
c - > status = s - > setuser . out . result ;
2006-10-02 05:53:45 +00:00
2006-09-20 23:39:15 +00:00
if ( s - > change . fields = = 0 ) {
/* all fields have been set - we're done */
c - > state = COMPOSITE_STATE_DONE ;
} else {
/* something's still not changed - repeat the procedure */
return usermod_change ( c , s ) ;
}
2005-07-21 22:32:04 +00:00
2006-12-12 22:34:35 +00:00
return c - > status ;
2005-07-21 22:32:04 +00:00
}
2005-07-27 21:59:16 +00:00
/**
* Event handler for asynchronous request . Handles transition through
* intermediate stages of the call .
*
* @ param req rpc call context
*/
2005-07-21 22:32:04 +00:00
static void usermod_handler ( struct rpc_request * req )
{
2006-05-19 21:28:28 +00:00
struct composite_context * c ;
struct usermod_state * s ;
2005-10-02 19:59:24 +00:00
struct monitor_msg msg ;
struct msg_rpc_lookup_name * msg_lookup ;
struct msg_rpc_open_user * msg_open ;
2005-07-21 22:32:04 +00:00
2006-05-19 21:28:28 +00:00
c = talloc_get_type ( req - > async . private , struct composite_context ) ;
s = talloc_get_type ( c - > private_data , struct usermod_state ) ;
2005-07-21 22:32:04 +00:00
switch ( s - > stage ) {
case USERMOD_LOOKUP :
c - > status = usermod_lookup ( c , s ) ;
2006-05-19 21:28:28 +00:00
2006-06-26 21:17:31 +00:00
if ( NT_STATUS_IS_OK ( c - > status ) ) {
/* monitor message */
msg . type = rpc_lookup_name ;
msg_lookup = talloc ( s , struct msg_rpc_lookup_name ) ;
msg_lookup - > rid = s - > lookupname . out . rids . ids ;
msg_lookup - > count = s - > lookupname . out . rids . count ;
msg . data = ( void * ) msg_lookup ;
msg . data_size = sizeof ( * msg_lookup ) ;
}
2005-07-21 22:32:04 +00:00
break ;
2005-08-01 20:47:26 +00:00
2005-07-21 22:32:04 +00:00
case USERMOD_OPEN :
c - > status = usermod_open ( c , s ) ;
2005-10-02 19:59:24 +00:00
2006-06-26 21:17:31 +00:00
if ( NT_STATUS_IS_OK ( c - > status ) ) {
/* monitor message */
msg . type = rpc_open_user ;
msg_open = talloc ( s , struct msg_rpc_open_user ) ;
msg_open - > rid = s - > openuser . in . rid ;
msg_open - > access_mask = s - > openuser . in . rid ;
msg . data = ( void * ) msg_open ;
msg . data_size = sizeof ( * msg_open ) ;
}
2005-07-21 22:32:04 +00:00
break ;
2005-08-01 20:47:26 +00:00
2005-08-02 01:12:58 +00:00
case USERMOD_QUERY :
c - > status = usermod_query ( c , s ) ;
2005-10-02 19:59:24 +00:00
2006-06-26 21:17:31 +00:00
if ( NT_STATUS_IS_OK ( c - > status ) ) {
/* monitor message */
msg . type = rpc_query_user ;
msg . data = NULL ;
msg . data_size = 0 ;
}
2005-08-02 01:12:58 +00:00
break ;
2005-07-21 22:32:04 +00:00
case USERMOD_MODIFY :
c - > status = usermod_modify ( c , s ) ;
2006-06-26 21:17:31 +00:00
if ( NT_STATUS_IS_OK ( c - > status ) ) {
/* monitor message */
msg . type = rpc_set_user ;
msg . data = NULL ;
msg . data_size = 0 ;
}
2005-07-21 22:32:04 +00:00
break ;
}
2006-05-19 21:28:28 +00:00
/* are we ok, so far ? */
2005-07-21 22:32:04 +00:00
if ( ! NT_STATUS_IS_OK ( c - > status ) ) {
2005-09-26 11:47:55 +00:00
c - > state = COMPOSITE_STATE_ERROR ;
2005-07-22 17:45:42 +00:00
}
2006-05-19 21:28:28 +00:00
/* call monitor function provided the pointer has been passed */
2005-10-02 19:59:24 +00:00
if ( s - > monitor_fn ) {
s - > monitor_fn ( & msg ) ;
}
2006-05-19 21:28:28 +00:00
/* are we done yet ? */
2005-09-26 11:47:55 +00:00
if ( c - > state > = COMPOSITE_STATE_DONE & &
2005-07-21 22:32:04 +00:00
c - > async . fn ) {
c - > async . fn ( c ) ;
}
}
2005-07-27 21:59:16 +00:00
/**
* Sends asynchronous usermod request
*
* @ param p dce / rpc call pipe
* @ param io arguments and results of the call
2006-05-19 21:28:28 +00:00
* @ param monitor monitor function for providing information about the progress
2005-07-27 21:59:16 +00:00
*/
2005-07-21 22:32:04 +00:00
struct composite_context * libnet_rpc_usermod_send ( struct dcerpc_pipe * p ,
2006-05-19 21:28:28 +00:00
struct libnet_rpc_usermod * io ,
void ( * monitor ) ( struct monitor_msg * ) )
2005-07-21 22:32:04 +00:00
{
struct composite_context * c ;
struct usermod_state * s ;
2006-05-19 21:28:28 +00:00
/* composite context allocation and setup */
2005-07-21 22:32:04 +00:00
c = talloc_zero ( p , struct composite_context ) ;
2006-05-19 21:28:28 +00:00
if ( c = = NULL ) return NULL ;
2005-07-21 22:32:04 +00:00
s = talloc_zero ( c , struct usermod_state ) ;
2006-05-19 21:28:28 +00:00
if ( composite_nomem ( s , c ) ) return c ;
2005-07-21 22:32:04 +00:00
2005-09-26 11:47:55 +00:00
c - > state = COMPOSITE_STATE_IN_PROGRESS ;
c - > private_data = s ;
c - > event_ctx = dcerpc_event_context ( p ) ;
2005-07-21 22:32:04 +00:00
2006-05-19 21:28:28 +00:00
/* store parameters in the call structure */
2005-07-21 22:32:04 +00:00
s - > pipe = p ;
s - > domain_handle = io - > in . domain_handle ;
2005-07-23 10:27:45 +00:00
s - > change = io - > in . change ;
2006-05-19 21:28:28 +00:00
s - > monitor_fn = monitor ;
2005-07-21 22:32:04 +00:00
2006-05-19 21:28:28 +00:00
/* prepare rpc call arguments */
2005-07-21 22:32:04 +00: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 ;
2006-05-19 21:28:28 +00:00
/* send the rpc request */
2005-07-21 22:32:04 +00:00
s - > req = dcerpc_samr_LookupNames_send ( p , c , & s - > lookupname ) ;
2006-05-19 21:28:28 +00:00
/* callback handler setup */
2005-07-21 22:32:04 +00:00
s - > req - > async . callback = usermod_handler ;
s - > req - > async . private = c ;
s - > stage = USERMOD_LOOKUP ;
return c ;
}
2005-07-27 21:59:16 +00: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-21 22:32:04 +00: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-27 21:59:16 +00: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
*/
2005-12-30 16:39:14 +00:00
NTSTATUS libnet_rpc_usermod ( struct dcerpc_pipe * p ,
2005-07-21 22:32:04 +00:00
TALLOC_CTX * mem_ctx ,
struct libnet_rpc_usermod * io )
{
2006-05-19 21:28:28 +00:00
struct composite_context * c = libnet_rpc_usermod_send ( p , io , NULL ) ;
2005-07-21 22:32:04 +00:00
return libnet_rpc_usermod_recv ( c , mem_ctx , io ) ;
}