2005-01-13 21:20:37 +03:00
/*
2002-01-30 09:08:46 +03:00
* Unix SMB / CIFS implementation .
2001-02-26 22:31:07 +03:00
* RPC Pipe client / server routines
* Copyright ( C ) Andrew Tridgell 1992 - 1997 ,
* Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1997 ,
2002-07-15 14:35:28 +04:00
* Copyright ( C ) Paul Ashton 1997 ,
* Copyright ( C ) Jeremy Allison 2001 ,
2002-08-17 19:34:15 +04:00
* Copyright ( C ) Rafal Szczesniak 2002 ,
2004-04-13 18:39:48 +04:00
* Copyright ( C ) Jim McDonough < jmcd @ us . ibm . com > 2002 ,
2005-01-13 21:20:37 +03:00
* Copyright ( C ) Simo Sorce 2003.
2001-02-26 22:31:07 +03:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* 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 lsa server code. */
# include "includes.h"
2002-07-15 14:35:28 +04:00
# undef DBGC_CLASS
# define DBGC_CLASS DBGC_RPC_SRV
2001-07-09 22:32:54 +04:00
extern PRIVS privs [ ] ;
struct lsa_info {
2002-11-13 02:20:50 +03:00
DOM_SID sid ;
uint32 access ;
2001-07-09 22:32:54 +04:00
} ;
2001-12-18 02:03:23 +03:00
struct generic_mapping lsa_generic_mapping = {
POLICY_READ ,
POLICY_WRITE ,
POLICY_EXECUTE ,
POLICY_ALL_ACCESS
} ;
2001-07-09 22:32:54 +04:00
/*******************************************************************
Function to free the per handle data .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_lsa_info ( void * ptr )
{
struct lsa_info * lsa = ( struct lsa_info * ) ptr ;
2003-04-22 12:50:20 +04:00
SAFE_FREE ( lsa ) ;
2001-07-09 22:32:54 +04:00
}
2001-02-26 22:31:07 +03:00
/***************************************************************************
Init dom_query
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-11-13 02:20:50 +03:00
static void init_dom_query ( DOM_QUERY * d_q , const char * dom_name , DOM_SID * dom_sid )
2001-02-26 22:31:07 +03:00
{
2003-09-26 01:26:16 +04:00
d_q - > buffer_dom_name = ( dom_name ! = NULL ) ? 1 : 0 ; /* domain buffer pointer */
d_q - > buffer_dom_sid = ( dom_sid ! = NULL ) ? 1 : 0 ; /* domain sid pointer */
/* this string is supposed to be non-null terminated. */
/* But the maxlen in this UNISTR2 must include the terminating null. */
2003-12-11 00:13:44 +03:00
init_unistr2 ( & d_q - > uni_domain_name , dom_name , UNI_BROKEN_NON_NULL ) ;
2001-02-26 22:31:07 +03:00
/*
* I ' m not sure why this really odd combination of length
* values works , but it does appear to . I need to look at
* this * much * more closely - but at the moment leave alone
* until it ' s understood . This allows a W2k client to join
* a domain with both odd and even length names . . . JRA .
*/
2003-09-26 01:26:16 +04:00
/*
* IMPORTANT NOTE ! ! ! !
* The two fields below probably are reversed in meaning , ie .
* the first field is probably the str_len , the second the max
* len . Both are measured in bytes anyway .
*/
2001-02-26 22:31:07 +03:00
2003-09-26 01:26:16 +04:00
d_q - > uni_dom_str_len = d_q - > uni_domain_name . uni_max_len * 2 ;
d_q - > uni_dom_max_len = d_q - > uni_domain_name . uni_str_len * 2 ;
2001-02-26 22:31:07 +03:00
if ( dom_sid ! = NULL )
init_dom_sid2 ( & d_q - > dom_sid , dom_sid ) ;
}
/***************************************************************************
init_dom_ref - adds a domain if it ' s not already in , returns the index .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int init_dom_ref ( DOM_R_REF * ref , char * dom_name , DOM_SID * dom_sid )
{
int num = 0 ;
if ( dom_name ! = NULL ) {
for ( num = 0 ; num < ref - > num_ref_doms_1 ; num + + ) {
fstring domname ;
2004-07-05 19:05:45 +04:00
rpcstr_pull ( domname , ref - > ref_dom [ num ] . uni_dom_name . buffer , sizeof ( domname ) , - 1 , 0 ) ;
2001-02-26 22:31:07 +03:00
if ( strequal ( domname , dom_name ) )
return num ;
}
} else {
num = ref - > num_ref_doms_1 ;
}
if ( num > = MAX_REF_DOMAINS ) {
/* index not found, already at maximum domain limit */
return - 1 ;
}
ref - > num_ref_doms_1 = num + 1 ;
ref - > ptr_ref_dom = 1 ;
ref - > max_entries = MAX_REF_DOMAINS ;
ref - > num_ref_doms_2 = num + 1 ;
ref - > hdr_ref_dom [ num ] . ptr_dom_sid = dom_sid ! = NULL ? 1 : 0 ;
2003-09-26 01:26:16 +04:00
init_unistr2 ( & ref - > ref_dom [ num ] . uni_dom_name , dom_name , UNI_FLAGS_NONE ) ;
init_uni_hdr ( & ref - > hdr_ref_dom [ num ] . hdr_dom_name , & ref - > ref_dom [ num ] . uni_dom_name ) ;
2001-02-26 22:31:07 +03:00
init_dom_sid2 ( & ref - > ref_dom [ num ] . ref_dom , dom_sid ) ;
return num ;
}
/***************************************************************************
init_lsa_rid2s
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_lsa_rid2s ( DOM_R_REF * ref , DOM_RID2 * rid2 ,
2001-05-08 05:26:28 +04:00
int num_entries , UNISTR2 * name ,
2001-03-13 04:44:05 +03:00
uint32 * mapped_count , BOOL endian )
2001-02-26 22:31:07 +03:00
{
int i ;
int total = 0 ;
* mapped_count = 0 ;
SMB_ASSERT ( num_entries < = MAX_LOOKUP_SIDS ) ;
2002-01-26 13:02:23 +03:00
become_root ( ) ; /* lookup_name can require root privs */
2001-02-26 22:31:07 +03:00
for ( i = 0 ; i < num_entries ; i + + ) {
BOOL status = False ;
DOM_SID sid ;
uint32 rid = 0xffffffff ;
int dom_idx = - 1 ;
pstring full_name ;
fstring dom_name , user ;
enum SID_NAME_USE name_type = SID_NAME_UNKNOWN ;
/* Split name into domain and user component */
2001-07-09 22:32:54 +04:00
unistr2_to_ascii ( full_name , & name [ i ] , sizeof ( full_name ) ) ;
2001-02-26 22:31:07 +03:00
split_domain_name ( full_name , dom_name , user ) ;
/* Lookup name */
DEBUG ( 5 , ( " init_lsa_rid2s: looking up name %s \n " , full_name ) ) ;
2002-01-26 13:02:23 +03:00
status = lookup_name ( dom_name , user , & sid , & name_type ) ;
2001-02-26 22:31:07 +03:00
2004-04-07 02:02:47 +04:00
if ( ( name_type = = SID_NAME_UNKNOWN ) & & ( lp_server_role ( ) = = ROLE_DOMAIN_MEMBER ) & & ( strncmp ( dom_name , full_name , strlen ( dom_name ) ) ! = 0 ) ) {
DEBUG ( 5 , ( " init_lsa_rid2s: domain name not provided and local account not found, using member domain \n " ) ) ;
fstrcpy ( dom_name , lp_workgroup ( ) ) ;
status = lookup_name ( dom_name , user , & sid , & name_type ) ;
}
2004-05-20 22:28:21 +04:00
#if 0 /* This is not true. */
2004-04-07 16:43:44 +04:00
if ( name_type = = SID_NAME_WKN_GRP ) {
/* BUILTIN aliases are still aliases :-) */
name_type = SID_NAME_ALIAS ;
}
2004-05-20 22:28:21 +04:00
# endif
2004-04-07 16:43:44 +04:00
2001-02-26 22:31:07 +03:00
DEBUG ( 5 , ( " init_lsa_rid2s: %s \n " , status ? " found " :
" not found " ) ) ;
2002-07-15 14:35:28 +04:00
if ( status & & name_type ! = SID_NAME_UNKNOWN ) {
2001-02-26 22:31:07 +03:00
sid_split_rid ( & sid , & rid ) ;
dom_idx = init_dom_ref ( ref , dom_name , & sid ) ;
( * mapped_count ) + + ;
} else {
dom_idx = - 1 ;
2004-02-20 02:00:01 +03:00
rid = 0 ;
2001-02-26 22:31:07 +03:00
name_type = SID_NAME_UNKNOWN ;
}
init_dom_rid2 ( & rid2 [ total ] , rid , name_type , dom_idx ) ;
total + + ;
}
2002-01-26 13:02:23 +03:00
unbecome_root ( ) ;
2001-02-26 22:31:07 +03:00
}
/***************************************************************************
init_reply_lookup_names
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_reply_lookup_names ( LSA_R_LOOKUP_NAMES * r_l ,
DOM_R_REF * ref , uint32 num_entries ,
DOM_RID2 * rid2 , uint32 mapped_count )
{
r_l - > ptr_dom_ref = 1 ;
r_l - > dom_ref = ref ;
r_l - > num_entries = num_entries ;
r_l - > ptr_entries = 1 ;
r_l - > num_entries2 = num_entries ;
r_l - > dom_rid = rid2 ;
r_l - > mapped_count = mapped_count ;
}
/***************************************************************************
Init lsa_trans_names .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_lsa_trans_names ( TALLOC_CTX * ctx , DOM_R_REF * ref , LSA_TRANS_NAME_ENUM * trn ,
int num_entries , DOM_SID2 * sid ,
uint32 * mapped_count )
{
int i ;
int total = 0 ;
* mapped_count = 0 ;
/* Allocate memory for list of names */
if ( num_entries > 0 ) {
2004-12-07 21:25:53 +03:00
if ( ! ( trn - > name = TALLOC_ARRAY ( ctx , LSA_TRANS_NAME , num_entries ) ) ) {
2001-02-26 22:31:07 +03:00
DEBUG ( 0 , ( " init_lsa_trans_names(): out of memory \n " ) ) ;
return ;
}
2004-12-07 21:25:53 +03:00
if ( ! ( trn - > uni_name = TALLOC_ARRAY ( ctx , UNISTR2 , num_entries ) ) ) {
2001-02-26 22:31:07 +03:00
DEBUG ( 0 , ( " init_lsa_trans_names(): out of memory \n " ) ) ;
return ;
}
}
2002-04-09 08:59:34 +04:00
become_root ( ) ; /* Need root to get to passdb to for local sids */
2001-02-26 22:31:07 +03:00
for ( i = 0 ; i < num_entries ; i + + ) {
BOOL status = False ;
DOM_SID find_sid = sid [ i ] . sid ;
uint32 rid = 0xffffffff ;
int dom_idx = - 1 ;
fstring name , dom_name ;
enum SID_NAME_USE sid_name_use = ( enum SID_NAME_USE ) 0 ;
sid_to_string ( name , & find_sid ) ;
DEBUG ( 5 , ( " init_lsa_trans_names: looking up sid %s \n " , name ) ) ;
/* Lookup sid from winbindd */
status = lookup_sid ( & find_sid , dom_name , name , & sid_name_use ) ;
DEBUG ( 5 , ( " init_lsa_trans_names: %s \n " , status ? " found " :
" not found " ) ) ;
if ( ! status ) {
sid_name_use = SID_NAME_UNKNOWN ;
2004-02-18 01:46:25 +03:00
memset ( dom_name , ' \0 ' , sizeof ( dom_name ) ) ;
sid_to_string ( name , & find_sid ) ;
dom_idx = - 1 ;
DEBUG ( 10 , ( " init_lsa_trans_names: added unknown user '%s' to "
" referenced list. \n " , name ) ) ;
2002-07-15 14:35:28 +04:00
} else {
( * mapped_count ) + + ;
2004-02-18 01:46:25 +03:00
/* Store domain sid in ref array */
if ( find_sid . num_auths = = 5 ) {
sid_split_rid ( & find_sid , & rid ) ;
}
dom_idx = init_dom_ref ( ref , dom_name , & find_sid ) ;
2001-02-26 22:31:07 +03:00
2004-11-19 16:26:17 +03:00
DEBUG ( 10 , ( " init_lsa_trans_names: added %s '%s \\ %s' (%d) to referenced list. \n " ,
sid_type_lookup ( sid_name_use ) , dom_name , name , sid_name_use ) ) ;
2001-02-26 22:31:07 +03:00
}
init_lsa_trans_name ( & trn - > name [ total ] , & trn - > uni_name [ total ] ,
sid_name_use , name , dom_idx ) ;
total + + ;
}
2002-04-09 08:59:34 +04:00
unbecome_root ( ) ;
2001-02-26 22:31:07 +03:00
trn - > num_entries = total ;
trn - > ptr_trans_names = 1 ;
trn - > num_entries2 = total ;
}
/***************************************************************************
Init_reply_lookup_sids .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_reply_lookup_sids ( LSA_R_LOOKUP_SIDS * r_l ,
DOM_R_REF * ref , LSA_TRANS_NAME_ENUM * names ,
uint32 mapped_count )
{
r_l - > ptr_dom_ref = 1 ;
r_l - > dom_ref = ref ;
r_l - > names = names ;
r_l - > mapped_count = mapped_count ;
}
2001-12-18 02:03:23 +03:00
static NTSTATUS lsa_get_generic_sd ( TALLOC_CTX * mem_ctx , SEC_DESC * * sd , size_t * sd_size )
{
extern DOM_SID global_sid_World ;
extern DOM_SID global_sid_Builtin ;
DOM_SID local_adm_sid ;
DOM_SID adm_sid ;
SEC_ACE ace [ 3 ] ;
SEC_ACCESS mask ;
SEC_ACL * psa = NULL ;
init_sec_access ( & mask , POLICY_EXECUTE ) ;
init_sec_ace ( & ace [ 0 ] , & global_sid_World , SEC_ACE_TYPE_ACCESS_ALLOWED , mask , 0 ) ;
2002-07-15 14:35:28 +04:00
sid_copy ( & adm_sid , get_global_sam_sid ( ) ) ;
2001-12-18 02:03:23 +03:00
sid_append_rid ( & adm_sid , DOMAIN_GROUP_RID_ADMINS ) ;
init_sec_access ( & mask , POLICY_ALL_ACCESS ) ;
init_sec_ace ( & ace [ 1 ] , & adm_sid , SEC_ACE_TYPE_ACCESS_ALLOWED , mask , 0 ) ;
sid_copy ( & local_adm_sid , & global_sid_Builtin ) ;
sid_append_rid ( & local_adm_sid , BUILTIN_ALIAS_RID_ADMINS ) ;
init_sec_access ( & mask , POLICY_ALL_ACCESS ) ;
init_sec_ace ( & ace [ 2 ] , & local_adm_sid , SEC_ACE_TYPE_ACCESS_ALLOWED , mask , 0 ) ;
if ( ( psa = make_sec_acl ( mem_ctx , NT4_ACL_REVISION , 3 , ace ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
2003-09-20 01:57:43 +04:00
if ( ( * sd = make_sec_desc ( mem_ctx , SEC_DESC_REVISION , SEC_DESC_SELF_RELATIVE , & adm_sid , NULL , NULL , psa , sd_size ) ) = = NULL )
2001-12-18 02:03:23 +03:00
return NT_STATUS_NO_MEMORY ;
return NT_STATUS_OK ;
}
2002-08-17 19:34:15 +04:00
/***************************************************************************
2002-11-13 02:20:50 +03:00
Init_dns_dom_info .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void init_dns_dom_info ( LSA_DNS_DOM_INFO * r_l , const char * nb_name ,
const char * dns_name , const char * forest_name ,
2004-04-13 18:39:48 +04:00
struct uuid * dom_guid , DOM_SID * dom_sid )
2002-08-17 19:34:15 +04:00
{
if ( nb_name & & * nb_name ) {
2003-09-26 01:26:16 +04:00
init_unistr2 ( & r_l - > uni_nb_dom_name , nb_name , UNI_FLAGS_NONE ) ;
init_uni_hdr ( & r_l - > hdr_nb_dom_name , & r_l - > uni_nb_dom_name ) ;
2002-08-17 19:34:15 +04:00
r_l - > hdr_nb_dom_name . uni_max_len + = 2 ;
r_l - > uni_nb_dom_name . uni_max_len + = 1 ;
}
if ( dns_name & & * dns_name ) {
2003-09-26 01:26:16 +04:00
init_unistr2 ( & r_l - > uni_dns_dom_name , dns_name , UNI_FLAGS_NONE ) ;
init_uni_hdr ( & r_l - > hdr_dns_dom_name , & r_l - > uni_dns_dom_name ) ;
2002-08-17 19:34:15 +04:00
r_l - > hdr_dns_dom_name . uni_max_len + = 2 ;
r_l - > uni_dns_dom_name . uni_max_len + = 1 ;
}
if ( forest_name & & * forest_name ) {
2003-09-26 01:26:16 +04:00
init_unistr2 ( & r_l - > uni_forest_name , forest_name , UNI_FLAGS_NONE ) ;
init_uni_hdr ( & r_l - > hdr_forest_name , & r_l - > uni_forest_name ) ;
2002-08-17 19:34:15 +04:00
r_l - > hdr_forest_name . uni_max_len + = 2 ;
r_l - > uni_forest_name . uni_max_len + = 1 ;
}
/* how do we init the guid ? probably should write an init fn */
if ( dom_guid ) {
2004-04-13 18:39:48 +04:00
memcpy ( & r_l - > dom_guid , dom_guid , sizeof ( struct uuid ) ) ;
2002-08-17 19:34:15 +04:00
}
if ( dom_sid ) {
r_l - > ptr_dom_sid = 1 ;
init_dom_sid2 ( & r_l - > dom_sid , dom_sid ) ;
}
}
2001-02-26 22:31:07 +03:00
/***************************************************************************
_lsa_open_policy2 .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 21:52:23 +04:00
NTSTATUS _lsa_open_policy2 ( pipes_struct * p , LSA_Q_OPEN_POL2 * q_u , LSA_R_OPEN_POL2 * r_u )
2001-02-26 22:31:07 +03:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * info ;
SEC_DESC * psd = NULL ;
size_t sd_size ;
uint32 des_access = q_u - > des_access ;
uint32 acc_granted ;
NTSTATUS status ;
/* map the generic bits to the lsa policy ones */
se_map_generic ( & des_access , & lsa_generic_mapping ) ;
/* get the generic lsa policy SD until we store it */
lsa_get_generic_sd ( p - > mem_ctx , & psd , & sd_size ) ;
2003-06-18 19:24:10 +04:00
if ( ! se_access_check ( psd , p - > pipe_user . nt_user_token , des_access , & acc_granted , & status ) ) {
if ( geteuid ( ) ! = 0 ) {
return status ;
}
DEBUG ( 4 , ( " ACCESS should be DENIED (granted: %#010x; required: %#010x) \n " ,
acc_granted , des_access ) ) ;
DEBUGADD ( 4 , ( " but overwritten by euid == 0 \n " ) ) ;
}
2005-01-13 21:20:37 +03:00
/* This is needed for lsa_open_account and rpcclient .... :-) */
if ( geteuid ( ) = = 0 )
acc_granted = POLICY_ALL_ACCESS ;
2001-12-18 02:03:23 +03:00
/* associate the domain SID with the (unique) handle. */
2004-12-07 21:25:53 +03:00
if ( ( info = SMB_MALLOC_P ( struct lsa_info ) ) = = NULL )
2001-12-18 02:03:23 +03:00
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
2002-07-15 14:35:28 +04:00
sid_copy ( & info - > sid , get_global_sam_sid ( ) ) ;
2001-12-18 02:03:23 +03:00
info - > access = acc_granted ;
2001-02-26 22:31:07 +03:00
/* set up the LSA QUERY INFO response */
2001-12-18 02:03:23 +03:00
if ( ! create_policy_hnd ( p , & r_u - > pol , free_lsa_info , ( void * ) info ) )
2001-03-11 03:32:10 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
2001-02-26 22:31:07 +03:00
2001-08-27 23:46:22 +04:00
return NT_STATUS_OK ;
2001-02-26 22:31:07 +03:00
}
/***************************************************************************
_lsa_open_policy
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_open_policy ( pipes_struct * p , LSA_Q_OPEN_POL * q_u , LSA_R_OPEN_POL * r_u )
2001-02-26 22:31:07 +03:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * info ;
SEC_DESC * psd = NULL ;
size_t sd_size ;
uint32 des_access = q_u - > des_access ;
uint32 acc_granted ;
NTSTATUS status ;
/* map the generic bits to the lsa policy ones */
se_map_generic ( & des_access , & lsa_generic_mapping ) ;
/* get the generic lsa policy SD until we store it */
lsa_get_generic_sd ( p - > mem_ctx , & psd , & sd_size ) ;
2003-06-18 19:24:10 +04:00
if ( ! se_access_check ( psd , p - > pipe_user . nt_user_token , des_access , & acc_granted , & status ) ) {
if ( geteuid ( ) ! = 0 ) {
return status ;
}
DEBUG ( 4 , ( " ACCESS should be DENIED (granted: %#010x; required: %#010x) \n " ,
acc_granted , des_access ) ) ;
DEBUGADD ( 4 , ( " but overwritten by euid == 0 \n " ) ) ;
acc_granted = des_access ;
}
2001-12-18 02:03:23 +03:00
/* associate the domain SID with the (unique) handle. */
2004-12-07 21:25:53 +03:00
if ( ( info = SMB_MALLOC_P ( struct lsa_info ) ) = = NULL )
2001-12-18 02:03:23 +03:00
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
2002-07-15 14:35:28 +04:00
sid_copy ( & info - > sid , get_global_sam_sid ( ) ) ;
2001-12-18 02:03:23 +03:00
info - > access = acc_granted ;
2001-02-26 22:31:07 +03:00
/* set up the LSA QUERY INFO response */
2001-12-18 02:03:23 +03:00
if ( ! create_policy_hnd ( p , & r_u - > pol , free_lsa_info , ( void * ) info ) )
2001-03-11 03:32:10 +03:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
2001-02-26 22:31:07 +03:00
2001-08-27 23:46:22 +04:00
return NT_STATUS_OK ;
2001-02-26 22:31:07 +03:00
}
/***************************************************************************
_lsa_enum_trust_dom - this needs fixing to do more than return NULL ! JRA .
2002-07-15 14:35:28 +04:00
ufff , done : ) mimir
2001-02-26 22:31:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_enum_trust_dom ( pipes_struct * p , LSA_Q_ENUM_TRUST_DOM * q_u , LSA_R_ENUM_TRUST_DOM * r_u )
2001-02-26 22:31:07 +03:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * info ;
2002-07-15 14:35:28 +04:00
uint32 enum_context = q_u - > enum_context ;
/*
* preferred length is set to 5 as a " our " preferred length
* nt sets this parameter to 2
2002-09-25 19:19:00 +04:00
* update ( 20.08 .2002 ) : it ' s not preferred length , but preferred size !
* it needs further investigation how to optimally choose this value
2002-07-15 14:35:28 +04:00
*/
uint32 max_num_domains = q_u - > preferred_len < 5 ? q_u - > preferred_len : 10 ;
TRUSTDOM * * trust_doms ;
uint32 num_domains ;
NTSTATUS nt_status ;
2001-02-26 22:31:07 +03:00
2001-12-18 02:03:23 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
2001-03-11 03:32:10 +03:00
return NT_STATUS_INVALID_HANDLE ;
2001-12-18 02:03:23 +03:00
/* check if the user have enough rights */
if ( ! ( info - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2003-08-15 05:42:30 +04:00
nt_status = secrets_get_trusted_domains ( p - > mem_ctx , ( int * ) & enum_context , max_num_domains , ( int * ) & num_domains , & trust_doms ) ;
2002-07-15 14:35:28 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) & &
! NT_STATUS_EQUAL ( nt_status , STATUS_MORE_ENTRIES ) & &
! NT_STATUS_EQUAL ( nt_status , NT_STATUS_NO_MORE_ENTRIES ) ) {
return nt_status ;
} else {
r_u - > status = nt_status ;
}
/* set up the lsa_enum_trust_dom response */
init_r_enum_trust_dom ( p - > mem_ctx , r_u , enum_context , max_num_domains , num_domains , trust_doms ) ;
2001-02-26 22:31:07 +03:00
return r_u - > status ;
}
/***************************************************************************
2001-03-15 07:34:53 +03:00
_lsa_query_info . See the POLICY_INFOMATION_CLASS docs at msdn .
2001-02-26 22:31:07 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_query_info ( pipes_struct * p , LSA_Q_QUERY_INFO * q_u , LSA_R_QUERY_INFO * r_u )
2001-02-26 22:31:07 +03:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * handle ;
2001-02-26 22:31:07 +03:00
LSA_INFO_UNION * info = & r_u - > dom ;
DOM_SID domain_sid ;
2002-11-13 02:20:50 +03:00
const char * name ;
2001-02-26 22:31:07 +03:00
DOM_SID * sid = NULL ;
2001-08-27 23:46:22 +04:00
r_u - > status = NT_STATUS_OK ;
2001-02-26 22:31:07 +03:00
2001-12-18 02:03:23 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) )
2001-03-11 03:32:10 +03:00
return NT_STATUS_INVALID_HANDLE ;
2001-02-26 22:31:07 +03:00
switch ( q_u - > info_class ) {
case 0x02 :
{
2001-12-18 02:03:23 +03:00
unsigned int i ;
/* check if the user have enough rights */
if ( ! ( handle - > access & POLICY_VIEW_AUDIT_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
/* fake info: We audit everything. ;) */
info - > id2 . auditing_enabled = 1 ;
info - > id2 . count1 = 7 ;
info - > id2 . count2 = 7 ;
2004-12-07 21:25:53 +03:00
if ( ( info - > id2 . auditsettings = TALLOC_ARRAY ( p - > mem_ctx , uint32 , 7 ) ) = = NULL )
2001-12-18 02:03:23 +03:00
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < 7 ; i + + )
info - > id2 . auditsettings [ i ] = 3 ;
break ;
2001-02-26 22:31:07 +03:00
}
case 0x03 :
2001-12-18 02:03:23 +03:00
/* check if the user have enough rights */
if ( ! ( handle - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2001-04-22 03:06:59 +04:00
/* Request PolicyPrimaryDomainInformation. */
switch ( lp_server_role ( ) ) {
2001-02-26 22:31:07 +03:00
case ROLE_DOMAIN_PDC :
case ROLE_DOMAIN_BDC :
2003-05-07 12:21:06 +04:00
name = get_global_sam_name ( ) ;
2002-07-15 14:35:28 +04:00
sid = get_global_sam_sid ( ) ;
2001-02-26 22:31:07 +03:00
break ;
case ROLE_DOMAIN_MEMBER :
2002-11-13 02:20:50 +03:00
name = lp_workgroup ( ) ;
2001-04-22 03:06:59 +04:00
/* We need to return the Domain SID here. */
2002-11-13 02:20:50 +03:00
if ( secrets_fetch_domain_sid ( lp_workgroup ( ) , & domain_sid ) )
2001-06-02 10:14:42 +04:00
sid = & domain_sid ;
2001-03-15 05:49:06 +03:00
else
2001-04-22 03:06:59 +04:00
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
2001-02-26 22:31:07 +03:00
break ;
2001-03-15 06:08:22 +03:00
case ROLE_STANDALONE :
2002-11-13 02:20:50 +03:00
name = lp_workgroup ( ) ;
2002-01-31 12:37:26 +03:00
sid = NULL ;
2001-03-15 06:08:22 +03:00
break ;
2001-03-15 05:49:06 +03:00
default :
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
2001-02-26 22:31:07 +03:00
}
init_dom_query ( & r_u - > dom . id3 , name , sid ) ;
break ;
case 0x05 :
2001-12-18 02:03:23 +03:00
/* check if the user have enough rights */
if ( ! ( handle - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2001-04-22 03:06:59 +04:00
/* Request PolicyAccountDomainInformation. */
2003-05-07 12:21:06 +04:00
name = get_global_sam_name ( ) ;
sid = get_global_sam_sid ( ) ;
2001-02-26 22:31:07 +03:00
init_dom_query ( & r_u - > dom . id5 , name , sid ) ;
break ;
case 0x06 :
2001-12-18 02:03:23 +03:00
/* check if the user have enough rights */
if ( ! ( handle - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2001-04-22 03:06:59 +04:00
switch ( lp_server_role ( ) ) {
2001-02-26 22:31:07 +03:00
case ROLE_DOMAIN_BDC :
/*
* only a BDC is a backup controller
* of the domain , it controls .
*/
info - > id6 . server_role = 2 ;
break ;
default :
/*
* any other role is a primary
* of the domain , it controls .
*/
info - > id6 . server_role = 3 ;
break ;
}
break ;
default :
DEBUG ( 0 , ( " _lsa_query_info: unknown info level in Lsa Query: %d \n " , q_u - > info_class ) ) ;
r_u - > status = NT_STATUS_INVALID_INFO_CLASS ;
break ;
}
2001-08-27 23:46:22 +04:00
if ( NT_STATUS_IS_OK ( r_u - > status ) ) {
2001-02-26 22:31:07 +03:00
r_u - > undoc_buffer = 0x22000000 ; /* bizarre */
r_u - > info_class = q_u - > info_class ;
}
return r_u - > status ;
}
/***************************************************************************
_lsa_lookup_sids
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_lookup_sids ( pipes_struct * p , LSA_Q_LOOKUP_SIDS * q_u , LSA_R_LOOKUP_SIDS * r_u )
2001-02-26 22:31:07 +03:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * handle ;
2001-02-26 22:31:07 +03:00
DOM_SID2 * sid = q_u - > sids . sid ;
int num_entries = q_u - > sids . num_entries ;
2001-03-01 07:01:23 +03:00
DOM_R_REF * ref = NULL ;
LSA_TRANS_NAME_ENUM * names = NULL ;
2001-02-26 22:31:07 +03:00
uint32 mapped_count = 0 ;
2003-03-13 03:50:04 +03:00
if ( num_entries > MAX_LOOKUP_SIDS ) {
num_entries = MAX_LOOKUP_SIDS ;
DEBUG ( 5 , ( " _lsa_lookup_sids: truncating SID lookup list to %d \n " , num_entries ) ) ;
}
2004-12-07 21:25:53 +03:00
ref = TALLOC_ZERO_P ( p - > mem_ctx , DOM_R_REF ) ;
names = TALLOC_ZERO_P ( p - > mem_ctx , LSA_TRANS_NAME_ENUM ) ;
2002-03-29 23:37:56 +03:00
2002-03-30 00:50:21 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) ) {
r_u - > status = NT_STATUS_INVALID_HANDLE ;
goto done ;
}
2001-03-11 03:32:10 +03:00
2001-12-18 02:03:23 +03:00
/* check if the user have enough rights */
2002-03-30 00:50:21 +03:00
if ( ! ( handle - > access & POLICY_LOOKUP_NAMES ) ) {
r_u - > status = NT_STATUS_ACCESS_DENIED ;
goto done ;
}
2001-03-01 07:01:23 +03:00
if ( ! ref | | ! names )
return NT_STATUS_NO_MEMORY ;
2001-02-26 22:31:07 +03:00
2002-03-30 00:50:21 +03:00
done :
2001-02-26 22:31:07 +03:00
/* set up the LSA Lookup SIDs response */
2001-03-01 07:01:23 +03:00
init_lsa_trans_names ( p - > mem_ctx , ref , names , num_entries , sid , & mapped_count ) ;
2004-05-21 22:06:27 +04:00
if ( NT_STATUS_IS_OK ( r_u - > status ) ) {
if ( mapped_count = = 0 )
r_u - > status = NT_STATUS_NONE_MAPPED ;
else if ( mapped_count ! = num_entries )
r_u - > status = STATUS_SOME_UNMAPPED ;
}
2001-03-01 07:01:23 +03:00
init_reply_lookup_sids ( r_u , ref , names , mapped_count ) ;
2001-02-26 22:31:07 +03:00
return r_u - > status ;
}
/***************************************************************************
lsa_reply_lookup_names
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_lookup_names ( pipes_struct * p , LSA_Q_LOOKUP_NAMES * q_u , LSA_R_LOOKUP_NAMES * r_u )
2001-02-26 22:31:07 +03:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * handle ;
2001-02-26 22:31:07 +03:00
UNISTR2 * names = q_u - > uni_name ;
int num_entries = q_u - > num_entries ;
2001-03-01 07:01:23 +03:00
DOM_R_REF * ref ;
DOM_RID2 * rids ;
2001-02-26 22:31:07 +03:00
uint32 mapped_count = 0 ;
2002-01-26 13:02:23 +03:00
if ( num_entries > MAX_LOOKUP_SIDS ) {
num_entries = MAX_LOOKUP_SIDS ;
DEBUG ( 5 , ( " _lsa_lookup_names: truncating name lookup list to %d \n " , num_entries ) ) ;
}
2004-12-07 21:25:53 +03:00
ref = TALLOC_ZERO_P ( p - > mem_ctx , DOM_R_REF ) ;
rids = TALLOC_ZERO_ARRAY ( p - > mem_ctx , DOM_RID2 , num_entries ) ;
2001-03-01 07:01:23 +03:00
2002-03-30 00:50:21 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) ) {
r_u - > status = NT_STATUS_INVALID_HANDLE ;
goto done ;
}
2002-03-29 23:37:56 +03:00
/* check if the user have enough rights */
2002-03-30 00:50:21 +03:00
if ( ! ( handle - > access & POLICY_LOOKUP_NAMES ) ) {
r_u - > status = NT_STATUS_ACCESS_DENIED ;
goto done ;
}
2002-03-29 23:37:56 +03:00
2001-03-01 07:01:23 +03:00
if ( ! ref | | ! rids )
return NT_STATUS_NO_MEMORY ;
2001-02-26 22:31:07 +03:00
2002-03-30 00:50:21 +03:00
done :
2001-02-26 22:31:07 +03:00
/* set up the LSA Lookup RIDs response */
2001-03-13 04:44:05 +03:00
init_lsa_rid2s ( ref , rids , num_entries , names , & mapped_count , p - > endian ) ;
2004-05-26 22:27:16 +04:00
if ( NT_STATUS_IS_OK ( r_u - > status ) ) {
if ( mapped_count = = 0 )
r_u - > status = NT_STATUS_NONE_MAPPED ;
else if ( mapped_count ! = num_entries )
r_u - > status = STATUS_SOME_UNMAPPED ;
}
2001-03-01 07:01:23 +03:00
init_reply_lookup_names ( r_u , ref , num_entries , rids , mapped_count ) ;
2001-02-26 22:31:07 +03:00
return r_u - > status ;
}
/***************************************************************************
_lsa_close . Also weird - needs to check if lsa handle is correct . JRA .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_close ( pipes_struct * p , LSA_Q_CLOSE * q_u , LSA_R_CLOSE * r_u )
2001-02-26 22:31:07 +03:00
{
2001-03-11 03:32:10 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , NULL ) )
return NT_STATUS_INVALID_HANDLE ;
close_policy_hnd ( p , & q_u - > pol ) ;
2001-08-27 23:46:22 +04:00
return NT_STATUS_OK ;
2001-02-26 22:31:07 +03:00
}
/***************************************************************************
" No more secrets Marty.... " : - ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_open_secret ( pipes_struct * p , LSA_Q_OPEN_SECRET * q_u , LSA_R_OPEN_SECRET * r_u )
2001-02-26 22:31:07 +03:00
{
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2001-06-30 03:12:55 +04:00
2001-07-09 22:32:54 +04:00
/***************************************************************************
_lsa_enum_privs .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_enum_privs ( pipes_struct * p , LSA_Q_ENUM_PRIVS * q_u , LSA_R_ENUM_PRIVS * r_u )
2001-07-09 22:32:54 +04:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * handle ;
2001-07-09 22:32:54 +04:00
uint32 i ;
2005-01-13 21:20:37 +03:00
uint32 enum_context = q_u - > enum_context ;
int num_privs = count_all_privileges ( ) ;
LSA_PRIV_ENTRY * entries = NULL ;
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
/* remember that the enum_context starts at 0 and not 1 */
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
if ( enum_context > = num_privs )
2002-03-29 23:37:56 +03:00
return NT_STATUS_NO_MORE_ENTRIES ;
2005-01-13 21:20:37 +03:00
DEBUG ( 10 , ( " _lsa_enum_privs: enum_context:%d total entries:%d \n " ,
enum_context , num_privs ) ) ;
if ( ! ( entries = TALLOC_ZERO_ARRAY ( p - > mem_ctx , LSA_PRIV_ENTRY , num_privs + 1 ) ) )
2002-03-29 23:37:56 +03:00
return NT_STATUS_NO_MEMORY ;
2001-12-18 02:03:23 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) )
2001-07-09 22:32:54 +04:00
return NT_STATUS_INVALID_HANDLE ;
2005-01-13 21:20:37 +03:00
/* check if the user have enough rights
I don ' t know if it ' s the right one . not documented . */
2001-12-18 02:03:23 +03:00
if ( ! ( handle - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2005-01-13 21:20:37 +03:00
if ( ! ( entries = TALLOC_ZERO_ARRAY ( p - > mem_ctx , LSA_PRIV_ENTRY , num_privs ) ) )
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < num_privs ; i + + ) {
if ( i < enum_context ) {
init_unistr2 ( & entries [ i ] . name , NULL , UNI_FLAGS_NONE ) ;
init_uni_hdr ( & entries [ i ] . hdr_name , & entries [ i ] . name ) ;
entries [ i ] . luid_low = 0 ;
entries [ i ] . luid_high = 0 ;
2001-11-23 02:50:16 +03:00
} else {
2005-01-13 21:20:37 +03:00
init_unistr2 ( & entries [ i ] . name , privs [ i ] . name , UNI_FLAGS_NONE ) ;
init_uni_hdr ( & entries [ i ] . hdr_name , & entries [ i ] . name ) ;
entries [ i ] . luid_low = privs [ i ] . se_priv ;
entries [ i ] . luid_high = 0 ;
2001-11-23 02:50:16 +03:00
}
2001-07-09 22:32:54 +04:00
}
2005-01-13 21:20:37 +03:00
enum_context = num_privs ;
init_lsa_r_enum_privs ( r_u , enum_context , num_privs , entries ) ;
2001-07-09 22:32:54 +04:00
2001-08-27 23:46:22 +04:00
return NT_STATUS_OK ;
2001-07-09 22:32:54 +04:00
}
/***************************************************************************
_lsa_priv_get_dispname .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_priv_get_dispname ( pipes_struct * p , LSA_Q_PRIV_GET_DISPNAME * q_u , LSA_R_PRIV_GET_DISPNAME * r_u )
2001-07-09 22:32:54 +04:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * handle ;
2001-07-09 22:32:54 +04:00
fstring name_asc ;
2005-01-13 21:20:37 +03:00
int i = 0 ;
2001-07-09 22:32:54 +04:00
2001-12-18 02:03:23 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) )
2001-07-09 22:32:54 +04:00
return NT_STATUS_INVALID_HANDLE ;
2001-12-18 02:03:23 +03:00
/* check if the user have enough rights */
/*
* I don ' t know if it ' s the right one . not documented .
*/
if ( ! ( handle - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2001-07-09 22:32:54 +04:00
unistr2_to_ascii ( name_asc , & q_u - > name , sizeof ( name_asc ) ) ;
2005-01-13 21:20:37 +03:00
DEBUG ( 10 , ( " _lsa_priv_get_dispname: %s \n " , name_asc ) ) ;
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
while ( privs [ i ] . se_priv ! = SE_END & & ! strequal ( name_asc , privs [ i ] . name ) )
2001-11-22 20:19:59 +03:00
i + + ;
2005-01-13 21:20:37 +03:00
if ( privs [ i ] . se_priv ! = SE_END ) {
2001-11-23 02:50:16 +03:00
DEBUG ( 10 , ( " : %s \n " , privs [ i ] . description ) ) ;
2003-09-26 01:26:16 +04:00
init_unistr2 ( & r_u - > desc , privs [ i ] . description , UNI_FLAGS_NONE ) ;
init_uni_hdr ( & r_u - > hdr_desc , & r_u - > desc ) ;
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
r_u - > ptr_info = 0xdeadbeef ;
r_u - > lang_id = q_u - > lang_id ;
2001-11-22 20:19:59 +03:00
return NT_STATUS_OK ;
} else {
2001-11-29 19:05:05 +03:00
DEBUG ( 10 , ( " _lsa_priv_get_dispname: doesn't exist \n " ) ) ;
2005-01-13 21:20:37 +03:00
r_u - > ptr_info = 0 ;
2001-11-22 20:19:59 +03:00
return NT_STATUS_NO_SUCH_PRIVILEGE ;
}
2001-07-09 22:32:54 +04:00
}
/***************************************************************************
_lsa_enum_accounts .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_enum_accounts ( pipes_struct * p , LSA_Q_ENUM_ACCOUNTS * q_u , LSA_R_ENUM_ACCOUNTS * r_u )
2001-07-09 22:32:54 +04:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * handle ;
2005-01-13 21:20:37 +03:00
DOM_SID * sid_list ;
int i , j , num_entries ;
2001-07-09 22:32:54 +04:00
LSA_SID_ENUM * sids = & r_u - > sids ;
2005-01-13 21:20:37 +03:00
NTSTATUS ret ;
2001-07-09 22:32:54 +04:00
2001-12-18 02:03:23 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) )
2001-07-09 22:32:54 +04:00
return NT_STATUS_INVALID_HANDLE ;
2001-12-18 02:03:23 +03:00
if ( ! ( handle - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2005-01-13 21:20:37 +03:00
sid_list = NULL ;
num_entries = 0 ;
/* The only way we can currently find out all the SIDs that have been
privileged is to scan all privileges */
if ( ! NT_STATUS_IS_OK ( ret = privilege_enumerate_accounts ( & sid_list , & num_entries ) ) ) {
return ret ;
2003-11-24 20:31:38 +03:00
}
2001-07-09 22:32:54 +04:00
2001-11-23 18:11:22 +03:00
if ( q_u - > enum_context > = num_entries )
return NT_STATUS_NO_MORE_ENTRIES ;
2004-12-07 21:25:53 +03:00
sids - > ptr_sid = TALLOC_ZERO_ARRAY ( p - > mem_ctx , uint32 , num_entries - q_u - > enum_context ) ;
sids - > sid = TALLOC_ZERO_ARRAY ( p - > mem_ctx , DOM_SID2 , num_entries - q_u - > enum_context ) ;
2001-07-09 22:32:54 +04:00
if ( sids - > ptr_sid = = NULL | | sids - > sid = = NULL ) {
2005-01-13 21:20:37 +03:00
SAFE_FREE ( sid_list ) ;
2001-07-09 22:32:54 +04:00
return NT_STATUS_NO_MEMORY ;
}
2005-01-13 21:20:37 +03:00
for ( i = q_u - > enum_context , j = 0 ; i < num_entries ; i + + , j + + ) {
init_dom_sid2 ( & ( * sids ) . sid [ j ] , & sid_list [ i ] ) ;
( * sids ) . ptr_sid [ j ] = 1 ;
2001-07-09 22:32:54 +04:00
}
2005-01-13 21:20:37 +03:00
SAFE_FREE ( sid_list ) ;
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
init_lsa_r_enum_accounts ( r_u , num_entries ) ;
2001-07-09 22:32:54 +04:00
2001-08-27 23:46:22 +04:00
return NT_STATUS_OK ;
2001-07-09 22:32:54 +04:00
}
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_unk_get_connuser ( pipes_struct * p , LSA_Q_UNK_GET_CONNUSER * q_u , LSA_R_UNK_GET_CONNUSER * r_u )
2001-06-30 03:12:55 +04:00
{
2001-12-18 02:03:23 +03:00
fstring username , domname ;
user_struct * vuser = get_valid_user_struct ( p - > vuid ) ;
2001-06-30 03:12:55 +04:00
2001-12-18 02:03:23 +03:00
if ( vuser = = NULL )
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
2001-06-30 03:12:55 +04:00
2001-12-18 02:03:23 +03:00
fstrcpy ( username , vuser - > user . smb_name ) ;
fstrcpy ( domname , vuser - > user . domain ) ;
2001-06-30 03:12:55 +04:00
2001-12-18 02:03:23 +03:00
r_u - > ptr_user_name = 1 ;
2003-09-26 01:26:16 +04:00
init_unistr2 ( & r_u - > uni2_user_name , username , UNI_STR_TERMINATE ) ;
init_uni_hdr ( & r_u - > hdr_user_name , & r_u - > uni2_user_name ) ;
2001-06-30 03:12:55 +04:00
2001-12-18 02:03:23 +03:00
r_u - > unk1 = 1 ;
2001-06-30 03:12:55 +04:00
2001-12-18 02:03:23 +03:00
r_u - > ptr_dom_name = 1 ;
2003-09-26 01:26:16 +04:00
init_unistr2 ( & r_u - > uni2_dom_name , domname , UNI_STR_TERMINATE ) ;
init_uni_hdr ( & r_u - > hdr_dom_name , & r_u - > uni2_dom_name ) ;
2001-06-30 03:12:55 +04:00
2001-12-18 02:03:23 +03:00
r_u - > status = NT_STATUS_OK ;
2001-06-30 03:12:55 +04:00
2001-12-18 02:03:23 +03:00
return r_u - > status ;
2001-06-30 03:12:55 +04:00
}
2001-07-09 22:32:54 +04:00
/***************************************************************************
2005-01-13 21:20:37 +03:00
Lsa Create Account
2001-07-09 22:32:54 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-01-13 21:20:37 +03:00
NTSTATUS _lsa_create_account ( pipes_struct * p , LSA_Q_CREATEACCOUNT * q_u , LSA_R_CREATEACCOUNT * r_u )
2001-07-09 22:32:54 +04:00
{
2001-12-18 02:03:23 +03:00
struct lsa_info * handle ;
2001-07-09 22:32:54 +04:00
struct lsa_info * info ;
2005-01-13 21:20:37 +03:00
/* find the connection policy handle. */
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) )
return NT_STATUS_INVALID_HANDLE ;
/* check if the user have enough rights */
/*
* I don ' t know if it ' s the right one . not documented .
* but guessed with rpcclient .
*/
if ( ! ( handle - > access & POLICY_GET_PRIVATE_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2005-01-15 00:05:54 +03:00
/* check to see if the pipe_user is a Domain Admin since
account_pol . tdb was already opened as root , this is all we have */
if ( ! nt_token_check_domain_rid ( p - > pipe_user . nt_user_token , DOMAIN_GROUP_RID_ADMINS ) )
return NT_STATUS_ACCESS_DENIED ;
2005-01-13 21:20:37 +03:00
/* associate the user/group SID with the (unique) handle. */
2005-01-15 00:05:54 +03:00
2005-01-13 21:20:37 +03:00
if ( ( info = SMB_MALLOC_P ( struct lsa_info ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
info - > sid = q_u - > sid . sid ;
info - > access = q_u - > access ;
/* get a (unique) handle. open a policy on it. */
if ( ! create_policy_hnd ( p , & r_u - > pol , free_lsa_info , ( void * ) info ) )
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
return privilege_create_account ( & info - > sid ) ;
}
/***************************************************************************
Lsa Open Account
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS _lsa_open_account ( pipes_struct * p , LSA_Q_OPENACCOUNT * q_u , LSA_R_OPENACCOUNT * r_u )
{
struct lsa_info * handle ;
struct lsa_info * info ;
2001-07-09 22:32:54 +04:00
/* find the connection policy handle. */
2001-12-18 02:03:23 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) )
2001-07-09 22:32:54 +04:00
return NT_STATUS_INVALID_HANDLE ;
2001-12-18 02:03:23 +03:00
/* check if the user have enough rights */
/*
* I don ' t know if it ' s the right one . not documented .
* but guessed with rpcclient .
*/
if ( ! ( handle - > access & POLICY_GET_PRIVATE_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2005-01-13 21:20:37 +03:00
/* TODO: Fis the parsing routine before reenabling this check! */
#if 0
if ( ! lookup_sid ( & handle - > sid , dom_name , name , & type ) )
return NT_STATUS_ACCESS_DENIED ;
# endif
2001-07-09 22:32:54 +04:00
/* associate the user/group SID with the (unique) handle. */
2004-12-07 21:25:53 +03:00
if ( ( info = SMB_MALLOC_P ( struct lsa_info ) ) = = NULL )
2001-07-09 22:32:54 +04:00
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( info ) ;
info - > sid = q_u - > sid . sid ;
info - > access = q_u - > access ;
/* get a (unique) handle. open a policy on it. */
if ( ! create_policy_hnd ( p , & r_u - > pol , free_lsa_info , ( void * ) info ) )
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
2005-01-13 21:20:37 +03:00
return NT_STATUS_OK ;
2001-07-09 22:32:54 +04:00
}
/***************************************************************************
2001-11-23 18:11:22 +03:00
For a given SID , enumerate all the privilege this account has .
2001-07-09 22:32:54 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-10-06 05:38:46 +04:00
NTSTATUS _lsa_enum_privsaccount ( pipes_struct * p , prs_struct * ps , LSA_Q_ENUMPRIVSACCOUNT * q_u , LSA_R_ENUMPRIVSACCOUNT * r_u )
2001-07-09 22:32:54 +04:00
{
struct lsa_info * info = NULL ;
2005-01-13 21:20:37 +03:00
PRIVILEGE_SET priv ;
2001-07-09 22:32:54 +04:00
/* find the connection policy handle. */
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
return NT_STATUS_INVALID_HANDLE ;
2005-01-13 21:20:37 +03:00
privilege_set_init ( & priv ) ;
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
get_privileges_for_sids ( & priv , & info - > sid , 1 ) ;
2001-11-29 19:05:05 +03:00
2005-01-13 21:20:37 +03:00
DEBUG ( 10 , ( " _lsa_enum_privsaccount: %s has %d privileges \n " ,
sid_string_static ( & info - > sid ) , priv . count ) ) ;
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
init_lsa_r_enum_privsaccount ( ps - > mem_ctx , r_u , priv . set , priv . count , 0 ) ;
2003-06-18 19:24:10 +04:00
2005-01-13 21:20:37 +03:00
privilege_set_free ( & priv ) ;
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
return NT_STATUS_OK ;
2001-07-09 22:32:54 +04:00
}
/***************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-08-27 23:46:22 +04:00
NTSTATUS _lsa_getsystemaccount ( pipes_struct * p , LSA_Q_GETSYSTEMACCOUNT * q_u , LSA_R_GETSYSTEMACCOUNT * r_u )
2001-07-09 22:32:54 +04:00
{
2001-11-29 19:05:05 +03:00
struct lsa_info * info = NULL ;
2005-01-13 21:20:37 +03:00
fstring name , dom_name ;
enum SID_NAME_USE type ;
2001-07-09 22:32:54 +04:00
/* find the connection policy handle. */
2005-01-13 21:20:37 +03:00
2001-11-29 19:05:05 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
2001-07-09 22:32:54 +04:00
return NT_STATUS_INVALID_HANDLE ;
2005-01-13 21:20:37 +03:00
if ( ! lookup_sid ( & info - > sid , dom_name , name , & type ) )
return NT_STATUS_ACCESS_DENIED ;
2001-11-29 19:05:05 +03:00
/*
0x01 - > Log on locally
0x02 - > Access this computer from network
0x04 - > Log on as a batch job
0x10 - > Log on as a service
they can be ORed together
*/
2003-06-18 19:24:10 +04:00
r_u - > access = PR_LOG_ON_LOCALLY | PR_ACCESS_FROM_NETWORK ;
2001-07-09 22:32:54 +04:00
2005-01-13 21:20:37 +03:00
return NT_STATUS_OK ;
2001-07-09 22:32:54 +04:00
}
2001-11-29 19:05:05 +03:00
/***************************************************************************
update the systemaccount information
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS _lsa_setsystemaccount ( pipes_struct * p , LSA_Q_SETSYSTEMACCOUNT * q_u , LSA_R_SETSYSTEMACCOUNT * r_u )
{
struct lsa_info * info = NULL ;
GROUP_MAP map ;
r_u - > status = NT_STATUS_OK ;
/* find the connection policy handle. */
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
return NT_STATUS_INVALID_HANDLE ;
2005-01-15 00:05:54 +03:00
/* check to see if the pipe_user is a Domain Admin since
account_pol . tdb was already opened as root , this is all we have */
if ( ! nt_token_check_domain_rid ( p - > pipe_user . nt_user_token , DOMAIN_GROUP_RID_ADMINS ) )
return NT_STATUS_ACCESS_DENIED ;
2003-06-18 19:24:10 +04:00
if ( ! pdb_getgrsid ( & map , info - > sid ) )
2001-11-29 19:05:05 +03:00
return NT_STATUS_NO_SUCH_GROUP ;
2002-11-02 06:47:48 +03:00
if ( ! pdb_update_group_mapping_entry ( & map ) )
2001-11-29 19:05:05 +03:00
return NT_STATUS_NO_SUCH_GROUP ;
return r_u - > status ;
}
/***************************************************************************
For a given SID , add some privileges .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS _lsa_addprivs ( pipes_struct * p , LSA_Q_ADDPRIVS * q_u , LSA_R_ADDPRIVS * r_u )
{
2003-10-06 05:38:46 +04:00
struct lsa_info * info = NULL ;
int i = 0 ;
2005-01-13 21:20:37 +03:00
uint32 mask ;
2003-10-06 05:38:46 +04:00
PRIVILEGE_SET * set = NULL ;
2001-11-29 19:05:05 +03:00
/* find the connection policy handle. */
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
return NT_STATUS_INVALID_HANDLE ;
2005-01-15 00:05:54 +03:00
/* check to see if the pipe_user is a Domain Admin since
account_pol . tdb was already opened as root , this is all we have */
if ( ! nt_token_check_domain_rid ( p - > pipe_user . nt_user_token , DOMAIN_GROUP_RID_ADMINS ) )
return NT_STATUS_ACCESS_DENIED ;
2001-11-29 19:05:05 +03:00
2003-10-06 05:38:46 +04:00
set = & q_u - > set ;
2001-11-29 19:05:05 +03:00
2003-10-06 05:38:46 +04:00
for ( i = 0 ; i < set - > count ; i + + ) {
2005-01-13 21:20:37 +03:00
mask = luid_to_privilege_mask ( & ( set - > set [ i ] . luid ) ) ;
if ( mask ! = SE_END ) {
if ( ! grant_privilege ( & info - > sid , mask ) ) {
DEBUG ( 3 , ( " _lsa_addprivs: grant_privilege( %s, 0x%x) failed! \n " ,
sid_string_static ( & info - > sid ) , mask ) ) ;
return NT_STATUS_NO_SUCH_PRIVILEGE ;
}
2001-11-29 19:05:05 +03:00
}
}
2005-01-13 21:20:37 +03:00
return NT_STATUS_OK ;
2001-11-29 19:05:05 +03:00
}
/***************************************************************************
For a given SID , remove some privileges .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS _lsa_removeprivs ( pipes_struct * p , LSA_Q_REMOVEPRIVS * q_u , LSA_R_REMOVEPRIVS * r_u )
{
2003-10-06 05:38:46 +04:00
struct lsa_info * info = NULL ;
2005-01-13 21:20:37 +03:00
int i = 0 ;
uint32 mask ;
2003-10-06 05:38:46 +04:00
PRIVILEGE_SET * set = NULL ;
2001-11-29 19:05:05 +03:00
/* find the connection policy handle. */
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
return NT_STATUS_INVALID_HANDLE ;
2005-01-15 00:05:54 +03:00
/* check to see if the pipe_user is a Domain Admin since
account_pol . tdb was already opened as root , this is all we have */
if ( ! nt_token_check_domain_rid ( p - > pipe_user . nt_user_token , DOMAIN_GROUP_RID_ADMINS ) )
return NT_STATUS_ACCESS_DENIED ;
2003-10-06 05:38:46 +04:00
set = & q_u - > set ;
2001-11-29 19:05:05 +03:00
2003-10-06 05:38:46 +04:00
for ( i = 0 ; i < set - > count ; i + + ) {
2005-01-13 21:20:37 +03:00
mask = luid_to_privilege_mask ( & ( set - > set [ i ] . luid ) ) ;
if ( mask ! = SE_END ) {
if ( ! revoke_privilege ( & info - > sid , mask ) ) {
DEBUG ( 3 , ( " _lsa_removeprivs: revoke_privilege( %s, 0x%x) failed! \n " ,
sid_string_static ( & info - > sid ) , mask ) ) ;
return NT_STATUS_NO_SUCH_PRIVILEGE ;
}
2001-11-29 19:05:05 +03:00
}
}
2005-01-13 21:20:37 +03:00
return NT_STATUS_OK ;
2001-11-29 19:05:05 +03:00
}
2001-12-14 20:31:48 +03:00
/***************************************************************************
For a given SID , remove some privileges .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS _lsa_query_secobj ( pipes_struct * p , LSA_Q_QUERY_SEC_OBJ * q_u , LSA_R_QUERY_SEC_OBJ * r_u )
{
2001-12-18 02:03:23 +03:00
struct lsa_info * handle = NULL ;
2001-12-14 20:31:48 +03:00
SEC_DESC * psd = NULL ;
size_t sd_size ;
2001-12-18 02:03:23 +03:00
NTSTATUS status ;
2001-12-14 20:31:48 +03:00
r_u - > status = NT_STATUS_OK ;
/* find the connection policy handle. */
2001-12-18 02:03:23 +03:00
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) )
2001-12-14 20:31:48 +03:00
return NT_STATUS_INVALID_HANDLE ;
2001-12-18 02:03:23 +03:00
/* check if the user have enough rights */
if ( ! ( handle - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
2001-12-14 20:31:48 +03:00
switch ( q_u - > sec_info ) {
case 1 :
/* SD contains only the owner */
2001-12-18 02:03:23 +03:00
status = lsa_get_generic_sd ( p - > mem_ctx , & psd , & sd_size ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
2001-12-14 20:31:48 +03:00
return NT_STATUS_NO_MEMORY ;
2001-12-18 02:03:23 +03:00
2001-12-14 20:31:48 +03:00
if ( ( r_u - > buf = make_sec_desc_buf ( p - > mem_ctx , sd_size , psd ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
break ;
case 4 :
/* SD contains only the ACL */
2001-12-18 02:03:23 +03:00
status = lsa_get_generic_sd ( p - > mem_ctx , & psd , & sd_size ) ;
if ( ! NT_STATUS_IS_OK ( status ) )
2001-12-14 20:31:48 +03:00
return NT_STATUS_NO_MEMORY ;
if ( ( r_u - > buf = make_sec_desc_buf ( p - > mem_ctx , sd_size , psd ) ) = = NULL )
return NT_STATUS_NO_MEMORY ;
break ;
default :
return NT_STATUS_INVALID_LEVEL ;
}
r_u - > ptr = 1 ;
return r_u - > status ;
}
2005-01-15 05:20:30 +03:00
/***************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-12-14 20:31:48 +03:00
2002-08-17 19:34:15 +04:00
NTSTATUS _lsa_query_info2 ( pipes_struct * p , LSA_Q_QUERY_INFO2 * q_u , LSA_R_QUERY_INFO2 * r_u )
{
struct lsa_info * handle ;
2002-11-13 02:20:50 +03:00
const char * nb_name ;
2002-08-17 19:34:15 +04:00
char * dns_name = NULL ;
char * forest_name = NULL ;
DOM_SID * sid = NULL ;
2004-04-13 18:39:48 +04:00
struct uuid guid ;
2003-04-22 11:28:41 +04:00
fstring dnsdomname ;
2002-08-17 19:34:15 +04:00
ZERO_STRUCT ( guid ) ;
r_u - > status = NT_STATUS_OK ;
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & handle ) )
return NT_STATUS_INVALID_HANDLE ;
switch ( q_u - > info_class ) {
case 0x0c :
/* check if the user have enough rights */
if ( ! ( handle - > access & POLICY_VIEW_LOCAL_INFORMATION ) )
return NT_STATUS_ACCESS_DENIED ;
/* Request PolicyPrimaryDomainInformation. */
switch ( lp_server_role ( ) ) {
case ROLE_DOMAIN_PDC :
case ROLE_DOMAIN_BDC :
2003-05-07 12:21:06 +04:00
nb_name = get_global_sam_name ( ) ;
2002-08-17 19:34:15 +04:00
/* ugly temp hack for these next two */
2003-04-22 11:28:41 +04:00
/* This should be a 'netbios domain -> DNS domain' mapping */
dnsdomname [ 0 ] = ' \0 ' ;
2004-01-30 21:38:48 +03:00
get_mydnsdomname ( dnsdomname ) ;
2003-07-03 23:11:31 +04:00
strlower_m ( dnsdomname ) ;
2003-04-22 11:28:41 +04:00
dns_name = dnsdomname ;
forest_name = dnsdomname ;
2002-08-17 19:34:15 +04:00
sid = get_global_sam_sid ( ) ;
2002-11-13 02:20:50 +03:00
secrets_fetch_domain_guid ( lp_workgroup ( ) , & guid ) ;
2002-08-17 19:34:15 +04:00
break ;
default :
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO ;
}
init_dns_dom_info ( & r_u - > info . dns_dom_info , nb_name , dns_name ,
forest_name , & guid , sid ) ;
break ;
default :
DEBUG ( 0 , ( " _lsa_query_info2: unknown info level in Lsa Query: %d \n " , q_u - > info_class ) ) ;
r_u - > status = NT_STATUS_INVALID_INFO_CLASS ;
break ;
}
if ( NT_STATUS_IS_OK ( r_u - > status ) ) {
r_u - > ptr = 0x1 ;
r_u - > info_class = q_u - > info_class ;
}
return r_u - > status ;
}
2005-01-15 05:20:30 +03:00
/***************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS _lsa_add_acct_rights ( pipes_struct * p , LSA_Q_ADD_ACCT_RIGHTS * q_u , LSA_R_ADD_ACCT_RIGHTS * r_u )
{
struct lsa_info * info = NULL ;
int i = 0 ;
DOM_SID sid ;
fstring privname ;
UNISTR2_ARRAY * uni_privnames = & q_u - > rights ;
/* find the connection policy handle. */
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
return NT_STATUS_INVALID_HANDLE ;
/* check to see if the pipe_user is a Domain Admin since
account_pol . tdb was already opened as root , this is all we have */
if ( ! nt_token_check_domain_rid ( p - > pipe_user . nt_user_token , DOMAIN_GROUP_RID_ADMINS ) )
return NT_STATUS_ACCESS_DENIED ;
/* according to an NT4 PDC, you can add privileges to SIDs even without
call_lsa_create_account ( ) first . And you can use any arbitrary SID . */
sid_copy ( & sid , & q_u - > sid . sid ) ;
/* just a little sanity check */
if ( q_u - > count ! = uni_privnames - > count ) {
DEBUG ( 0 , ( " _lsa_add_acct_rights: count != number of UNISTR2 elements! \n " ) ) ;
return NT_STATUS_INVALID_HANDLE ;
}
for ( i = 0 ; i < q_u - > count ; i + + ) {
unistr2_to_ascii ( privname , & uni_privnames - > strings [ i ] . string , sizeof ( fstring ) - 1 ) ;
/* only try to add non-null strings */
if ( * privname & & ! grant_privilege_by_name ( & sid , privname ) ) {
DEBUG ( 2 , ( " _lsa_add_acct_rights: Failed to add privilege [%s] \n " , privname ) ) ;
return NT_STATUS_NO_SUCH_PRIVILEGE ;
}
}
return NT_STATUS_OK ;
}
/***************************************************************************
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
NTSTATUS _lsa_remove_acct_rights ( pipes_struct * p , LSA_Q_REMOVE_ACCT_RIGHTS * q_u , LSA_R_REMOVE_ACCT_RIGHTS * r_u )
{
struct lsa_info * info = NULL ;
int i = 0 ;
DOM_SID sid ;
fstring privname ;
UNISTR2_ARRAY * uni_privnames = & q_u - > rights ;
/* find the connection policy handle. */
if ( ! find_policy_by_hnd ( p , & q_u - > pol , ( void * * ) & info ) )
return NT_STATUS_INVALID_HANDLE ;
/* check to see if the pipe_user is a Domain Admin since
account_pol . tdb was already opened as root , this is all we have */
if ( ! nt_token_check_domain_rid ( p - > pipe_user . nt_user_token , DOMAIN_GROUP_RID_ADMINS ) )
return NT_STATUS_ACCESS_DENIED ;
/* according to an NT4 PDC, you can add privileges to SIDs even without
call_lsa_create_account ( ) first . And you can use any arbitrary SID . */
sid_copy ( & sid , & q_u - > sid . sid ) ;
if ( q_u - > removeall ) {
if ( ! revoke_privilege ( & sid , SE_ALL_PRIVS ) )
return NT_STATUS_ACCESS_DENIED ;
return NT_STATUS_OK ;
}
/* just a little sanity check */
if ( q_u - > count ! = uni_privnames - > count ) {
DEBUG ( 0 , ( " _lsa_add_acct_rights: count != number of UNISTR2 elements! \n " ) ) ;
return NT_STATUS_INVALID_HANDLE ;
}
for ( i = 0 ; i < q_u - > count ; i + + ) {
unistr2_to_ascii ( privname , & uni_privnames - > strings [ i ] . string , sizeof ( fstring ) - 1 ) ;
/* only try to add non-null strings */
if ( * privname & & ! revoke_privilege_by_name ( & sid , privname ) ) {
DEBUG ( 2 , ( " _lsa_remove_acct_rights: Failed to add privilege [%s] \n " , privname ) ) ;
return NT_STATUS_NO_SUCH_PRIVILEGE ;
}
}
return NT_STATUS_OK ;
}