2003-10-06 05:24:48 +04:00
/*
* Unix SMB / Netbios implementation .
2009-03-01 19:59:30 +03:00
* struct security_ace handling functions
2003-10-06 05:24:48 +04:00
* Copyright ( C ) Andrew Tridgell 1992 - 1998 ,
* Copyright ( C ) Jeremy R . Allison 1995 - 2003.
* Copyright ( C ) Luke Kenneth Casson Leighton 1996 - 1998 ,
* Copyright ( C ) Paul Ashton 1997 - 1998.
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
* the Free Software Foundation ; either version 3 of the License , or
2003-10-06 05:24:48 +04:00
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2007-07-10 09:23:25 +04:00
* along with this program ; if not , see < http : //www.gnu.org/licenses/>.
2003-10-06 05:24:48 +04:00
*/
# include "includes.h"
2009-03-01 19:59:30 +03:00
# include "librpc/gen_ndr/ndr_security.h"
2009-03-02 10:55:00 +03:00
# include "libcli/security/dom_sid.h"
2003-10-06 05:24:48 +04:00
2009-03-01 19:59:30 +03:00
# define SEC_ACE_HEADER_SIZE (2 * sizeof(uint8_t) + sizeof(uint16_t) + sizeof(uint32_t))
2003-10-06 05:24:48 +04:00
2009-03-01 19:59:30 +03:00
/**
* Check if ACE has OBJECT type .
*/
bool sec_ace_object ( uint8_t type )
2003-10-06 05:24:48 +04:00
{
if ( type = = SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT | |
type = = SEC_ACE_TYPE_ACCESS_DENIED_OBJECT | |
type = = SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT | |
type = = SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT ) {
2009-03-01 19:59:30 +03:00
return true ;
2003-10-06 05:24:48 +04:00
}
2009-03-01 19:59:30 +03:00
return false ;
2003-10-06 05:24:48 +04:00
}
2009-03-01 19:59:30 +03:00
/**
* copy a struct security_ace structure .
*/
void sec_ace_copy ( struct security_ace * ace_dest , struct security_ace * ace_src )
2003-10-06 05:24:48 +04:00
{
ace_dest - > type = ace_src - > type ;
ace_dest - > flags = ace_src - > flags ;
ace_dest - > size = ace_src - > size ;
2006-09-21 02:23:12 +04:00
ace_dest - > access_mask = ace_src - > access_mask ;
ace_dest - > object = ace_src - > object ;
2009-03-01 19:59:30 +03:00
ace_dest - > trustee = ace_src - > trustee ;
2003-10-06 05:24:48 +04:00
}
/*******************************************************************
2009-03-01 19:59:30 +03:00
Sets up a struct security_ace structure .
2003-10-06 05:24:48 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-01 19:59:30 +03:00
void init_sec_ace ( struct security_ace * t , const struct dom_sid * sid , enum security_ace_type type ,
uint32_t mask , uint8_t flag )
2003-10-06 05:24:48 +04:00
{
t - > type = type ;
t - > flags = flag ;
2009-01-01 06:45:33 +03:00
t - > size = ndr_size_dom_sid ( sid , NULL , 0 ) + 8 ;
2006-09-21 02:23:12 +04:00
t - > access_mask = mask ;
2003-10-06 05:24:48 +04:00
2009-03-01 19:59:30 +03:00
t - > trustee = * sid ;
2003-10-06 05:24:48 +04:00
}
/*******************************************************************
adds new SID with its permissions to ACE list
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-01 19:59:30 +03:00
NTSTATUS sec_ace_add_sid ( TALLOC_CTX * ctx , struct security_ace * * pp_new , struct security_ace * old , unsigned * num , struct dom_sid * sid , uint32_t mask )
2003-10-06 05:24:48 +04:00
{
unsigned int i = 0 ;
2005-06-25 00:25:18 +04:00
if ( ! ctx | | ! pp_new | | ! old | | ! sid | | ! num ) return NT_STATUS_INVALID_PARAMETER ;
2003-10-06 05:24:48 +04:00
* num + = 1 ;
2009-03-01 19:59:30 +03:00
if ( ( pp_new [ 0 ] = talloc_zero_array ( ctx , struct security_ace , * num ) ) = = 0 )
2003-10-06 05:24:48 +04:00
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < * num - 1 ; i + + )
2005-06-25 00:25:18 +04:00
sec_ace_copy ( & ( * pp_new ) [ i ] , & old [ i ] ) ;
2003-10-06 05:24:48 +04:00
2007-12-21 00:27:01 +03:00
( * pp_new ) [ i ] . type = SEC_ACE_TYPE_ACCESS_ALLOWED ;
2005-06-25 00:25:18 +04:00
( * pp_new ) [ i ] . flags = 0 ;
2009-01-01 06:45:33 +03:00
( * pp_new ) [ i ] . size = SEC_ACE_HEADER_SIZE + ndr_size_dom_sid ( sid , NULL , 0 ) ;
2006-09-21 02:23:12 +04:00
( * pp_new ) [ i ] . access_mask = mask ;
2009-03-01 19:59:30 +03:00
( * pp_new ) [ i ] . trustee = * sid ;
2003-10-06 05:24:48 +04:00
return NT_STATUS_OK ;
}
/*******************************************************************
modify SID ' s permissions at ACL
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-01 19:59:30 +03:00
NTSTATUS sec_ace_mod_sid ( struct security_ace * ace , size_t num , struct dom_sid * sid , uint32_t mask )
2003-10-06 05:24:48 +04:00
{
unsigned int i = 0 ;
if ( ! ace | | ! sid ) return NT_STATUS_INVALID_PARAMETER ;
for ( i = 0 ; i < num ; i + + ) {
2009-03-01 19:59:30 +03:00
if ( dom_sid_equal ( & ace [ i ] . trustee , sid ) ) {
2006-09-21 02:23:12 +04:00
ace [ i ] . access_mask = mask ;
2003-10-06 05:24:48 +04:00
return NT_STATUS_OK ;
}
}
return NT_STATUS_NOT_FOUND ;
}
/*******************************************************************
delete SID from ACL
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-01 19:59:30 +03:00
NTSTATUS sec_ace_del_sid ( TALLOC_CTX * ctx , struct security_ace * * pp_new , struct security_ace * old , uint32_t * num , struct dom_sid * sid )
2003-10-06 05:24:48 +04:00
{
unsigned int i = 0 ;
unsigned int n_del = 0 ;
2005-06-25 00:25:18 +04:00
if ( ! ctx | | ! pp_new | | ! old | | ! sid | | ! num ) return NT_STATUS_INVALID_PARAMETER ;
2003-10-06 05:24:48 +04:00
2007-04-30 06:51:26 +04:00
if ( * num ) {
2009-03-01 19:59:30 +03:00
if ( ( pp_new [ 0 ] = talloc_zero_array ( ctx , struct security_ace , * num ) ) = = 0 )
2007-04-30 06:51:26 +04:00
return NT_STATUS_NO_MEMORY ;
} else {
pp_new [ 0 ] = NULL ;
}
2003-10-06 05:24:48 +04:00
for ( i = 0 ; i < * num ; i + + ) {
2009-03-01 19:59:30 +03:00
if ( ! dom_sid_equal ( & old [ i ] . trustee , sid ) )
2005-06-25 00:25:18 +04:00
sec_ace_copy ( & ( * pp_new ) [ i ] , & old [ i ] ) ;
2003-10-06 05:24:48 +04:00
else
n_del + + ;
}
if ( n_del = = 0 )
return NT_STATUS_NOT_FOUND ;
else {
* num - = n_del ;
return NT_STATUS_OK ;
}
}
/*******************************************************************
2009-03-01 19:59:30 +03:00
Compares two struct security_ace structures
2003-10-06 05:24:48 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-01 19:59:30 +03:00
bool sec_ace_equal ( struct security_ace * s1 , struct security_ace * s2 )
2003-10-06 05:24:48 +04:00
{
/* Trivial case */
2006-03-08 04:01:34 +03:00
if ( ! s1 & & ! s2 ) {
2009-03-01 19:59:30 +03:00
return true ;
2006-03-08 04:01:34 +03:00
}
if ( ! s1 | | ! s2 ) {
2009-03-01 19:59:30 +03:00
return false ;
2006-03-08 04:01:34 +03:00
}
2003-10-06 05:24:48 +04:00
/* Check top level stuff */
if ( s1 - > type ! = s2 - > type | | s1 - > flags ! = s2 - > flags | |
2006-09-21 02:23:12 +04:00
s1 - > access_mask ! = s2 - > access_mask ) {
2009-03-01 19:59:30 +03:00
return false ;
2003-10-06 05:24:48 +04:00
}
/* Check SID */
2009-03-01 19:59:30 +03:00
if ( ! dom_sid_equal ( & s1 - > trustee , & s2 - > trustee ) ) {
return false ;
2003-10-06 05:24:48 +04:00
}
2009-03-01 19:59:30 +03:00
return true ;
2003-10-06 05:24:48 +04:00
}
2009-03-01 19:59:30 +03:00
int nt_ace_inherit_comp ( struct security_ace * a1 , struct security_ace * a2 )
2003-10-06 05:24:48 +04:00
{
int a1_inh = a1 - > flags & SEC_ACE_FLAG_INHERITED_ACE ;
int a2_inh = a2 - > flags & SEC_ACE_FLAG_INHERITED_ACE ;
if ( a1_inh = = a2_inh )
return 0 ;
if ( ! a1_inh & & a2_inh )
return - 1 ;
return 1 ;
}
/*******************************************************************
Comparison function to apply the order explained below in a group .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-01 19:59:30 +03:00
int nt_ace_canon_comp ( struct security_ace * a1 , struct security_ace * a2 )
2003-10-06 05:24:48 +04:00
{
if ( ( a1 - > type = = SEC_ACE_TYPE_ACCESS_DENIED ) & &
( a2 - > type ! = SEC_ACE_TYPE_ACCESS_DENIED ) )
return - 1 ;
if ( ( a2 - > type = = SEC_ACE_TYPE_ACCESS_DENIED ) & &
( a1 - > type ! = SEC_ACE_TYPE_ACCESS_DENIED ) )
return 1 ;
/* Both access denied or access allowed. */
/* 1. ACEs that apply to the object itself */
if ( ! ( a1 - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) & &
( a2 - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) )
return - 1 ;
else if ( ! ( a2 - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) & &
( a1 - > flags & SEC_ACE_FLAG_INHERIT_ONLY ) )
return 1 ;
/* 2. ACEs that apply to a subobject of the object, such as
* a property set or property . */
if ( a1 - > flags & ( SEC_ACE_FLAG_CONTAINER_INHERIT | SEC_ACE_FLAG_OBJECT_INHERIT ) & &
! ( a2 - > flags & ( SEC_ACE_FLAG_CONTAINER_INHERIT | SEC_ACE_FLAG_OBJECT_INHERIT ) ) )
return - 1 ;
else if ( a2 - > flags & ( SEC_ACE_FLAG_CONTAINER_INHERIT | SEC_ACE_FLAG_OBJECT_INHERIT ) & &
! ( a1 - > flags & ( SEC_ACE_FLAG_CONTAINER_INHERIT | SEC_ACE_FLAG_OBJECT_INHERIT ) ) )
return 1 ;
return 0 ;
}
/*******************************************************************
Functions to convert a SEC_DESC ACE DACL list into canonical order .
JRA .
- - - from http : //msdn.microsoft.com/library/default.asp?url=/library/en-us/security/security/order_of_aces_in_a_dacl.asp
The following describes the preferred order :
To ensure that noninherited ACEs have precedence over inherited ACEs ,
place all noninherited ACEs in a group before any inherited ACEs .
This ordering ensures , for example , that a noninherited access - denied ACE
is enforced regardless of any inherited ACE that allows access .
Within the groups of noninherited ACEs and inherited ACEs , order ACEs according to ACE type , as the following shows :
1. Access - denied ACEs that apply to the object itself
2. Access - denied ACEs that apply to a subobject of the object , such as a property set or property
3. Access - allowed ACEs that apply to the object itself
4. Access - allowed ACEs that apply to a subobject of the object "
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-03-01 19:59:30 +03:00
void dacl_sort_into_canonical_order ( struct security_ace * srclist , unsigned int num_aces )
2003-10-06 05:24:48 +04:00
{
unsigned int i ;
if ( ! srclist | | num_aces = = 0 )
return ;
/* Sort so that non-inherited ACE's come first. */
qsort ( srclist , num_aces , sizeof ( srclist [ 0 ] ) , QSORT_CAST nt_ace_inherit_comp ) ;
/* Find the boundary between non-inherited ACEs. */
for ( i = 0 ; i < num_aces ; i + + ) {
2009-03-01 19:59:30 +03:00
struct security_ace * curr_ace = & srclist [ i ] ;
2003-10-06 05:24:48 +04:00
if ( curr_ace - > flags & SEC_ACE_FLAG_INHERITED_ACE )
break ;
}
/* i now points at entry number of the first inherited ACE. */
/* Sort the non-inherited ACEs. */
if ( i )
qsort ( srclist , i , sizeof ( srclist [ 0 ] ) , QSORT_CAST nt_ace_canon_comp ) ;
/* Now sort the inherited ACEs. */
if ( num_aces - i )
qsort ( & srclist [ i ] , num_aces - i , sizeof ( srclist [ 0 ] ) , QSORT_CAST nt_ace_canon_comp ) ;
}