2001-02-27 21:22:39 +03:00
/*
* Unix SMB / Netbios implementation .
* Version 1.9 .
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 1997 ,
* Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1997 ,
* Copyright ( C ) Paul Ashton 1997.
* Copyright ( C ) Hewlett - Packard Company 1999.
* Copyright ( C ) Jeremy Allison 2001.
*
* 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 .
*/
/*
* This is the implementation of the SAMR code .
*/
# include "includes.h"
extern int DEBUGLEVEL ;
extern fstring global_myworkgroup ;
extern pstring global_myname ;
extern DOM_SID global_sam_sid ;
extern rid_name domain_group_rids [ ] ;
extern rid_name domain_alias_rids [ ] ;
extern rid_name builtin_alias_rids [ ] ;
2001-03-11 03:32:10 +03:00
struct samr_info {
/* for use by the \PIPE\samr policy */
DOM_SID sid ;
uint32 status ; /* some sort of flag. best to record it. comes from opnum 0x39 */
} ;
/*******************************************************************
Function to free the per handle data .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_samr_info ( void * ptr )
{
struct samr_info * samr = ( struct samr_info * ) ptr ;
safe_free ( samr ) ;
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
This next function should be replaced with something that
dynamically returns the correct user info . . . . . JRA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL get_sampwd_entries ( SAM_USER_INFO_21 * pw_buf , int start_idx ,
int * total_entries , int * num_entries ,
int max_num_entries , uint16 acb_mask )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * pwd = NULL ;
2001-02-27 21:22:39 +03:00
( * num_entries ) = 0 ;
( * total_entries ) = 0 ;
if ( pw_buf = = NULL )
return False ;
2001-03-11 03:32:10 +03:00
if ( ! pdb_setsampwent ( False ) ) {
DEBUG ( 0 , ( " get_sampwd_entries: Unable to open passdb. \n " ) ) ;
2001-02-27 21:22:39 +03:00
return False ;
}
2001-03-11 03:32:10 +03:00
while ( ( ( pwd = pdb_getsampwent ( ) ) ! = NULL ) & & ( * num_entries ) < max_num_entries ) {
2001-02-27 21:22:39 +03:00
int user_name_len ;
if ( start_idx > 0 ) {
/* skip the requested number of entries.
not very efficient , but hey . . .
*/
start_idx - - ;
continue ;
}
2001-03-11 03:32:10 +03:00
user_name_len = strlen ( pdb_get_username ( pwd ) ) + 1 ;
init_unistr2 ( & pw_buf [ ( * num_entries ) ] . uni_user_name , pdb_get_username ( pwd ) , user_name_len ) ;
2001-02-27 21:22:39 +03:00
init_uni_hdr ( & pw_buf [ ( * num_entries ) ] . hdr_user_name , user_name_len ) ;
pw_buf [ ( * num_entries ) ] . user_rid = pwd - > user_rid ;
memset ( ( char * ) pw_buf [ ( * num_entries ) ] . nt_pwd , ' \0 ' , 16 ) ;
/* Now check if the NT compatible password is available. */
2001-03-11 03:32:10 +03:00
if ( pdb_get_nt_passwd ( pwd ) )
memcpy ( pw_buf [ ( * num_entries ) ] . nt_pwd , pdb_get_nt_passwd ( pwd ) , 16 ) ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
pw_buf [ ( * num_entries ) ] . acb_info = pdb_get_acct_ctrl ( pwd ) ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " entry idx: %d user %s, rid 0x%x, acb %x " ,
2001-03-11 03:32:10 +03:00
( * num_entries ) , pdb_get_username ( pwd ) , pdb_get_user_rid ( pwd ) , pdb_get_acct_ctrl ( pwd ) ) ) ;
2001-02-27 21:22:39 +03:00
if ( acb_mask = = 0 | | ( pwd - > acct_ctrl & acb_mask ) ) {
DEBUG ( 5 , ( " acb_mask %x accepts \n " , acb_mask ) ) ;
( * num_entries ) + + ;
}
else
DEBUG ( 5 , ( " acb_mask %x rejects \n " , acb_mask ) ) ;
( * total_entries ) + + ;
}
2001-03-11 03:32:10 +03:00
pdb_endsampwent ( ) ;
2001-02-27 21:22:39 +03:00
return ( * num_entries ) > 0 ;
}
static BOOL jf_get_sampwd_entries ( SAM_USER_INFO_21 * pw_buf , int start_idx ,
2001-03-11 03:32:10 +03:00
int * total_entries , uint32 * num_entries ,
2001-02-27 21:22:39 +03:00
int max_num_entries , uint16 acb_mask )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * pwd = NULL ;
2001-02-27 21:22:39 +03:00
* num_entries = 0 ;
* total_entries = 0 ;
if ( pw_buf = = NULL )
return False ;
2001-03-11 03:32:10 +03:00
if ( ! pdb_setsampwent ( False ) ) {
DEBUG ( 0 , ( " jf_get_sampwd_entries: Unable to open passdb. \n " ) ) ;
return False ;
}
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
while ( ( ( pwd = pdb_getsampwent ( ) ) ! = NULL ) & & ( * num_entries ) < max_num_entries ) {
2001-02-27 21:22:39 +03:00
int user_name_len ;
int full_name_len ;
2001-03-11 03:32:10 +03:00
if ( acb_mask ! = 0 & & ! ( pdb_get_acct_ctrl ( pwd ) & acb_mask ) )
2001-02-27 21:22:39 +03:00
continue ;
if ( start_idx > 0 ) {
/* skip the requested number of entries.
not very efficient , but hey . . .
*/
start_idx - - ;
continue ;
}
ZERO_STRUCTP ( & pw_buf [ ( * num_entries ) ] ) ;
2001-03-11 03:32:10 +03:00
user_name_len = strlen ( pdb_get_username ( pwd ) ) ;
init_unistr2 ( & pw_buf [ ( * num_entries ) ] . uni_user_name , pdb_get_username ( pwd ) , user_name_len ) ;
2001-02-27 21:22:39 +03:00
init_uni_hdr ( & pw_buf [ ( * num_entries ) ] . hdr_user_name , user_name_len ) ;
2001-03-11 03:32:10 +03:00
full_name_len = strlen ( pdb_get_fullname ( pwd ) ) ;
init_unistr2 ( & pw_buf [ ( * num_entries ) ] . uni_full_name , pdb_get_fullname ( pwd ) , full_name_len ) ;
2001-02-27 21:22:39 +03:00
init_uni_hdr ( & pw_buf [ ( * num_entries ) ] . hdr_full_name , full_name_len ) ;
2001-03-11 03:32:10 +03:00
pw_buf [ ( * num_entries ) ] . user_rid = pdb_get_user_rid ( pwd ) ;
2001-02-27 21:22:39 +03:00
memset ( ( char * ) pw_buf [ ( * num_entries ) ] . nt_pwd , ' \0 ' , 16 ) ;
/* Now check if the NT compatible password is available. */
2001-03-11 03:32:10 +03:00
if ( pdb_get_nt_passwd ( pwd ) )
memcpy ( pw_buf [ ( * num_entries ) ] . nt_pwd , pdb_get_nt_passwd ( pwd ) , 16 ) ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
pw_buf [ ( * num_entries ) ] . acb_info = pdb_get_acct_ctrl ( pwd ) ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
DEBUG ( 5 , ( " entry idx: %d user %s, rid 0x%x, acb %x \n " , ( * num_entries ) ,
pdb_get_username ( pwd ) , pdb_get_user_rid ( pwd ) , pdb_get_acct_ctrl ( pwd ) ) ) ;
2001-02-27 21:22:39 +03:00
( * num_entries ) + + ;
}
2001-03-11 03:32:10 +03:00
pdb_endsampwent ( ) ;
2001-02-27 21:22:39 +03:00
* total_entries = * num_entries ;
return True ;
}
/*******************************************************************
This function uses the username map file and tries to map a UNIX
user name to an DOS name . ( Sort of the reverse of the
map_username ( ) function . ) Since more than one DOS name can map
to the UNIX name , to reverse the mapping you have to specify
which corresponding DOS name you want ; that ' s where the name_idx
parameter comes in . Returns the string requested or NULL if it
fails or can ' t complete the request for any reason . This doesn ' t
handle group names ( starting with ' @ ' ) or names starting with
' + ' or ' & ' . If they are encountered , they are skipped .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * unmap_unixname ( char * unix_user_name , int name_idx )
{
char * mapfile = lp_username_map ( ) ;
char * * lines ;
static pstring tok ;
int i ;
if ( ! * unix_user_name ) return NULL ;
if ( ! * mapfile ) return NULL ;
lines = file_lines_load ( mapfile , NULL , False ) ;
if ( ! lines ) {
DEBUG ( 0 , ( " unmap_unixname: can't open username map %s \n " , mapfile ) ) ;
return NULL ;
}
DEBUG ( 5 , ( " unmap_unixname: scanning username map %s, index: %d \n " , mapfile , name_idx ) ) ;
for ( i = 0 ; lines [ i ] ; i + + ) {
char * unixname = lines [ i ] ;
char * dosname = strchr ( unixname , ' = ' ) ;
if ( ! dosname )
continue ;
* dosname + + = 0 ;
while ( isspace ( * unixname ) )
unixname + + ;
if ( ' ! ' = = * unixname ) {
unixname + + ;
while ( * unixname & & isspace ( * unixname ) )
unixname + + ;
}
if ( ! * unixname | | strchr ( " #; " , * unixname ) )
continue ;
if ( strncmp ( unixname , unix_user_name , strlen ( unix_user_name ) ) )
continue ;
/* We have matched the UNIX user name */
while ( next_token ( & dosname , tok , LIST_SEP , sizeof ( tok ) ) ) {
if ( ! strchr ( " @&+ " , * tok ) ) {
name_idx - - ;
if ( name_idx < 0 ) {
break ;
}
}
}
if ( name_idx > = 0 ) {
DEBUG ( 0 , ( " unmap_unixname: index too high - not that many DOS names \n " ) ) ;
file_lines_free ( lines ) ;
return NULL ;
} else {
file_lines_free ( lines ) ;
return tok ;
}
}
DEBUG ( 0 , ( " unmap_unixname: Couldn't find the UNIX user name \n " ) ) ;
file_lines_free ( lines ) ;
return NULL ;
}
/*******************************************************************
This function sets up a list of users taken from the list of
users that UNIX knows about , as well as all the user names that
Samba maps to a valid UNIX user name . ( This should work with
/ etc / passwd or NIS . )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL get_passwd_entries ( SAM_USER_INFO_21 * pw_buf ,
int start_idx ,
int * total_entries , int * num_entries ,
int max_num_entries ,
uint16 acb_mask )
{
static struct passwd * pwd = NULL ;
static uint32 pw_rid ;
static BOOL orig_done = False ;
static int current_idx = 0 ;
static int mapped_idx = 0 ;
char * sep ;
DEBUG ( 5 , ( " get_passwd_entries: retrieving a list of UNIX users \n " ) ) ;
( * num_entries ) = 0 ;
( * total_entries ) = 0 ;
/* Skip all this stuff if we're in appliance mode */
if ( lp_hide_local_users ( ) ) goto done ;
if ( pw_buf = = NULL ) return False ;
if ( current_idx = = 0 ) {
sys_setpwent ( ) ;
}
/* These two cases are inefficient, but should be called very rarely */
/* they are the cases where the starting index isn't picking up */
/* where we left off last time. It is efficient when it starts over */
/* at zero though. */
if ( start_idx > current_idx ) {
/* We aren't far enough; advance to start_idx */
while ( current_idx < = start_idx ) {
char * unmap_name ;
if ( ! orig_done ) {
if ( ( pwd = sys_getpwent ( ) ) = = NULL ) break ;
current_idx + + ;
orig_done = True ;
}
while ( ( ( unmap_name = unmap_unixname ( pwd - > pw_name , mapped_idx ) ) ! = NULL ) & &
( current_idx < start_idx ) ) {
current_idx + + ;
mapped_idx + + ;
}
if ( unmap_name = = NULL ) {
orig_done = False ;
mapped_idx = 0 ;
}
}
} else if ( start_idx < current_idx ) {
/* We are already too far; start over and advance to start_idx */
sys_endpwent ( ) ;
sys_setpwent ( ) ;
current_idx = 0 ;
mapped_idx = 0 ;
orig_done = False ;
while ( current_idx < start_idx ) {
char * unmap_name ;
if ( ! orig_done ) {
if ( ( pwd = sys_getpwent ( ) ) = = NULL ) break ;
current_idx + + ;
orig_done = True ;
}
while ( ( ( unmap_name = unmap_unixname ( pwd - > pw_name , mapped_idx ) ) ! = NULL ) & &
( current_idx < start_idx ) ) {
current_idx + + ;
mapped_idx + + ;
}
if ( unmap_name = = NULL ) {
orig_done = False ;
mapped_idx = 0 ;
}
}
}
sep = lp_winbind_separator ( ) ;
/* now current_idx == start_idx */
while ( ( * num_entries ) < max_num_entries ) {
int user_name_len ;
char * unmap_name ;
/* This does the original UNIX user itself */
if ( ! orig_done ) {
if ( ( pwd = sys_getpwent ( ) ) = = NULL ) break ;
/* Don't enumerate winbind users as they are not local */
if ( strchr ( pwd - > pw_name , * sep ) ! = NULL ) {
continue ;
}
user_name_len = strlen ( pwd - > pw_name ) ;
/* skip the trust account stored in the /etc/passwd file */
if ( pwd - > pw_name [ user_name_len - 1 ] = = ' $ ' )
continue ;
pw_rid = pdb_uid_to_user_rid ( pwd - > pw_uid ) ;
ZERO_STRUCTP ( & pw_buf [ ( * num_entries ) ] ) ;
init_unistr2 ( & pw_buf [ ( * num_entries ) ] . uni_user_name , pwd - > pw_name , user_name_len ) ;
init_uni_hdr ( & pw_buf [ ( * num_entries ) ] . hdr_user_name , user_name_len ) ;
pw_buf [ ( * num_entries ) ] . user_rid = pw_rid ;
memset ( ( char * ) pw_buf [ ( * num_entries ) ] . nt_pwd , ' \0 ' , 16 ) ;
pw_buf [ ( * num_entries ) ] . acb_info = ACB_NORMAL ;
DEBUG ( 5 , ( " get_passwd_entries: entry idx %d user %s, rid 0x%x \n " , ( * num_entries ) , pwd - > pw_name , pw_rid ) ) ;
( * num_entries ) + + ;
( * total_entries ) + + ;
current_idx + + ;
orig_done = True ;
}
/* This does all the user names that map to the UNIX user */
while ( ( ( unmap_name = unmap_unixname ( pwd - > pw_name , mapped_idx ) ) ! = NULL ) & &
( * num_entries < max_num_entries ) ) {
user_name_len = strlen ( unmap_name ) ;
ZERO_STRUCTP ( & pw_buf [ ( * num_entries ) ] ) ;
init_unistr2 ( & pw_buf [ ( * num_entries ) ] . uni_user_name , unmap_name , user_name_len ) ;
init_uni_hdr ( & pw_buf [ ( * num_entries ) ] . hdr_user_name , user_name_len ) ;
pw_buf [ ( * num_entries ) ] . user_rid = pw_rid ;
memset ( ( char * ) pw_buf [ ( * num_entries ) ] . nt_pwd , ' \0 ' , 16 ) ;
pw_buf [ ( * num_entries ) ] . acb_info = ACB_NORMAL ;
DEBUG ( 5 , ( " get_passwd_entries: entry idx %d user %s, rid 0x%x \n " , ( * num_entries ) , pwd - > pw_name , pw_rid ) ) ;
( * num_entries ) + + ;
( * total_entries ) + + ;
current_idx + + ;
mapped_idx + + ;
}
if ( unmap_name = = NULL ) {
/* done with 'aliases', go on to next UNIX user */
orig_done = False ;
mapped_idx = 0 ;
}
}
if ( pwd = = NULL ) {
/* totally done, reset everything */
sys_endpwent ( ) ;
current_idx = 0 ;
mapped_idx = 0 ;
}
done :
return ( * num_entries ) > 0 ;
}
/*******************************************************************
_samr_close_hnd
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_close_hnd ( pipes_struct * p , SAMR_Q_CLOSE_HND * q_u , SAMR_R_CLOSE_HND * r_u )
{
r_u - > status = NT_STATUS_NOPROBLEMO ;
/* close the policy handle */
2001-03-11 03:32:10 +03:00
if ( ! close_policy_hnd ( p , & q_u - > pol ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_NAME_INVALID ;
DEBUG ( 5 , ( " samr_reply_close_hnd: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
samr_reply_open_domain
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_open_domain ( pipes_struct * p , SAMR_Q_OPEN_DOMAIN * q_u , SAMR_R_OPEN_DOMAIN * r_u )
{
2001-03-11 03:32:10 +03:00
struct samr_info * info ;
2001-02-27 21:22:39 +03:00
r_u - > status = NT_STATUS_NOPROBLEMO ;
/* find the connection policy handle. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , NULL ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
/* associate the domain SID with the (unique) handle. */
2001-03-11 03:32:10 +03:00
if ( ( info = ( struct samr_info * ) malloc ( sizeof ( struct samr_info ) ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
info - > sid = q_u - > dom_sid . sid ;
/* get a (unique) handle. open a policy on it. */
if ( ! create_policy_hnd ( p , & r_u - > domain_pol , free_samr_info , ( void * ) info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
DEBUG ( 5 , ( " samr_open_domain: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
2001-03-11 03:32:10 +03:00
static uint32 get_lsa_policy_samr_rid ( struct samr_info * info )
{
if ( ! info ) {
DEBUG ( 3 , ( " Error getting policy \n " ) ) ;
return 0xffffffff ;
}
return info - > sid . sub_auths [ info - > sid . num_auths - 1 ] ;
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
_samr_get_usrdom_pwinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_get_usrdom_pwinfo ( pipes_struct * p , SAMR_Q_GET_USRDOM_PWINFO * q_u , SAMR_R_GET_USRDOM_PWINFO * r_u )
{
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
r_u - > status = NT_STATUS_NOPROBLEMO ;
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > user_pol , ( void * * ) & info ) ) {
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
}
/* find the user's rid */
2001-03-11 03:32:10 +03:00
if ( get_lsa_policy_samr_rid ( info ) = = 0xffffffff ) {
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_TYPE_MISMATCH ;
}
init_samr_r_get_usrdom_pwinfo ( r_u , NT_STATUS_NOPROBLEMO ) ;
DEBUG ( 5 , ( " _samr_get_usrdom_pwinfo: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
samr_make_usr_obj_sd
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static uint32 samr_make_usr_obj_sd ( TALLOC_CTX * ctx , SEC_DESC_BUF * * buf , DOM_SID * usr_sid )
{
extern DOM_SID global_sid_Builtin ;
extern DOM_SID global_sid_World ;
DOM_SID adm_sid ;
DOM_SID act_sid ;
SEC_ACE ace [ 4 ] ;
SEC_ACCESS mask ;
SEC_ACL * psa = NULL ;
SEC_DESC * psd = NULL ;
size_t sd_size ;
sid_copy ( & adm_sid , & global_sid_Builtin ) ;
sid_append_rid ( & adm_sid , BUILTIN_ALIAS_RID_ADMINS ) ;
sid_copy ( & act_sid , & global_sid_Builtin ) ;
sid_append_rid ( & act_sid , BUILTIN_ALIAS_RID_ACCOUNT_OPS ) ;
init_sec_access ( & mask , 0x2035b ) ;
init_sec_ace ( & ace [ 0 ] , & global_sid_World , SEC_ACE_TYPE_ACCESS_ALLOWED , mask , 0 ) ;
init_sec_access ( & mask , 0xf07ff ) ;
init_sec_ace ( & ace [ 1 ] , & adm_sid , SEC_ACE_TYPE_ACCESS_ALLOWED , mask , 0 ) ;
init_sec_ace ( & ace [ 2 ] , & act_sid , SEC_ACE_TYPE_ACCESS_ALLOWED , mask , 0 ) ;
init_sec_access ( & mask , 0x20044 ) ;
init_sec_ace ( & ace [ 3 ] , usr_sid , SEC_ACE_TYPE_ACCESS_ALLOWED , mask , 0 ) ;
if ( ( psa = make_sec_acl ( ctx , NT4_ACL_REVISION , 4 , ace ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
if ( ( psd = make_sec_desc ( ctx , SEC_DESC_REVISION , NULL , NULL , NULL , psa , & sd_size ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
if ( ( * buf = make_sec_desc_buf ( ctx , sd_size , psd ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
return NT_STATUS_NOPROBLEMO ;
}
2001-03-11 03:32:10 +03:00
static BOOL get_lsa_policy_samr_sid ( pipes_struct * p , POLICY_HND * pol , DOM_SID * sid )
{
struct samr_info * info = NULL ;
/* find the policy handle. open a policy on it. */
if ( ! find_policy_by_hnd ( p , pol , ( void * * ) & info ) )
return False ;
if ( ! info )
return False ;
* sid = info - > sid ;
return True ;
}
2001-02-27 21:22:39 +03:00
/*******************************************************************
_samr_query_sec_obj
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_sec_obj ( pipes_struct * p , SAMR_Q_QUERY_SEC_OBJ * q_u , SAMR_R_QUERY_SEC_OBJ * r_u )
{
DOM_SID pol_sid ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
/* Get the SID. */
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & q_u - > user_pol , & pol_sid ) )
return NT_STATUS_INVALID_HANDLE ;
2001-02-27 21:22:39 +03:00
r_u - > status = samr_make_usr_obj_sd ( p - > mem_ctx , & r_u - > buf , & pol_sid ) ;
if ( r_u - > status = = NT_STATUS_NOPROBLEMO )
r_u - > ptr = 1 ;
return r_u - > status ;
}
/*******************************************************************
makes a SAM_ENTRY / UNISTR2 * structure from a user list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void make_user_sam_entry_list ( TALLOC_CTX * ctx , SAM_ENTRY * * sam_pp , UNISTR2 * * uni_name_pp ,
uint32 num_sam_entries , SAM_USER_INFO_21 * pass )
{
uint32 i ;
SAM_ENTRY * sam ;
UNISTR2 * uni_name ;
* sam_pp = NULL ;
* uni_name_pp = NULL ;
if ( num_sam_entries = = 0 )
return ;
sam = ( SAM_ENTRY * ) talloc ( ctx , sizeof ( SAM_ENTRY ) * num_sam_entries ) ;
uni_name = ( UNISTR2 * ) talloc ( ctx , sizeof ( UNISTR2 ) * num_sam_entries ) ;
if ( sam = = NULL | | uni_name = = NULL ) {
DEBUG ( 0 , ( " NULL pointers in SAMR_R_QUERY_DISPINFO \n " ) ) ;
return ;
}
for ( i = 0 ; i < num_sam_entries ; i + + ) {
int len = pass [ i ] . uni_user_name . uni_str_len ;
init_sam_entry ( & sam [ i ] , len , pass [ i ] . user_rid ) ;
copy_unistr2 ( & uni_name [ i ] , & pass [ i ] . uni_user_name ) ;
}
* sam_pp = sam ;
* uni_name_pp = uni_name ;
}
/*******************************************************************
samr_reply_enum_dom_users
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_enum_dom_users ( pipes_struct * p , SAMR_Q_ENUM_DOM_USERS * q_u , SAMR_R_ENUM_DOM_USERS * r_u )
{
SAM_USER_INFO_21 pass [ MAX_SAM_ENTRIES ] ;
int num_entries = 0 ;
int total_entries = 0 ;
BOOL ret ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , NULL ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
DEBUG ( 5 , ( " _samr_enum_dom_users: %d \n " , __LINE__ ) ) ;
become_root ( ) ;
ret = get_sampwd_entries ( pass , q_u - > start_idx , & total_entries , & num_entries ,
MAX_SAM_ENTRIES , q_u - > acb_mask ) ;
unbecome_root ( ) ;
if ( ! ret )
return NT_STATUS_ACCESS_DENIED ;
/*
* Note from JRA . total_entries is not being used here . Currently if there is a
* large user base then it looks like NT will enumerate until get_sampwd_entries
* returns False due to num_entries being zero . This will cause an access denied
* return . I don ' t think this is right and needs further investigation . Note that
* this is also the same in the TNG code ( I don ' t think that has been tested with
* a very large user list as MAX_SAM_ENTRIES is set to 600 ) .
*
* I also think that one of the ' num_entries ' return parameters is probably
* the " max entries " parameter - but in the TNG code they ' re all currently set to the same
* value ( again I think this is wrong ) .
*/
make_user_sam_entry_list ( p - > mem_ctx , & r_u - > sam , & r_u - > uni_acct_name , num_entries , pass ) ;
init_samr_r_enum_dom_users ( r_u , q_u - > start_idx + num_entries , num_entries ) ;
DEBUG ( 5 , ( " _samr_enum_dom_users: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
makes a SAM_ENTRY / UNISTR2 * structure from a group list .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void make_group_sam_entry_list ( TALLOC_CTX * ctx , SAM_ENTRY * * sam_pp , UNISTR2 * * uni_name_pp ,
uint32 num_sam_entries , DOMAIN_GRP * grp )
{
uint32 i ;
SAM_ENTRY * sam ;
UNISTR2 * uni_name ;
* sam_pp = NULL ;
* uni_name_pp = NULL ;
if ( num_sam_entries = = 0 )
return ;
sam = ( SAM_ENTRY * ) talloc ( ctx , sizeof ( SAM_ENTRY ) * num_sam_entries ) ;
uni_name = ( UNISTR2 * ) talloc ( ctx , sizeof ( UNISTR2 ) * num_sam_entries ) ;
if ( sam = = NULL | | uni_name = = NULL ) {
DEBUG ( 0 , ( " NULL pointers in SAMR_R_QUERY_DISPINFO \n " ) ) ;
return ;
}
for ( i = 0 ; i < num_sam_entries ; i + + ) {
/*
* JRA . I think this should include the null . TNG does not .
*/
int len = strlen ( grp [ i ] . name ) + 1 ;
init_sam_entry ( & sam [ i ] , len , grp [ i ] . rid ) ;
init_unistr2 ( & uni_name [ i ] , grp [ i ] . name , len ) ;
}
* sam_pp = sam ;
* uni_name_pp = uni_name ;
}
/*******************************************************************
Get the group entries - similar to get_sampwd_entries ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL get_group_alias_entries ( DOMAIN_GRP * d_grp , DOM_SID * sid , uint32 start_idx ,
uint32 * p_num_entries , uint32 max_entries )
{
fstring sid_str ;
fstring sam_sid_str ;
uint32 num_entries = 0 ;
sid_to_string ( sid_str , sid ) ;
sid_to_string ( sam_sid_str , & global_sam_sid ) ;
* p_num_entries = 0 ;
/* well-known aliases */
if ( strequal ( sid_str , " S-1-5-32 " ) ) {
char * name ;
while ( ! lp_hide_local_users ( ) & &
num_entries < max_entries & &
( ( name = builtin_alias_rids [ num_entries ] . name ) ! = NULL ) ) {
fstrcpy ( d_grp [ num_entries ] . name , name ) ;
d_grp [ num_entries ] . rid = builtin_alias_rids [ num_entries ] . rid ;
num_entries + + ;
}
} else if ( strequal ( sid_str , sam_sid_str ) & & ! lp_hide_local_users ( ) ) {
char * name ;
char * sep ;
struct group * grp ;
sep = lp_winbind_separator ( ) ;
/* local aliases */
/* we return the UNIX groups here. This seems to be the right */
/* thing to do, since NT member servers return their local */
/* groups in the same situation. */
setgrent ( ) ;
while ( num_entries < max_entries & & ( ( grp = getgrent ( ) ) ! = NULL ) ) {
int i ;
uint32 trid ;
name = grp - > gr_name ;
/* Don't return winbind groups as they are not local! */
if ( strchr ( name , * sep ) ! = NULL )
continue ;
trid = pdb_gid_to_group_rid ( grp - > gr_gid ) ;
for ( i = 0 ; i < num_entries ; i + + )
if ( d_grp [ i ] . rid = = trid ) break ;
if ( i < num_entries )
continue ; /* rid was there, dup! */
/* JRA - added this for large group db enumeration... */
if ( start_idx > 0 ) {
/* skip the requested number of entries.
not very efficient , but hey . . .
*/
start_idx - - ;
continue ;
}
fstrcpy ( d_grp [ num_entries ] . name , name ) ;
d_grp [ num_entries ] . rid = trid ;
num_entries + + ;
}
endgrent ( ) ;
}
* p_num_entries = num_entries ;
return True ;
}
/*******************************************************************
Get the group entries - similar to get_sampwd_entries ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL get_group_domain_entries ( DOMAIN_GRP * d_grp , DOM_SID * sid , uint32 start_idx ,
uint32 * p_num_entries , uint32 max_entries )
{
fstring sid_str ;
fstring sam_sid_str ;
uint32 num_entries = 0 ;
fstring name = " Domain Admins " ;
fstring comment = " Just to make it work ! " ;
sid_to_string ( sid_str , sid ) ;
sid_to_string ( sam_sid_str , & global_sam_sid ) ;
* p_num_entries = 0 ;
fstrcpy ( d_grp [ 0 ] . name , name ) ;
fstrcpy ( d_grp [ 0 ] . comment , comment ) ;
d_grp [ 0 ] . rid = DOMAIN_GROUP_RID_ADMINS ;
d_grp [ 0 ] . attr = SID_NAME_DOM_GRP ;
fstrcpy ( d_grp [ 1 ] . name , " Domain Users " ) ;
fstrcpy ( d_grp [ 1 ] . comment , " Just to make it work ! " ) ;
d_grp [ 1 ] . rid = DOMAIN_GROUP_RID_USERS ;
d_grp [ 1 ] . attr = SID_NAME_DOM_GRP ;
num_entries = 2 ;
* p_num_entries = num_entries ;
return True ;
}
/*******************************************************************
samr_reply_enum_dom_groups
Only reply with one group - domain admins . This must be fixed for
a real PDC . JRA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_enum_dom_groups ( pipes_struct * p , SAMR_Q_ENUM_DOM_GROUPS * q_u , SAMR_R_ENUM_DOM_GROUPS * r_u )
{
DOMAIN_GRP grp [ 2 ] ;
2001-03-11 03:32:10 +03:00
uint32 num_entries ;
2001-02-27 21:22:39 +03:00
DOM_SID sid ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & q_u - > pol , & sid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
DEBUG ( 5 , ( " samr_reply_enum_dom_groups: %d \n " , __LINE__ ) ) ;
get_group_domain_entries ( grp , & sid , q_u - > start_idx , & num_entries , MAX_SAM_ENTRIES ) ;
make_group_sam_entry_list ( p - > mem_ctx , & r_u - > sam , & r_u - > uni_grp_name , num_entries , grp ) ;
init_samr_r_enum_dom_groups ( r_u , q_u - > start_idx , num_entries ) ;
DEBUG ( 5 , ( " samr_enum_dom_groups: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
samr_reply_enum_dom_aliases
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_enum_dom_aliases ( pipes_struct * p , SAMR_Q_ENUM_DOM_ALIASES * q_u , SAMR_R_ENUM_DOM_ALIASES * r_u )
{
DOMAIN_GRP grp [ MAX_SAM_ENTRIES ] ;
2001-03-11 03:32:10 +03:00
uint32 num_entries = 0 ;
2001-02-27 21:22:39 +03:00
fstring sid_str ;
DOM_SID sid ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & q_u - > pol , & sid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
sid_to_string ( sid_str , & sid ) ;
DEBUG ( 5 , ( " samr_reply_enum_dom_aliases: sid %s \n " , sid_str ) ) ;
if ( ! get_group_alias_entries ( grp , & sid , q_u - > start_idx , & num_entries , MAX_SAM_ENTRIES ) )
return NT_STATUS_ACCESS_DENIED ;
make_group_sam_entry_list ( p - > mem_ctx , & r_u - > sam , & r_u - > uni_grp_name , num_entries , grp ) ;
init_samr_r_enum_dom_aliases ( r_u , q_u - > start_idx , num_entries ) ;
DEBUG ( 5 , ( " samr_enum_dom_aliases: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
samr_reply_query_dispinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_dispinfo ( pipes_struct * p , SAMR_Q_QUERY_DISPINFO * q_u , SAMR_R_QUERY_DISPINFO * r_u )
{
SAM_USER_INFO_21 pass [ MAX_SAM_ENTRIES ] ;
DOMAIN_GRP grps [ MAX_SAM_ENTRIES ] ;
uint16 acb_mask = ACB_NORMAL ;
2001-03-11 03:32:10 +03:00
uint32 num_entries = 0 ;
2001-02-27 21:22:39 +03:00
int orig_num_entries = 0 ;
int total_entries = 0 ;
uint32 data_size = 0 ;
DOM_SID sid ;
BOOL ret ;
SAM_DISPINFO_CTR * ctr ;
DEBUG ( 5 , ( " samr_reply_query_dispinfo: %d \n " , __LINE__ ) ) ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & q_u - > domain_pol , & sid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
/* decide how many entries to get depending on the max_entries
and max_size passed by client */
if ( q_u - > max_entries > MAX_SAM_ENTRIES )
q_u - > max_entries = MAX_SAM_ENTRIES ;
/* Get what we need from the password database */
switch ( q_u - > switch_level ) {
case 0x2 :
acb_mask = ACB_WSTRUST ;
/* Fall through */
case 0x1 :
case 0x4 :
become_root ( ) ;
#if 0
ret = get_passwd_entries ( pass , q_u - > start_idx , & total_entries , & num_entries ,
MAX_SAM_ENTRIES , acb_mask ) ;
# endif
#if 0
/*
* Which should we use here ? JRA .
*/
ret = get_sampwd_entries ( pass , q_u - > start_idx , & total_entries , & num_entries ,
MAX_SAM_ENTRIES , acb_mask ) ;
# endif
# if 1
ret = jf_get_sampwd_entries ( pass , q_u - > start_idx , & total_entries , & num_entries ,
MAX_SAM_ENTRIES , acb_mask ) ;
# endif
unbecome_root ( ) ;
if ( ! ret ) {
DEBUG ( 5 , ( " get_sampwd_entries: failed \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
break ;
case 0x3 :
case 0x5 :
ret = get_group_domain_entries ( grps , & sid , q_u - > start_idx , & num_entries , MAX_SAM_ENTRIES ) ;
if ( ! ret )
return NT_STATUS_ACCESS_DENIED ;
break ;
default :
DEBUG ( 0 , ( " _samr_query_dispinfo: Unknown info level (%u) \n " , ( unsigned int ) q_u - > switch_level ) ) ;
return NT_STATUS_INVALID_INFO_CLASS ;
}
if ( num_entries > q_u - > max_entries )
num_entries = q_u - > max_entries ;
if ( num_entries > MAX_SAM_ENTRIES ) {
num_entries = MAX_SAM_ENTRIES ;
DEBUG ( 5 , ( " limiting number of entries to %d \n " , num_entries ) ) ;
}
data_size = q_u - > max_size ;
orig_num_entries = num_entries ;
ctr = ( SAM_DISPINFO_CTR * ) talloc ( p - > mem_ctx , sizeof ( SAM_DISPINFO_CTR ) ) ;
/* Now create reply structure */
switch ( q_u - > switch_level ) {
case 0x1 :
ctr - > sam . info1 = ( SAM_DISPINFO_1 * ) talloc ( p - > mem_ctx , num_entries * sizeof ( SAM_DISPINFO_1 ) ) ;
init_sam_dispinfo_1 ( ctr - > sam . info1 , & num_entries , & data_size , q_u - > start_idx , pass ) ;
break ;
case 0x2 :
ctr - > sam . info2 = ( SAM_DISPINFO_2 * ) talloc ( p - > mem_ctx , num_entries * sizeof ( SAM_DISPINFO_2 ) ) ;
init_sam_dispinfo_2 ( ctr - > sam . info2 , & num_entries , & data_size , q_u - > start_idx , pass ) ;
break ;
case 0x3 :
ctr - > sam . info3 = ( SAM_DISPINFO_3 * ) talloc ( p - > mem_ctx , num_entries * sizeof ( SAM_DISPINFO_3 ) ) ;
init_sam_dispinfo_3 ( ctr - > sam . info3 , & num_entries , & data_size , q_u - > start_idx , grps ) ;
break ;
case 0x4 :
ctr - > sam . info4 = ( SAM_DISPINFO_4 * ) talloc ( p - > mem_ctx , num_entries * sizeof ( SAM_DISPINFO_4 ) ) ;
init_sam_dispinfo_4 ( ctr - > sam . info4 , & num_entries , & data_size , q_u - > start_idx , pass ) ;
break ;
case 0x5 :
ctr - > sam . info5 = ( SAM_DISPINFO_5 * ) talloc ( p - > mem_ctx , num_entries * sizeof ( SAM_DISPINFO_5 ) ) ;
init_sam_dispinfo_5 ( ctr - > sam . info5 , & num_entries , & data_size , q_u - > start_idx , grps ) ;
break ;
default :
ctr - > sam . info = NULL ;
return NT_STATUS_INVALID_INFO_CLASS ;
}
DEBUG ( 5 , ( " _samr_query_dispinfo: %d \n " , __LINE__ ) ) ;
init_samr_r_query_dispinfo ( r_u , num_entries , data_size , q_u - > switch_level , ctr , r_u - > status ) ;
if ( num_entries < orig_num_entries ) {
return STATUS_MORE_ENTRIES ;
}
return r_u - > status ;
}
/*******************************************************************
samr_reply_query_aliasinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_aliasinfo ( pipes_struct * p , SAMR_Q_QUERY_ALIASINFO * q_u , SAMR_R_QUERY_ALIASINFO * r_u )
{
fstring alias_desc = " Local Unix group " ;
fstring alias = " " ;
enum SID_NAME_USE type ;
uint32 alias_rid ;
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
r_u - > status = NT_STATUS_NOPROBLEMO ;
DEBUG ( 5 , ( " _samr_query_aliasinfo: %d \n " , __LINE__ ) ) ;
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
2001-03-11 03:32:10 +03:00
alias_rid = get_lsa_policy_samr_rid ( info ) ;
2001-02-27 21:22:39 +03:00
if ( alias_rid = = 0xffffffff )
return NT_STATUS_NO_SUCH_ALIAS ;
if ( ! local_lookup_rid ( alias_rid , alias , & type ) )
2001-03-11 03:32:10 +03:00
return NT_STATUS_NO_SUCH_ALIAS ;
2001-02-27 21:22:39 +03:00
switch ( q_u - > switch_level ) {
case 3 :
r_u - > ptr = 1 ;
r_u - > ctr . switch_value1 = 3 ;
init_samr_alias_info3 ( & r_u - > ctr . alias . info3 , alias_desc ) ;
break ;
default :
return NT_STATUS_INVALID_INFO_CLASS ;
}
DEBUG ( 5 , ( " _samr_query_aliasinfo: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
#if 0
/*******************************************************************
samr_reply_lookup_ids
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_lookup_ids ( pipes_struct * p , SAMR_Q_LOOKUP_IDS * q_u , SAMR_R_LOOKUP_IDS * r_u )
{
uint32 rid [ MAX_SAM_ENTRIES ] ;
int num_rids = q_u - > num_sids1 ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
DEBUG ( 5 , ( " _samr_lookup_ids: %d \n " , __LINE__ ) ) ;
if ( num_rids > MAX_SAM_ENTRIES ) {
num_rids = MAX_SAM_ENTRIES ;
DEBUG ( 5 , ( " _samr_lookup_ids: truncating entries to %d \n " , num_rids ) ) ;
}
#if 0
int i ;
SMB_ASSERT_ARRAY ( q_u - > uni_user_name , num_rids ) ;
for ( i = 0 ; i < num_rids & & status = = 0 ; i + + )
{
struct sam_passwd * sam_pass ;
fstring user_name ;
fstrcpy ( user_name , unistrn2 ( q_u - > uni_user_name [ i ] . buffer ,
q_u - > uni_user_name [ i ] . uni_str_len ) ) ;
/* find the user account */
become_root ( ) ;
sam_pass = get_smb21pwd_entry ( user_name , 0 ) ;
unbecome_root ( ) ;
if ( sam_pass = = NULL )
{
status = 0xC0000000 | NT_STATUS_NO_SUCH_USER ;
rid [ i ] = 0 ;
}
else
{
rid [ i ] = sam_pass - > user_rid ;
}
}
# endif
num_rids = 1 ;
rid [ 0 ] = BUILTIN_ALIAS_RID_USERS ;
init_samr_r_lookup_ids ( & r_u , num_rids , rid , NT_STATUS_NOPROBLEMO ) ;
DEBUG ( 5 , ( " _samr_lookup_ids: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
# endif
/*******************************************************************
_samr_lookup_names
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_lookup_names ( pipes_struct * p , SAMR_Q_LOOKUP_NAMES * q_u , SAMR_R_LOOKUP_NAMES * r_u )
{
uint32 rid [ MAX_SAM_ENTRIES ] ;
enum SID_NAME_USE type [ MAX_SAM_ENTRIES ] ;
int i ;
int num_rids = q_u - > num_names1 ;
DOM_SID pol_sid ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
DEBUG ( 5 , ( " _samr_lookup_names: %d \n " , __LINE__ ) ) ;
ZERO_ARRAY ( rid ) ;
ZERO_ARRAY ( type ) ;
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & q_u - > pol , & pol_sid ) ) {
2001-02-27 21:22:39 +03:00
init_samr_r_lookup_names ( p - > mem_ctx , r_u , 0 , NULL , NULL , NT_STATUS_OBJECT_TYPE_MISMATCH ) ;
return r_u - > status ;
}
if ( num_rids > MAX_SAM_ENTRIES ) {
num_rids = MAX_SAM_ENTRIES ;
DEBUG ( 5 , ( " _samr_lookup_names: truncating entries to %d \n " , num_rids ) ) ;
}
SMB_ASSERT_ARRAY ( q_u - > uni_name , num_rids ) ;
for ( i = 0 ; i < num_rids ; i + + ) {
fstring name ;
r_u - > status = NT_STATUS_NONE_MAPPED ;
rid [ i ] = 0xffffffff ;
type [ i ] = SID_NAME_UNKNOWN ;
fstrcpy ( name , dos_unistrn2 ( q_u - > uni_name [ i ] . buffer , q_u - > uni_name [ i ] . uni_str_len ) ) ;
if ( sid_equal ( & pol_sid , & global_sam_sid ) ) {
DOM_SID sid ;
if ( local_lookup_name ( global_myname , name , & sid , & type [ i ] ) ) {
sid_split_rid ( & sid , & rid [ i ] ) ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
}
}
}
2001-03-11 03:32:10 +03:00
init_samr_r_lookup_names ( p - > mem_ctx , r_u , num_rids , rid , ( uint32 * ) type , r_u - > status ) ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " _samr_lookup_names: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
_samr_chgpasswd_user
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_chgpasswd_user ( pipes_struct * p , SAMR_Q_CHGPASSWD_USER * q_u , SAMR_R_CHGPASSWD_USER * r_u )
{
fstring user_name ;
fstring wks ;
DEBUG ( 5 , ( " _samr_chgpasswd_user: %d \n " , __LINE__ ) ) ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
fstrcpy ( user_name , dos_unistrn2 ( q_u - > uni_user_name . buffer , q_u - > uni_user_name . uni_str_len ) ) ;
fstrcpy ( wks , dos_unistrn2 ( q_u - > uni_dest_host . buffer , q_u - > uni_dest_host . uni_str_len ) ) ;
DEBUG ( 5 , ( " samr_chgpasswd_user: user: %s wks: %s \n " , user_name , wks ) ) ;
if ( ! pass_oem_change ( user_name , q_u - > lm_newpass . pass , q_u - > lm_oldhash . hash ,
q_u - > nt_newpass . pass , q_u - > nt_oldhash . hash ) )
r_u - > status = NT_STATUS_WRONG_PASSWORD ;
init_samr_r_chgpasswd_user ( r_u , r_u - > status ) ;
DEBUG ( 5 , ( " _samr_chgpasswd_user: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
makes a SAMR_R_LOOKUP_RIDS structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL make_samr_lookup_rids ( TALLOC_CTX * ctx , uint32 num_names , fstring names [ ] ,
UNIHDR * * pp_hdr_name , UNISTR2 * * pp_uni_name )
{
uint32 i ;
UNIHDR * hdr_name ;
UNISTR2 * uni_name ;
* pp_uni_name = NULL ;
* pp_hdr_name = NULL ;
if ( num_names ! = 0 ) {
hdr_name = ( UNIHDR * ) talloc ( ctx , sizeof ( UNIHDR ) * num_names ) ;
if ( hdr_name = = NULL )
return False ;
uni_name = ( UNISTR2 * ) talloc ( ctx , sizeof ( UNISTR2 ) * num_names ) ;
if ( uni_name = = NULL )
return False ;
}
for ( i = 0 ; i < num_names ; i + + ) {
int len = names [ i ] ! = NULL ? strlen ( names [ i ] ) : 0 ;
DEBUG ( 10 , ( " names[%d]:%s \n " , i , names [ i ] ) ) ;
init_uni_hdr ( & hdr_name [ i ] , len ) ;
init_unistr2 ( & uni_name [ i ] , names [ i ] , len ) ;
}
* pp_uni_name = uni_name ;
* pp_hdr_name = hdr_name ;
return True ;
}
/*******************************************************************
_samr_lookup_rids
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_lookup_rids ( pipes_struct * p , SAMR_Q_LOOKUP_RIDS * q_u , SAMR_R_LOOKUP_RIDS * r_u )
{
fstring group_names [ MAX_SAM_ENTRIES ] ;
uint32 group_attrs [ MAX_SAM_ENTRIES ] ;
UNIHDR * hdr_name = NULL ;
UNISTR2 * uni_name = NULL ;
DOM_SID pol_sid ;
int num_rids = q_u - > num_rids1 ;
int i ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
DEBUG ( 5 , ( " _samr_lookup_rids: %d \n " , __LINE__ ) ) ;
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & q_u - > pol , & pol_sid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
if ( num_rids > MAX_SAM_ENTRIES ) {
num_rids = MAX_SAM_ENTRIES ;
DEBUG ( 5 , ( " _samr_lookup_rids: truncating entries to %d \n " , num_rids ) ) ;
}
r_u - > status = NT_STATUS_NONE_MAPPED ;
for ( i = 0 ; i < num_rids ; i + + ) {
fstring tmpname ;
fstring domname ;
DOM_SID sid ;
enum SID_NAME_USE type ;
group_attrs [ i ] = SID_NAME_UNKNOWN ;
* group_names [ i ] = ' \0 ' ;
if ( sid_equal ( & pol_sid , & global_sam_sid ) ) {
sid_copy ( & sid , & pol_sid ) ;
sid_append_rid ( & sid , q_u - > rid [ i ] ) ;
if ( lookup_sid ( & sid , domname , tmpname , & type ) ) {
r_u - > status = NT_STATUS_NOPROBLEMO ;
group_attrs [ i ] = ( uint32 ) type ;
fstrcpy ( group_names [ i ] , tmpname ) ;
}
}
}
if ( ! make_samr_lookup_rids ( p - > mem_ctx , num_rids , group_names , & hdr_name , & uni_name ) )
return NT_STATUS_NO_MEMORY ;
init_samr_r_lookup_rids ( r_u , num_rids , hdr_name , uni_name , group_attrs ) ;
DEBUG ( 5 , ( " _samr_lookup_rids: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
_api_samr_open_user
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _api_samr_open_user ( pipes_struct * p , SAMR_Q_OPEN_USER * q_u , SAMR_R_OPEN_USER * r_u )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * sampass ;
2001-02-27 21:22:39 +03:00
DOM_SID sid ;
POLICY_HND domain_pol = q_u - > domain_pol ;
uint32 user_rid = q_u - > user_rid ;
POLICY_HND * user_pol = & r_u - > user_pol ;
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
r_u - > status = NT_STATUS_NO_PROBLEMO ;
/* find the domain policy handle. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & domain_pol , NULL ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
become_root ( ) ;
2001-03-11 03:32:10 +03:00
sampass = pdb_getsampwrid ( user_rid ) ;
2001-02-27 21:22:39 +03:00
unbecome_root ( ) ;
/* check that the RID exists in our domain. */
2001-03-11 03:32:10 +03:00
if ( sampass = = NULL )
2001-02-27 21:22:39 +03:00
return NT_STATUS_NO_SUCH_USER ;
/* Get the domain SID stored in the domain policy */
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & domain_pol , & sid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
/* append the user's RID to it */
2001-03-11 03:32:10 +03:00
if ( ! sid_append_rid ( & sid , user_rid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_NO_SUCH_USER ;
2001-03-11 03:32:10 +03:00
/* associate the user's SID with the new handle. */
if ( ( info = ( struct samr_info * ) malloc ( sizeof ( struct samr_info ) ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
info - > sid = sid ;
/* get a (unique) handle. open a policy on it. */
if ( ! create_policy_hnd ( p , user_pol , free_samr_info , ( void * ) info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
return r_u - > status ;
}
/*************************************************************************
get_user_info_10
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL get_user_info_10 ( SAM_USER_INFO_10 * id10 , uint32 user_rid )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * smbpass ;
2001-02-27 21:22:39 +03:00
if ( ! pdb_rid_is_user ( user_rid ) ) {
DEBUG ( 4 , ( " RID 0x%x is not a user RID \n " , user_rid ) ) ;
return False ;
}
become_root ( ) ;
2001-03-11 03:32:10 +03:00
smbpass = pdb_getsampwrid ( user_rid ) ;
2001-02-27 21:22:39 +03:00
unbecome_root ( ) ;
2001-03-11 03:32:10 +03:00
if ( smbpass = = NULL ) {
2001-02-27 21:22:39 +03:00
DEBUG ( 4 , ( " User 0x%x not found \n " , user_rid ) ) ;
return False ;
}
2001-03-11 03:32:10 +03:00
DEBUG ( 3 , ( " User:[%s] \n " , pdb_get_username ( smbpass ) ) ) ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
init_sam_user_info10 ( id10 , pdb_get_acct_ctrl ( smbpass ) ) ;
2001-02-27 21:22:39 +03:00
return True ;
}
/*************************************************************************
get_user_info_12
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL get_user_info_12 ( SAM_USER_INFO_12 * id12 , uint32 user_rid )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * smbpass ;
2001-02-27 21:22:39 +03:00
become_root ( ) ;
2001-03-11 03:32:10 +03:00
smbpass = pdb_getsampwrid ( user_rid ) ;
2001-02-27 21:22:39 +03:00
unbecome_root ( ) ;
2001-03-11 03:32:10 +03:00
if ( smbpass = = NULL ) {
2001-02-27 21:22:39 +03:00
DEBUG ( 4 , ( " User 0x%x not found \n " , user_rid ) ) ;
return False ;
}
2001-03-11 03:32:10 +03:00
DEBUG ( 3 , ( " User:[%s] 0x%x \n " , pdb_get_username ( smbpass ) , pdb_get_acct_ctrl ( smbpass ) ) ) ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
if ( pdb_get_acct_ctrl ( smbpass ) & ACB_DISABLED )
2001-02-27 21:22:39 +03:00
return False ;
2001-03-11 03:32:10 +03:00
init_sam_user_info12 ( id12 , pdb_get_lanman_passwd ( smbpass ) , pdb_get_nt_passwd ( smbpass ) ) ;
2001-02-27 21:22:39 +03:00
return True ;
}
/*************************************************************************
get_user_info_21
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL get_user_info_21 ( SAM_USER_INFO_21 * id21 , uint32 user_rid )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * sampass ;
2001-02-27 21:22:39 +03:00
if ( ! pdb_rid_is_user ( user_rid ) ) {
DEBUG ( 4 , ( " RID 0x%x is not a user RID \n " , user_rid ) ) ;
return False ;
}
become_root ( ) ;
2001-03-11 03:32:10 +03:00
sampass = pdb_getsampwrid ( user_rid ) ;
2001-02-27 21:22:39 +03:00
unbecome_root ( ) ;
2001-03-11 03:32:10 +03:00
if ( sampass = = NULL ) {
2001-02-27 21:22:39 +03:00
DEBUG ( 4 , ( " User 0x%x not found \n " , user_rid ) ) ;
return False ;
}
2001-03-11 03:32:10 +03:00
DEBUG ( 3 , ( " User:[%s] \n " , pdb_get_username ( sampass ) ) ) ;
init_sam_user_info21A ( id21 , sampass ) ;
2001-02-27 21:22:39 +03:00
return True ;
}
/*******************************************************************
_samr_query_userinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_userinfo ( pipes_struct * p , SAMR_Q_QUERY_USERINFO * q_u , SAMR_R_QUERY_USERINFO * r_u )
{
SAM_USERINFO_CTR * ctr ;
uint32 rid = 0 ;
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
r_u - > status = NT_STATUS_NO_PROBLEMO ;
/* search for the handle */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
/* find the user's rid */
2001-03-11 03:32:10 +03:00
if ( ( rid = get_lsa_policy_samr_rid ( info ) ) = = 0xffffffff )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_TYPE_MISMATCH ;
DEBUG ( 5 , ( " _samr_query_userinfo: rid:0x%x \n " , rid ) ) ;
ctr = ( SAM_USERINFO_CTR * ) talloc ( p - > mem_ctx , sizeof ( SAM_USERINFO_CTR ) ) ;
if ( ! ctr )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( ctr ) ;
/* ok! user info levels (lots: see MSDEV help), off we go... */
ctr - > switch_value = q_u - > switch_value ;
switch ( q_u - > switch_value ) {
case 0x10 :
ctr - > info . id10 = ( SAM_USER_INFO_10 * ) talloc ( p - > mem_ctx , sizeof ( SAM_USER_INFO_10 ) ) ;
if ( ctr - > info . id10 = = NULL )
return NT_STATUS_NO_MEMORY ;
if ( ! get_user_info_10 ( ctr - > info . id10 , rid ) )
return NT_STATUS_NO_SUCH_USER ;
break ;
#if 0
/* whoops - got this wrong. i think. or don't understand what's happening. */
case 0x11 :
{
NTTIME expire ;
info = ( void * ) & id11 ;
expire . low = 0xffffffff ;
expire . high = 0x7fffffff ;
ctr - > info . id = ( SAM_USER_INFO_11 * ) talloc ( p - > mem_ctx ,
sizeof
( * ctr - >
info .
id11 ) ) ;
init_sam_user_info11 ( ctr - > info . id11 , & expire ,
" BROOKFIELDS$ " , /* name */
0x03ef , /* user rid */
0x201 , /* group rid */
0x0080 ) ; /* acb info */
break ;
}
# endif
case 0x12 :
ctr - > info . id12 = ( SAM_USER_INFO_12 * ) talloc ( p - > mem_ctx , sizeof ( SAM_USER_INFO_12 ) ) ;
if ( ctr - > info . id12 = = NULL )
return NT_STATUS_NO_MEMORY ;
if ( ! get_user_info_12 ( ctr - > info . id12 , rid ) )
return NT_STATUS_NO_SUCH_USER ;
break ;
case 21 :
ctr - > info . id21 = ( SAM_USER_INFO_21 * ) talloc ( p - > mem_ctx , sizeof ( SAM_USER_INFO_21 ) ) ;
if ( ctr - > info . id21 = = NULL )
return NT_STATUS_NO_MEMORY ;
if ( ! get_user_info_21 ( ctr - > info . id21 , rid ) )
return NT_STATUS_NO_SUCH_USER ;
break ;
default :
return NT_STATUS_INVALID_INFO_CLASS ;
}
init_samr_r_query_userinfo ( r_u , ctr , r_u - > status ) ;
DEBUG ( 5 , ( " _samr_query_userinfo: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
samr_reply_query_usergroups
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_usergroups ( pipes_struct * p , SAMR_Q_QUERY_USERGROUPS * q_u , SAMR_R_QUERY_USERGROUPS * r_u )
{
struct sam_passwd * sam_pass ;
DOM_GID * gids = NULL ;
int num_groups = 0 ;
pstring groups ;
uint32 rid ;
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
r_u - > status = NT_STATUS_NO_PROBLEMO ;
DEBUG ( 5 , ( " _samr_query_usergroups: %d \n " , __LINE__ ) ) ;
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
/* find the user's rid */
2001-03-11 03:32:10 +03:00
if ( ( rid = get_lsa_policy_samr_rid ( info ) ) = = 0xffffffff )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_TYPE_MISMATCH ;
become_root ( ) ;
2001-03-11 03:32:10 +03:00
sam_pass = pdb_getsampwrid ( rid ) ;
2001-02-27 21:22:39 +03:00
unbecome_root ( ) ;
if ( sam_pass = = NULL )
return NT_STATUS_NO_SUCH_USER ;
2001-03-11 03:32:10 +03:00
get_domain_user_groups ( groups , pdb_get_username ( sam_pass ) ) ;
2001-02-27 21:22:39 +03:00
gids = NULL ;
num_groups = make_dom_gids ( p - > mem_ctx , groups , & gids ) ;
/* construct the response. lkclXXXX: gids are not copied! */
init_samr_r_query_usergroups ( r_u , num_groups , gids , r_u - > status ) ;
DEBUG ( 5 , ( " _samr_query_usergroups: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
_samr_query_dom_info
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_dom_info ( pipes_struct * p , SAMR_Q_QUERY_DOMAIN_INFO * q_u , SAMR_R_QUERY_DOMAIN_INFO * r_u )
{
SAM_UNK_CTR * ctr ;
if ( ( ctr = ( SAM_UNK_CTR * ) talloc ( p - > mem_ctx , sizeof ( SAM_UNK_CTR ) ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( ctr ) ;
r_u - > status = NT_STATUS_NO_PROBLEMO ;
DEBUG ( 5 , ( " _samr_query_dom_info: %d \n " , __LINE__ ) ) ;
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > domain_pol , NULL ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
switch ( q_u - > switch_value ) {
case 0x01 :
init_unk_info1 ( & ctr - > info . inf1 ) ;
break ;
case 0x02 :
/* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */
init_unk_info2 ( & ctr - > info . inf2 , global_myworkgroup , global_myname , ( uint32 ) time ( NULL ) ) ;
break ;
case 0x03 :
init_unk_info3 ( & ctr - > info . inf3 ) ;
break ;
case 0x06 :
init_unk_info6 ( & ctr - > info . inf6 ) ;
break ;
case 0x07 :
init_unk_info7 ( & ctr - > info . inf7 ) ;
break ;
case 0x0c :
init_unk_info12 ( & ctr - > info . inf12 ) ;
break ;
default :
return NT_STATUS_INVALID_INFO_CLASS ;
}
init_samr_r_query_dom_info ( r_u , q_u - > switch_value , ctr , NT_STATUS_NOPROBLEMO ) ;
DEBUG ( 5 , ( " _samr_query_dom_info: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/*******************************************************************
_api_samr_create_user
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _api_samr_create_user ( pipes_struct * p , SAMR_Q_CREATE_USER * q_u , SAMR_R_CREATE_USER * r_u )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * sam_pass ;
2001-02-27 21:22:39 +03:00
fstring mach_acct ;
pstring err_str ;
pstring msg_str ;
int local_flags = 0 ;
DOM_SID sid ;
pstring add_script ;
POLICY_HND dom_pol = q_u - > domain_pol ;
UNISTR2 user_account = q_u - > uni_name ;
uint16 acb_info = q_u - > acb_info ;
POLICY_HND * user_pol = & r_u - > user_pol ;
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & dom_pol , NULL ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
/* find the machine account: tell the caller if it exists.
lkclXXXX i have * no * idea if this is a problem or not
or even if you are supposed to construct a different
reply if the account already exists . . .
*/
fstrcpy ( mach_acct , dos_unistrn2 ( user_account . buffer , user_account . uni_str_len ) ) ;
strlower ( mach_acct ) ;
become_root ( ) ;
2001-03-11 03:32:10 +03:00
sam_pass = pdb_getsampwnam ( mach_acct ) ;
2001-02-27 21:22:39 +03:00
unbecome_root ( ) ;
if ( sam_pass ! = NULL ) {
/* machine account exists: say so */
return NT_STATUS_USER_EXISTS ;
}
local_flags = LOCAL_ADD_USER | LOCAL_DISABLE_USER | LOCAL_SET_NO_PASSWORD ;
local_flags | = ( acb_info & ACB_WSTRUST ) ? LOCAL_TRUST_ACCOUNT : 0 ;
/*
* NB . VERY IMPORTANT ! This call must be done as the current pipe user ,
* * NOT * surrounded by a become_root ( ) / unbecome_root ( ) call . This ensures
* that only people with write access to the smbpasswd file will be able
* to create a user . JRA .
*/
/*
* add the user in the / etc / passwd file or the unix authority system .
* We don ' t check if the smb_create_user ( ) function succed or not for 2 reasons :
* a ) local_password_change ( ) checks for us if the / etc / passwd account really exists
* b ) smb_create_user ( ) would return an error if the account already exists
* and as it could return an error also if it can ' t create the account , it would be tricky .
*
* So we go the easy way , only check after if the account exists .
* JFM ( 2 / 3 / 2001 ) , to clear any possible bad understanding ( - :
*/
pstrcpy ( add_script , lp_adduser_script ( ) ) ;
if ( * add_script )
smb_create_user ( mach_acct , NULL ) ;
/* add the user in the smbpasswd file or the Samba authority database */
if ( ! local_password_change ( mach_acct , local_flags , NULL , err_str ,
sizeof ( err_str ) , msg_str , sizeof ( msg_str ) ) )
{
DEBUG ( 0 , ( " %s \n " , err_str ) ) ;
2001-03-11 03:32:10 +03:00
close_policy_hnd ( p , user_pol ) ;
2001-02-27 21:22:39 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
become_root ( ) ;
2001-03-11 03:32:10 +03:00
sam_pass = pdb_getsampwnam ( mach_acct ) ;
2001-02-27 21:22:39 +03:00
unbecome_root ( ) ;
if ( sam_pass = = NULL ) {
/* account doesn't exist: say so */
2001-03-11 03:32:10 +03:00
close_policy_hnd ( p , user_pol ) ;
2001-02-27 21:22:39 +03:00
return NT_STATUS_ACCESS_DENIED ;
}
/* Get the domain SID stored in the domain policy */
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & dom_pol , & sid ) ) {
close_policy_hnd ( p , user_pol ) ;
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
}
/* append the user's RID to it */
2001-03-11 03:32:10 +03:00
if ( ! sid_append_rid ( & sid , pdb_get_user_rid ( sam_pass ) ) ) {
close_policy_hnd ( p , user_pol ) ;
2001-02-27 21:22:39 +03:00
return NT_STATUS_NO_SUCH_USER ;
}
2001-03-11 03:32:10 +03:00
/* associate the user's SID with the new handle. */
if ( ( info = ( struct samr_info * ) malloc ( sizeof ( struct samr_info ) ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
info - > sid = sid ;
/* get a (unique) handle. open a policy on it. */
if ( ! create_policy_hnd ( p , user_pol , free_samr_info , ( void * ) info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
r_u - > user_rid = sam_pass - > user_rid ;
r_u - > unknown_0 = 0x000703ff ;
return NT_STATUS_NO_PROBLEMO ;
}
/*******************************************************************
samr_reply_connect_anon
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_connect_anon ( pipes_struct * p , SAMR_Q_CONNECT_ANON * q_u , SAMR_R_CONNECT_ANON * r_u )
{
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
/* set up the SAMR connect_anon response */
r_u - > status = NT_STATUS_NO_PROBLEMO ;
2001-03-11 03:32:10 +03:00
/* associate the user's SID with the new handle. */
if ( ( info = ( struct samr_info * ) malloc ( sizeof ( struct samr_info ) ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
info - > status = q_u - > unknown_0 ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
/* get a (unique) handle. open a policy on it. */
if ( ! create_policy_hnd ( p , & r_u - > connect_pol , free_samr_info , ( void * ) info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
return r_u - > status ;
}
/*******************************************************************
samr_reply_connect
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_connect ( pipes_struct * p , SAMR_Q_CONNECT * q_u , SAMR_R_CONNECT * r_u )
{
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " _samr_connect: %d \n " , __LINE__ ) ) ;
r_u - > status = NT_STATUS_NO_PROBLEMO ;
2001-03-11 03:32:10 +03:00
/* associate the user's SID with the new handle. */
if ( ( info = ( struct samr_info * ) malloc ( sizeof ( struct samr_info ) ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
info - > status = q_u - > access_mask ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
/* get a (unique) handle. open a policy on it. */
if ( ! create_policy_hnd ( p , & r_u - > connect_pol , free_samr_info , ( void * ) info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
DEBUG ( 5 , ( " _samr_connect: %d \n " , __LINE__ ) ) ;
return r_u - > status ;
}
/**********************************************************************
api_samr_lookup_domain
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_lookup_domain ( pipes_struct * p , SAMR_Q_LOOKUP_DOMAIN * q_u , SAMR_R_LOOKUP_DOMAIN * r_u )
{
r_u - > status = NT_STATUS_NO_PROBLEMO ;
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > connect_pol , NULL ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
/* assume the domain name sent is our global_myname and
send global_sam_sid */
init_samr_r_lookup_domain ( r_u , & global_sam_sid , r_u - > status ) ;
return r_u - > status ;
}
/******************************************************************
makes a SAMR_R_ENUM_DOMAINS structure .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL make_enum_domains ( TALLOC_CTX * ctx , SAM_ENTRY * * pp_sam ,
UNISTR2 * * pp_uni_name , uint32 num_sam_entries , fstring doms [ ] )
{
uint32 i ;
SAM_ENTRY * sam ;
UNISTR2 * uni_name ;
DEBUG ( 5 , ( " make_enum_domains \n " ) ) ;
* pp_sam = NULL ;
* pp_uni_name = NULL ;
if ( num_sam_entries = = 0 )
return True ;
sam = ( SAM_ENTRY * ) talloc ( ctx , sizeof ( SAM_ENTRY ) * num_sam_entries ) ;
uni_name = ( UNISTR2 * ) talloc ( ctx , sizeof ( UNISTR2 ) * num_sam_entries ) ;
if ( sam = = NULL | | uni_name = = NULL )
return False ;
for ( i = 0 ; i < num_sam_entries ; i + + ) {
int len = doms [ i ] ! = NULL ? strlen ( doms [ i ] ) : 0 ;
init_sam_entry ( & sam [ i ] , len , 0 ) ;
init_unistr2 ( & uni_name [ i ] , doms [ i ] , len ) ;
}
* pp_sam = sam ;
* pp_uni_name = uni_name ;
return True ;
}
/**********************************************************************
api_samr_enum_domains
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_enum_domains ( pipes_struct * p , SAMR_Q_ENUM_DOMAINS * q_u , SAMR_R_ENUM_DOMAINS * r_u )
{
uint32 num_entries = 2 ;
fstring dom [ 2 ] ;
r_u - > status = NT_STATUS_NO_PROBLEMO ;
fstrcpy ( dom [ 0 ] , global_myworkgroup ) ;
fstrcpy ( dom [ 1 ] , " Builtin " ) ;
if ( ! make_enum_domains ( p - > mem_ctx , & r_u - > sam , & r_u - > uni_dom_name , num_entries , dom ) )
return NT_STATUS_NO_MEMORY ;
init_samr_r_enum_domains ( r_u , q_u - > start_idx + num_entries , num_entries ) ;
return r_u - > status ;
}
/*******************************************************************
api_samr_open_alias
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _api_samr_open_alias ( pipes_struct * p , SAMR_Q_OPEN_ALIAS * q_u , SAMR_R_OPEN_ALIAS * r_u )
{
DOM_SID sid ;
POLICY_HND domain_pol = q_u - > dom_pol ;
uint32 alias_rid = q_u - > rid_alias ;
POLICY_HND * alias_pol = & r_u - > pol ;
2001-03-11 03:32:10 +03:00
struct samr_info * info = NULL ;
2001-02-27 21:22:39 +03:00
r_u - > status = NT_STATUS_NO_PROBLEMO ;
/* get the domain policy. */
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & domain_pol , NULL ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
/* Get the domain SID stored in the domain policy */
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , & domain_pol , & sid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
2001-03-11 03:32:10 +03:00
/* append the alias' RID to it */
if ( ! sid_append_rid ( & sid , alias_rid ) )
return NT_STATUS_NO_SUCH_USER ;
2001-02-27 21:22:39 +03:00
/*
* we should check if the rid really exist ! ! !
* JFM .
*/
2001-03-11 03:32:10 +03:00
/* associate the user's SID with the new handle. */
if ( ( info = ( struct samr_info * ) malloc ( sizeof ( struct samr_info ) ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
ZERO_STRUCTP ( info ) ;
info - > sid = sid ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
/* get a (unique) handle. open a policy on it. */
if ( ! create_policy_hnd ( p , alias_pol , free_samr_info , ( void * ) info ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
return r_u - > status ;
}
/*******************************************************************
set_user_info_10
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL set_user_info_10 ( const SAM_USER_INFO_10 * id10 , uint32 rid )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * pwd = pdb_getsampwrid ( rid ) ;
2001-02-27 21:22:39 +03:00
if ( id10 = = NULL ) {
DEBUG ( 5 , ( " set_user_info_10: NULL id10 \n " ) ) ;
return False ;
}
2001-03-11 03:32:10 +03:00
pwd = pdb_getsampwrid ( rid ) ;
if ( ! pwd )
2001-02-27 21:22:39 +03:00
return False ;
2001-03-11 03:32:10 +03:00
pdb_set_acct_ctrl ( pwd , id10 - > acb_info ) ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
if ( ! pdb_update_sam_account ( pwd , True ) )
2001-02-27 21:22:39 +03:00
return False ;
return True ;
}
/*******************************************************************
set_user_info_12
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL set_user_info_12 ( SAM_USER_INFO_12 * id12 , uint32 rid )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * pwd = pdb_getsampwrid ( rid ) ;
2001-02-27 21:22:39 +03:00
if ( pwd = = NULL )
return False ;
2001-03-11 03:32:10 +03:00
2001-02-27 21:22:39 +03:00
if ( id12 = = NULL ) {
DEBUG ( 2 , ( " set_user_info_12: id12 is NULL \n " ) ) ;
return False ;
}
2001-03-11 03:32:10 +03:00
pdb_set_lanman_passwd ( pwd , id12 - > lm_pwd ) ;
pdb_set_nt_passwd ( pwd , id12 - > nt_pwd ) ;
if ( ! pdb_update_sam_account ( pwd , True ) )
2001-02-27 21:22:39 +03:00
return False ;
2001-03-11 03:32:10 +03:00
2001-02-27 21:22:39 +03:00
return True ;
}
/*******************************************************************
set_user_info_21
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-03-11 03:32:10 +03:00
static BOOL set_user_info_21 ( SAM_USER_INFO_21 * id21 , uint32 rid )
2001-02-27 21:22:39 +03:00
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * pwd = pdb_getsampwrid ( rid ) ;
SAM_ACCOUNT new_pwd ;
2001-02-27 21:22:39 +03:00
if ( id21 = = NULL ) {
DEBUG ( 5 , ( " set_user_info_21: NULL id21 \n " ) ) ;
return False ;
}
2001-03-11 03:32:10 +03:00
2001-02-27 21:22:39 +03:00
if ( pwd = = NULL )
return False ;
2001-03-11 03:32:10 +03:00
/* we make a copy so that we can modify stuff */
2001-02-27 21:22:39 +03:00
copy_sam_passwd ( & new_pwd , pwd ) ;
copy_id21_to_sam_passwd ( & new_pwd , id21 ) ;
2001-03-11 03:32:10 +03:00
/*
* The funny part about the previous two calls is
* that pwd still has the password hashes from the
* passdb entry . These have not been updated from
* id21 . I don ' t know if they need to be set . - - jerry
*/
/* write the change out */
if ( ! pdb_update_sam_account ( & new_pwd , True ) )
2001-02-27 21:22:39 +03:00
return False ;
2001-03-11 03:32:10 +03:00
2001-02-27 21:22:39 +03:00
return True ;
}
/*******************************************************************
set_user_info_23
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL set_user_info_23 ( SAM_USER_INFO_23 * id23 , uint32 rid )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * pwd = pdb_getsampwrid ( rid ) ;
SAM_ACCOUNT new_pwd ;
2001-03-11 03:51:54 +03:00
uint8 nt_hash [ 16 ] ;
uint8 lm_hash [ 16 ] ;
2001-03-11 03:32:10 +03:00
pstring buf ;
uint32 len ;
uint16 acct_ctrl ;
if ( id23 = = NULL ) {
DEBUG ( 5 , ( " set_user_info_23: NULL id23 \n " ) ) ;
return False ;
}
if ( pwd = = NULL )
return False ;
acct_ctrl = pdb_get_acct_ctrl ( pwd ) ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
copy_sam_passwd ( & new_pwd , pwd ) ;
copy_id23_to_sam_passwd ( & new_pwd , id23 ) ;
if ( ! decode_pw_buffer ( ( char * ) id23 - > pass , buf , 256 , & len ) )
return False ;
nt_lm_owf_gen ( buf , nt_hash , lm_hash ) ;
pdb_set_lanman_passwd ( & new_pwd , lm_hash ) ;
pdb_set_nt_passwd ( & new_pwd , nt_hash ) ;
2001-02-27 21:22:39 +03:00
/* if it's a trust account, don't update /etc/passwd */
2001-03-11 03:32:10 +03:00
if ( ( ( acct_ctrl & ACB_DOMTRUST ) = = ACB_DOMTRUST ) | |
( ( acct_ctrl & ACB_WSTRUST ) = = ACB_WSTRUST ) | |
( ( acct_ctrl & ACB_SVRTRUST ) = = ACB_SVRTRUST ) ) {
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " Changing trust account password, not updating /etc/passwd \n " ) ) ;
2001-03-11 03:32:10 +03:00
} else {
/* update the UNIX password */
2001-02-27 21:22:39 +03:00
/* update the UNIX password */
if ( lp_unix_password_sync ( ) )
2001-03-11 03:32:10 +03:00
if ( ! chgpasswd ( pdb_get_username ( & new_pwd ) , " " , buf , True ) )
2001-02-27 21:22:39 +03:00
return False ;
}
2001-03-11 03:32:10 +03:00
memset ( buf , 0 , sizeof ( buf ) ) ;
if ( ! pdb_update_sam_account ( & new_pwd , True ) )
return False ;
return True ;
2001-02-27 21:22:39 +03:00
}
/*******************************************************************
set_user_info_24
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static BOOL set_user_info_24 ( SAM_USER_INFO_24 * id24 , uint32 rid )
{
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * pwd = pdb_getsampwrid ( rid ) ;
uchar nt_hash [ 16 ] ;
uchar lm_hash [ 16 ] ;
2001-02-27 21:22:39 +03:00
uint32 len ;
pstring buf ;
2001-03-11 03:32:10 +03:00
uint16 acct_ctrl ;
2001-02-27 21:22:39 +03:00
if ( pwd = = NULL )
return False ;
2001-03-11 03:32:10 +03:00
acct_ctrl = pdb_get_acct_ctrl ( pwd ) ;
2001-02-27 21:22:39 +03:00
2001-03-11 03:32:10 +03:00
memset ( buf , 0 , sizeof ( buf ) ) ;
if ( ! decode_pw_buffer ( ( char * ) id24 - > pass , buf , 256 , & len ) )
2001-02-27 21:22:39 +03:00
return False ;
2001-03-11 03:32:10 +03:00
DEBUG ( 5 , ( " set_user_info_24:nt_lm_owf_gen \n " ) ) ;
nt_lm_owf_gen ( buf , nt_hash , lm_hash ) ;
pdb_set_lanman_passwd ( pwd , lm_hash ) ;
pdb_set_nt_passwd ( pwd , nt_hash ) ;
2001-02-27 21:22:39 +03:00
/* if it's a trust account, don't update /etc/passwd */
2001-03-11 03:32:10 +03:00
if ( ( ( acct_ctrl & ACB_DOMTRUST ) = = ACB_DOMTRUST ) | |
( ( acct_ctrl & ACB_WSTRUST ) = = ACB_WSTRUST ) | |
( ( acct_ctrl & ACB_SVRTRUST ) = = ACB_SVRTRUST ) ) {
2001-02-27 21:22:39 +03:00
DEBUG ( 5 , ( " Changing trust account password, not updating /etc/passwd \n " ) ) ;
} else {
/* update the UNIX password */
2001-03-11 03:32:10 +03:00
if ( lp_unix_password_sync ( ) )
if ( ! chgpasswd ( pdb_get_username ( pwd ) , " " , buf , True ) )
2001-02-27 21:22:39 +03:00
return False ;
}
2001-03-11 03:32:10 +03:00
memset ( buf , 0 , sizeof ( buf ) ) ;
DEBUG ( 0 , ( " set_user_info_24: pdb_update_sam_account() \n " ) ) ;
/* update the SAMBA password */
if ( ! pdb_update_sam_account ( pwd , True ) )
return False ;
return True ;
2001-02-27 21:22:39 +03:00
}
/*******************************************************************
samr_reply_set_userinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_set_userinfo ( pipes_struct * p , SAMR_Q_SET_USERINFO * q_u , SAMR_R_SET_USERINFO * r_u )
{
uint32 rid = 0x0 ;
DOM_SID sid ;
struct current_user user ;
2001-03-11 03:32:10 +03:00
SAM_ACCOUNT * sam_pass ;
2001-02-27 21:22:39 +03:00
unsigned char sess_key [ 16 ] ;
POLICY_HND * pol = & q_u - > pol ;
uint16 switch_value = q_u - > switch_value ;
SAM_USERINFO_CTR * ctr = q_u - > ctr ;
DEBUG ( 5 , ( " _samr_set_userinfo: %d \n " , __LINE__ ) ) ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
if ( p - > ntlmssp_auth_validated ) {
memcpy ( & user , & p - > pipe_user , sizeof ( user ) ) ;
} else {
extern struct current_user current_user ;
memcpy ( & user , & current_user , sizeof ( user ) ) ;
}
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , pol , & sid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
sid_split_rid ( & sid , & rid ) ;
DEBUG ( 5 , ( " _samr_set_userinfo: rid:0x%x, level:%d \n " , rid , switch_value ) ) ;
if ( ctr = = NULL ) {
DEBUG ( 5 , ( " _samr_set_userinfo: NULL info level \n " ) ) ;
return NT_STATUS_INVALID_INFO_CLASS ;
}
/*
* We need the NT hash of the user who is changing the user ' s password .
* This NT hash is used to generate a " user session key "
* This " user session key " is in turn used to encrypt / decrypt the user ' s password .
*/
become_root ( ) ;
2001-03-11 03:32:10 +03:00
sam_pass = pdb_getsampwuid ( user . uid ) ;
2001-02-27 21:22:39 +03:00
unbecome_root ( ) ;
2001-03-11 03:32:10 +03:00
if ( sam_pass = = NULL ) {
2001-02-27 21:22:39 +03:00
DEBUG ( 0 , ( " _samr_set_userinfo: Unable to get smbpasswd entry for uid %u \n " , ( unsigned int ) user . uid ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
memset ( sess_key , ' \0 ' , 16 ) ;
2001-03-11 03:32:10 +03:00
mdfour ( sess_key , pdb_get_nt_passwd ( sam_pass ) , 16 ) ;
2001-02-27 21:22:39 +03:00
/* ok! user info levels (lots: see MSDEV help), off we go... */
switch ( switch_value ) {
case 0x12 :
if ( ! set_user_info_12 ( ctr - > info . id12 , rid ) )
return NT_STATUS_ACCESS_DENIED ;
break ;
case 24 :
SamOEMhash ( ctr - > info . id24 - > pass , sess_key , 1 ) ;
if ( ! set_user_info_24 ( ctr - > info . id24 , rid ) )
return NT_STATUS_ACCESS_DENIED ;
break ;
case 23 :
SamOEMhash ( ctr - > info . id23 - > pass , sess_key , 1 ) ;
if ( ! set_user_info_23 ( ctr - > info . id23 , rid ) )
return NT_STATUS_ACCESS_DENIED ;
break ;
default :
return NT_STATUS_INVALID_INFO_CLASS ;
}
return r_u - > status ;
}
/*******************************************************************
samr_reply_set_userinfo2
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_set_userinfo2 ( pipes_struct * p , SAMR_Q_SET_USERINFO2 * q_u , SAMR_R_SET_USERINFO2 * r_u )
{
DOM_SID sid ;
uint32 rid = 0x0 ;
2001-03-11 03:32:10 +03:00
SAM_USERINFO_CTR * ctr = q_u - > ctr ;
2001-02-27 21:22:39 +03:00
POLICY_HND * pol = & q_u - > pol ;
uint16 switch_value = q_u - > switch_value ;
DEBUG ( 5 , ( " samr_reply_set_userinfo2: %d \n " , __LINE__ ) ) ;
r_u - > status = NT_STATUS_NOPROBLEMO ;
/* find the policy handle. open a policy on it. */
2001-03-11 03:32:10 +03:00
if ( ! get_lsa_policy_samr_sid ( p , pol , & sid ) )
2001-02-27 21:22:39 +03:00
return NT_STATUS_INVALID_HANDLE ;
sid_split_rid ( & sid , & rid ) ;
DEBUG ( 5 , ( " samr_reply_set_userinfo2: rid:0x%x \n " , rid ) ) ;
if ( ctr = = NULL ) {
DEBUG ( 5 , ( " samr_reply_set_userinfo2: NULL info level \n " ) ) ;
return NT_STATUS_INVALID_INFO_CLASS ;
}
2001-03-11 03:32:10 +03:00
switch_value = ctr - > switch_value ;
2001-02-27 21:22:39 +03:00
/* ok! user info levels (lots: see MSDEV help), off we go... */
switch ( switch_value ) {
case 21 :
if ( ! set_user_info_21 ( ctr - > info . id21 , rid ) )
return NT_STATUS_ACCESS_DENIED ;
break ;
case 16 :
if ( ! set_user_info_10 ( ctr - > info . id10 , rid ) )
return NT_STATUS_ACCESS_DENIED ;
break ;
default :
return NT_STATUS_INVALID_INFO_CLASS ;
}
return r_u - > status ;
}
/*********************************************************************
_samr_query_aliasmem
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_useraliases ( pipes_struct * p , SAMR_Q_QUERY_USERALIASES * q_u , SAMR_R_QUERY_USERALIASES * r_u )
{
DEBUG ( 0 , ( " _samr_query_useraliases: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_query_aliasmem
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_aliasmem ( pipes_struct * p , SAMR_Q_QUERY_ALIASMEM * q_u , SAMR_R_QUERY_ALIASMEM * r_u )
{
DEBUG ( 0 , ( " _samr_query_aliasmem: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_query_groupmem
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_groupmem ( pipes_struct * p , SAMR_Q_QUERY_GROUPMEM * q_u , SAMR_R_QUERY_GROUPMEM * r_u )
{
DEBUG ( 0 , ( " _samr_query_groupmem: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_add_aliasmem
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_add_aliasmem ( pipes_struct * p , SAMR_Q_ADD_ALIASMEM * q_u , SAMR_R_ADD_ALIASMEM * r_u )
{
DEBUG ( 0 , ( " _samr_add_aliasmem: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_del_aliasmem
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_del_aliasmem ( pipes_struct * p , SAMR_Q_DEL_ALIASMEM * q_u , SAMR_R_DEL_ALIASMEM * r_u )
{
DEBUG ( 0 , ( " _samr_del_aliasmem: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_add_groupmem
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_add_groupmem ( pipes_struct * p , SAMR_Q_ADD_GROUPMEM * q_u , SAMR_R_ADD_GROUPMEM * r_u )
{
DEBUG ( 0 , ( " _samr_add_groupmem: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_del_groupmem
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_del_groupmem ( pipes_struct * p , SAMR_Q_DEL_GROUPMEM * q_u , SAMR_R_DEL_GROUPMEM * r_u )
{
DEBUG ( 0 , ( " _samr_del_groupmem: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_delete_dom_user
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_delete_dom_user ( pipes_struct * p , SAMR_Q_DELETE_DOM_USER * q_u , SAMR_R_DELETE_DOM_USER * r_u )
{
DEBUG ( 0 , ( " _samr_delete_dom_user: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_delete_dom_group
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_delete_dom_group ( pipes_struct * p , SAMR_Q_DELETE_DOM_GROUP * q_u , SAMR_R_DELETE_DOM_GROUP * r_u )
{
DEBUG ( 0 , ( " _samr_delete_dom_group: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_delete_dom_alias
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_delete_dom_alias ( pipes_struct * p , SAMR_Q_DELETE_DOM_ALIAS * q_u , SAMR_R_DELETE_DOM_ALIAS * r_u )
{
DEBUG ( 0 , ( " _samr_delete_dom_alias: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_create_dom_group
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_create_dom_group ( pipes_struct * p , SAMR_Q_CREATE_DOM_GROUP * q_u , SAMR_R_CREATE_DOM_GROUP * r_u )
{
DEBUG ( 0 , ( " _samr_create_dom_group: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_create_dom_alias
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_create_dom_alias ( pipes_struct * p , SAMR_Q_CREATE_DOM_ALIAS * q_u , SAMR_R_CREATE_DOM_ALIAS * r_u )
{
DEBUG ( 0 , ( " _samr_create_dom_alias: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_query_groupinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_query_groupinfo ( pipes_struct * p , SAMR_Q_QUERY_GROUPINFO * q_u , SAMR_R_QUERY_GROUPINFO * r_u )
{
DEBUG ( 0 , ( " _samr_query_groupinfo: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_set_groupinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_set_groupinfo ( pipes_struct * p , SAMR_Q_SET_GROUPINFO * q_u , SAMR_R_SET_GROUPINFO * r_u )
{
DEBUG ( 0 , ( " _samr_set_groupinfo: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_get_dom_pwinfo
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_get_dom_pwinfo ( pipes_struct * p , SAMR_Q_GET_DOM_PWINFO * q_u , SAMR_R_GET_DOM_PWINFO * r_u )
{
DEBUG ( 0 , ( " _samr_get_dom_pwinfo: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_open_group
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_open_group ( pipes_struct * p , SAMR_Q_OPEN_GROUP * q_u , SAMR_R_OPEN_GROUP * r_u )
{
DEBUG ( 0 , ( " _samr_open_group: Not yet implemented. \n " ) ) ;
return False ;
}
/*********************************************************************
_samr_unknown_2d
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 _samr_unknown_2d ( pipes_struct * p , SAMR_Q_UNKNOWN_2D * q_u , SAMR_R_UNKNOWN_2D * r_u )
{
DEBUG ( 0 , ( " _samr_unknown_2d: Not yet implemented. \n " ) ) ;
return False ;
}