2005-02-13 03:48:21 +03:00
/*
Unix SMB / CIFS implementation .
Copyright ( C ) Rafal Szczesniak < mimir @ samba . org > 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 .
*/
# 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-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/ndr_samr.h"
2005-02-13 03:48:21 +03:00
2006-05-28 14:43:48 +04:00
/**
* Verify , before actually doing anything with user accounts , whether
* required domain is already opened and thus ready for operation .
* If it is not , or if the opened domain is not the one requested , open
* the requested domain .
*/
static struct composite_context * domain_opened ( struct libnet_context * ctx ,
const char * domain_name ,
struct composite_context * parent_ctx ,
struct libnet_DomainOpen * domain_open ,
void ( * continue_fn ) ( struct composite_context * ) ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * domopen_req ;
if ( domain_name = = NULL ) {
2006-06-14 01:57:44 +04:00
/*
* Try to guess the domain name from credentials ,
* if it ' s not been explicitly specified .
*/
2006-05-28 14:43:48 +04:00
if ( policy_handle_empty ( & ctx - > domain . handle ) ) {
domain_open - > in . domain_name = cli_credentials_get_domain ( ctx - > cred ) ;
domain_open - > in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
2006-06-14 01:57:44 +04:00
2006-05-28 14:43:48 +04:00
} else {
composite_error ( parent_ctx , NT_STATUS_INVALID_PARAMETER ) ;
return parent_ctx ;
}
} else {
2006-06-14 01:57:44 +04:00
/*
* The domain name has been specified , so check whether the same
* domain is already opened . If it is - just return NULL . Start
* opening a new domain otherwise .
*/
2006-05-28 14:43:48 +04:00
if ( policy_handle_empty ( & ctx - > domain . handle ) | |
! strequal ( domain_name , ctx - > domain . name ) ) {
domain_open - > in . domain_name = domain_name ;
2006-06-14 01:57:44 +04:00
domain_open - > in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
} else {
/* domain has already been opened and it's the same domain
as requested */
return NULL ;
2006-05-28 14:43:48 +04:00
}
}
2006-06-14 01:57:44 +04:00
/* send request to open the domain */
domopen_req = libnet_DomainOpen_send ( ctx , domain_open , monitor ) ;
if ( composite_nomem ( domopen_req , parent_ctx ) ) return parent_ctx ;
composite_continue ( parent_ctx , domopen_req , continue_fn , parent_ctx ) ;
return parent_ctx ;
2006-05-28 14:43:48 +04: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
* @ param mem_ctx memory context of the call
* @ param r pointer to a structure containing arguments and results of the call
* @ param monitor pointer to monitor function
* @ return compostite context of the request
*/
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 ;
2006-05-28 14:43:48 +04:00
struct composite_context * prereq_ctx ;
2006-05-16 01:49:27 +04:00
2006-06-28 00:46:23 +04:00
/* composite context allocation and setup */
2006-05-16 01:49:27 +04:00
c = talloc_zero ( mem_ctx , struct composite_context ) ;
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct create_user_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > state = COMPOSITE_STATE_IN_PROGRESS ;
c - > private_data = s ;
c - > event_ctx = ctx - > event_ctx ;
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-05-28 14:43:48 +04:00
prereq_ctx = domain_opened ( ctx , s - > r . in . domain_name , c , & s - > domain_open ,
continue_domain_open_create , monitor ) ;
if ( prereq_ctx ) return prereq_ctx ;
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 ;
s - > user_add . in . domain_handle = ctx - > domain . handle ;
2006-06-28 00:46:23 +04:00
/* send the request */
2006-05-16 01:49:27 +04:00
create_req = libnet_rpc_useradd_send ( ctx - > samr_pipe , & s - > user_add , monitor ) ;
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 ;
s - > user_add . in . domain_handle = s - > ctx - > domain . handle ;
2006-06-28 00:46:23 +04:00
/* send the request */
2006-05-16 01:49:27 +04:00
create_req = libnet_rpc_useradd_send ( s - > ctx - > samr_pipe , & s - > user_add , s - > monitor_fn ) ;
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
* @ param mem_ctx memory context of the call
* @ param r pointer to a structure containing arguments and result of the call
* @ 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-28 00:46:23 +04:00
/* wait for completion and check possible errors */
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
* @ param mem_ctx memory context of the call
* @ param r pointer to a structure containing arguments and result of the call
* @ 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 ) ;
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 ;
2006-05-28 14:43:48 +04:00
struct composite_context * prereq_ctx ;
2006-05-18 01:41:59 +04:00
c = talloc_zero ( mem_ctx , struct composite_context ) ;
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct delete_user_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > private_data = s ;
c - > state = COMPOSITE_STATE_IN_PROGRESS ;
c - > event_ctx = ctx - > event_ctx ;
s - > ctx = ctx ;
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-05-28 14:43:48 +04:00
prereq_ctx = domain_opened ( ctx , s - > r . in . domain_name , c , & s - > domain_open ,
continue_domain_open_delete , monitor ) ;
if ( prereq_ctx ) return prereq_ctx ;
2005-02-13 03:48:21 +03:00
2006-05-18 01:41:59 +04:00
s - > user_del . in . username = r - > in . user_name ;
s - > user_del . in . domain_handle = ctx - > domain . handle ;
2005-06-08 03:24:10 +04:00
2006-05-18 01:41:59 +04:00
delete_req = libnet_rpc_userdel_send ( ctx - > samr_pipe , & s - > user_del , monitor ) ;
if ( composite_nomem ( delete_req , c ) ) return c ;
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-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-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 ;
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
s - > user_del . in . username = s - > r . in . user_name ;
s - > user_del . in . domain_handle = s - > ctx - > domain . handle ;
delete_req = libnet_rpc_userdel_send ( s - > ctx - > samr_pipe , & s - > user_del , s - > monitor_fn ) ;
if ( composite_nomem ( delete_req , c ) ) return ;
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-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-05-18 01:41:59 +04:00
c - > status = libnet_rpc_userdel_recv ( ctx , c , & s - > user_del ) ;
if ( ! composite_is_ok ( c ) ) return ;
if ( s - > monitor_fn ) s - > monitor_fn ( & msg ) ;
composite_done ( c ) ;
}
2006-01-13 06:39:49 +03:00
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 ;
status = composite_wait ( c ) ;
2006-05-24 15:32:17 +04:00
if ( NT_STATUS_IS_OK ( status ) ) {
r - > out . error_string = NULL ;
} else {
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
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
struct composite_context * libnet_ModifyUser_send ( struct libnet_context * ctx ,
TALLOC_CTX * mem_ctx ,
struct libnet_ModifyUser * r ,
void ( * monitor ) ( struct monitor_msg * ) )
{
struct composite_context * c ;
struct modify_user_state * s ;
struct composite_context * prereq_ctx ;
2006-06-14 01:57:44 +04:00
struct composite_context * userinfo_req ;
2006-05-28 14:43:48 +04:00
c = talloc_zero ( mem_ctx , struct composite_context ) ;
if ( c = = NULL ) return NULL ;
s = talloc_zero ( c , struct modify_user_state ) ;
if ( composite_nomem ( s , c ) ) return c ;
c - > state = COMPOSITE_STATE_IN_PROGRESS ;
c - > private_data = s ;
c - > event_ctx = ctx - > event_ctx ;
s - > ctx = ctx ;
s - > r = * r ;
prereq_ctx = domain_opened ( ctx , s - > r . in . domain_name , c , & s - > domain_open ,
continue_domain_open_modify , monitor ) ;
if ( prereq_ctx ) return prereq_ctx ;
s - > user_mod . in . username = r - > in . user_name ;
s - > user_mod . in . domain_handle = ctx - > domain . handle ;
2006-06-14 01:57:44 +04:00
userinfo_req = libnet_rpc_userinfo_send ( ctx - > samr_pipe , & s - > user_info , monitor ) ;
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 ;
}
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-06-14 01:57:44 +04:00
s - > user_info . in . domain_handle = s - > ctx - > domain . handle ;
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-06-14 01:57:44 +04:00
userinfo_req = libnet_rpc_userinfo_send ( s - > ctx - > samr_pipe , & s - > user_info , s - > monitor_fn ) ;
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 ) ;
}
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-06-27 01:18:45 +04:00
s - > user_mod . in . domain_handle = s - > ctx - > domain . handle ;
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
usermod_req = libnet_rpc_usermod_send ( s - > ctx - > samr_pipe , & s - > user_mod , s - > monitor_fn ) ;
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-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 */
if ( r - > in . account_name ! = NULL & &
! strequal_w ( user - > account_name . string , r - > in . account_name ) ) {
mod - > account_name = talloc_strdup ( mem_ctx , r - > in . account_name ) ;
if ( mod - > account_name = = NULL ) return NT_STATUS_NO_MEMORY ;
mod - > fields | = USERMOD_FIELD_ACCOUNT_NAME ;
}
if ( r - > in . full_name ! = NULL & &
! strequal_w ( user - > full_name . string , r - > in . full_name ) ) {
mod - > full_name = talloc_strdup ( mem_ctx , r - > in . full_name ) ;
if ( mod - > full_name = = NULL ) return NT_STATUS_NO_MEMORY ;
mod - > fields | = USERMOD_FIELD_FULL_NAME ;
}
return NT_STATUS_OK ;
}
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 ) ;
}
NTSTATUS libnet_ModifyUser_recv ( struct composite_context * c , TALLOC_CTX * mem_ctx ,
struct libnet_ModifyUser * r )
{
NTSTATUS status = composite_wait ( c ) ;
return status ;
}
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 ) ;
}