2023-03-03 20:48:25 +03:00
/*
2005-12-02 06:16:42 +03:00
Unix SMB / CIFS implementation .
security descriptor description language functions
Copyright ( C ) Andrew Tridgell 2005
2023-03-03 20:48:25 +03:00
2005-12-02 06:16:42 +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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2005-12-02 06:16:42 +03:00
( at your option ) any later version .
2023-03-03 20:48:25 +03:00
2005-12-02 06:16:42 +03:00
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 .
2023-03-03 20:48:25 +03:00
2005-12-02 06:16:42 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-12-02 06:16:42 +03:00
*/
2023-03-03 20:41:33 +03:00
# include "replace.h"
# include "lib/util/debug.h"
2010-10-12 08:27:50 +04:00
# include "libcli/security/security.h"
2006-04-29 21:34:49 +04:00
# include "librpc/gen_ndr/ndr_misc.h"
2023-03-24 00:28:09 +03:00
# include "lib/util/smb_strtox.h"
2022-12-02 02:43:21 +03:00
# include "libcli/security/sddl.h"
2006-05-13 23:14:12 +04:00
# include "system/locale.h"
2023-04-26 01:24:25 +03:00
# include "lib/util/util_str_hex.h"
2005-12-02 06:16:42 +03:00
2020-04-30 20:49:12 +03:00
struct sddl_transition_state {
2016-01-14 13:02:10 +03:00
const struct dom_sid * machine_sid ;
2020-04-30 20:49:12 +03:00
const struct dom_sid * domain_sid ;
2016-01-14 13:02:10 +03:00
const struct dom_sid * forest_sid ;
2020-04-30 20:49:12 +03:00
} ;
2005-12-02 06:16:42 +03:00
struct flag_map {
const char * name ;
uint32_t flag ;
} ;
2021-04-19 15:46:21 +03:00
static bool sddl_map_flag (
const struct flag_map * map ,
const char * str ,
size_t * plen ,
uint32_t * pflag )
{
while ( map - > name ! = NULL ) {
size_t len = strlen ( map - > name ) ;
int cmp = strncmp ( map - > name , str , len ) ;
if ( cmp = = 0 ) {
* plen = len ;
* pflag = map - > flag ;
return true ;
}
map + = 1 ;
}
return false ;
}
2005-12-02 06:16:42 +03:00
/*
map a series of letter codes into a uint32_t
*/
2023-03-03 20:48:25 +03:00
static bool sddl_map_flags ( const struct flag_map * map , const char * str ,
2023-03-16 11:17:56 +03:00
uint32_t * pflags , size_t * plen ,
bool unknown_flag_is_part_of_next_thing )
2005-12-02 06:16:42 +03:00
{
2005-12-02 07:26:51 +03:00
const char * str0 = str ;
2021-04-19 15:46:21 +03:00
if ( plen ! = NULL ) {
* plen = 0 ;
}
* pflags = 0 ;
2023-04-21 06:47:10 +03:00
while ( str [ 0 ] ! = ' \0 ' & & isupper ( ( unsigned char ) str [ 0 ] ) ) {
2021-04-19 15:46:21 +03:00
size_t len ;
uint32_t flags ;
bool found ;
found = sddl_map_flag ( map , str , & len , & flags ) ;
if ( ! found ) {
2023-04-21 06:47:10 +03:00
break ;
2005-12-02 06:16:42 +03:00
}
2021-04-19 15:46:21 +03:00
* pflags | = flags ;
if ( plen ! = NULL ) {
* plen + = len ;
}
str + = len ;
2005-12-02 06:16:42 +03:00
}
2023-04-21 06:47:10 +03:00
/*
* For ACL flags , unknown_flag_is_part_of_next_thing is set ,
* and we expect some more stuff that isn ' t flags .
*
* For ACE flags , unknown_flag_is_part_of_next_thing is unset ,
* and the flags have been tokenised into their own little
* string . We don ' t expect anything here , even whitespace .
*/
if ( * str = = ' \0 ' | | unknown_flag_is_part_of_next_thing ) {
return true ;
}
DBG_WARNING ( " Unknown flag - '%s' in '%s' \n " , str , str0 ) ;
return false ;
2005-12-02 06:16:42 +03:00
}
2023-03-16 11:17:56 +03:00
2005-12-02 06:16:42 +03:00
/*
a mapping between the 2 letter SID codes and sid strings
*/
static const struct {
const char * code ;
const char * sid ;
2016-01-14 13:02:10 +03:00
uint32_t machine_rid ;
uint32_t domain_rid ;
uint32_t forest_rid ;
2005-12-02 06:16:42 +03:00
} sid_codes [ ] = {
2018-12-12 23:18:32 +03:00
{ . code = " WD " , . sid = SID_WORLD } ,
2005-12-02 07:26:51 +03:00
2018-12-12 23:18:32 +03:00
{ . code = " CO " , . sid = SID_CREATOR_OWNER } ,
{ . code = " CG " , . sid = SID_CREATOR_GROUP } ,
2022-03-14 08:18:09 +03:00
{ . code = " OW " , . sid = SID_OWNER_RIGHTS } ,
2005-12-02 07:26:51 +03:00
2018-12-12 23:18:32 +03:00
{ . code = " NU " , . sid = SID_NT_NETWORK } ,
{ . code = " IU " , . sid = SID_NT_INTERACTIVE } ,
{ . code = " SU " , . sid = SID_NT_SERVICE } ,
{ . code = " AN " , . sid = SID_NT_ANONYMOUS } ,
{ . code = " ED " , . sid = SID_NT_ENTERPRISE_DCS } ,
{ . code = " PS " , . sid = SID_NT_SELF } ,
{ . code = " AU " , . sid = SID_NT_AUTHENTICATED_USERS } ,
{ . code = " RC " , . sid = SID_NT_RESTRICTED } ,
{ . code = " SY " , . sid = SID_NT_SYSTEM } ,
{ . code = " LS " , . sid = SID_NT_LOCAL_SERVICE } ,
{ . code = " NS " , . sid = SID_NT_NETWORK_SERVICE } ,
2022-03-14 08:18:09 +03:00
{ . code = " WR " , . sid = SID_SECURITY_RESTRICTED_CODE } ,
2009-11-28 00:37:52 +03:00
2018-12-12 23:18:32 +03:00
{ . code = " BA " , . sid = SID_BUILTIN_ADMINISTRATORS } ,
{ . code = " BU " , . sid = SID_BUILTIN_USERS } ,
{ . code = " BG " , . sid = SID_BUILTIN_GUESTS } ,
{ . code = " PU " , . sid = SID_BUILTIN_POWER_USERS } ,
{ . code = " AO " , . sid = SID_BUILTIN_ACCOUNT_OPERATORS } ,
{ . code = " SO " , . sid = SID_BUILTIN_SERVER_OPERATORS } ,
{ . code = " PO " , . sid = SID_BUILTIN_PRINT_OPERATORS } ,
{ . code = " BO " , . sid = SID_BUILTIN_BACKUP_OPERATORS } ,
{ . code = " RE " , . sid = SID_BUILTIN_REPLICATOR } ,
{ . code = " RU " , . sid = SID_BUILTIN_PREW2K } ,
{ . code = " RD " , . sid = SID_BUILTIN_REMOTE_DESKTOP_USERS } ,
{ . code = " NO " , . sid = SID_BUILTIN_NETWORK_CONF_OPERATORS } ,
2009-11-28 00:37:52 +03:00
2022-03-14 08:18:09 +03:00
{ . code = " MU " , . sid = SID_BUILTIN_PERFMON_USERS } ,
{ . code = " LU " , . sid = SID_BUILTIN_PERFLOG_USERS } ,
2022-03-14 08:14:15 +03:00
{ . code = " IS " , . sid = SID_BUILTIN_IUSERS } ,
2022-03-14 08:18:09 +03:00
{ . code = " CY " , . sid = SID_BUILTIN_CRYPTO_OPERATORS } ,
2022-03-14 08:14:15 +03:00
{ . code = " ER " , . sid = SID_BUILTIN_EVENT_LOG_READERS } ,
2022-03-14 08:18:09 +03:00
{ . code = " CD " , . sid = SID_BUILTIN_CERT_SERV_DCOM_ACCESS } ,
{ . code = " RA " , . sid = SID_BUILTIN_RDS_REMOTE_ACCESS_SERVERS } ,
{ . code = " ES " , . sid = SID_BUILTIN_RDS_ENDPOINT_SERVERS } ,
{ . code = " MS " , . sid = SID_BUILTIN_RDS_MANAGEMENT_SERVERS } ,
{ . code = " HA " , . sid = SID_BUILTIN_HYPER_V_ADMINS } ,
{ . code = " AA " , . sid = SID_BUILTIN_ACCESS_CONTROL_ASSISTANCE_OPS } ,
{ . code = " RM " , . sid = SID_BUILTIN_REMOTE_MANAGEMENT_USERS } ,
{ . code = " UD " , . sid = SID_USER_MODE_DRIVERS } ,
{ . code = " AC " , . sid = SID_SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } ,
{ . code = " LW " , . sid = SID_SECURITY_MANDATORY_LOW } ,
{ . code = " ME " , . sid = SID_SECURITY_MANDATORY_MEDIUM } ,
{ . code = " MP " , . sid = SID_SECURITY_MANDATORY_MEDIUM_PLUS } ,
{ . code = " HI " , . sid = SID_SECURITY_MANDATORY_HIGH } ,
{ . code = " SI " , . sid = SID_SECURITY_MANDATORY_SYSTEM } ,
{ . code = " AS " , . sid = SID_AUTHENTICATION_AUTHORITY_ASSERTED_IDENTITY } ,
{ . code = " SS " , . sid = SID_SERVICE_ASSERTED_IDENTITY } ,
2022-03-14 08:14:15 +03:00
2016-01-14 13:02:10 +03:00
{ . code = " RO " , . forest_rid = DOMAIN_RID_ENTERPRISE_READONLY_DCS } ,
2022-03-14 08:14:15 +03:00
2016-01-14 13:02:10 +03:00
{ . code = " LA " , . machine_rid = DOMAIN_RID_ADMINISTRATOR } ,
{ . code = " LG " , . machine_rid = DOMAIN_RID_GUEST } ,
2009-05-29 05:18:33 +04:00
2016-01-14 13:02:10 +03:00
{ . code = " DA " , . domain_rid = DOMAIN_RID_ADMINS } ,
{ . code = " DU " , . domain_rid = DOMAIN_RID_USERS } ,
{ . code = " DG " , . domain_rid = DOMAIN_RID_GUESTS } ,
{ . code = " DC " , . domain_rid = DOMAIN_RID_DOMAIN_MEMBERS } ,
{ . code = " DD " , . domain_rid = DOMAIN_RID_DCS } ,
{ . code = " CA " , . domain_rid = DOMAIN_RID_CERT_ADMINS } ,
{ . code = " SA " , . forest_rid = DOMAIN_RID_SCHEMA_ADMINS } ,
{ . code = " EA " , . forest_rid = DOMAIN_RID_ENTERPRISE_ADMINS } ,
{ . code = " PA " , . domain_rid = DOMAIN_RID_POLICY_ADMINS } ,
2022-03-14 08:18:09 +03:00
2016-01-14 13:02:10 +03:00
{ . code = " CN " , . domain_rid = DOMAIN_RID_CLONEABLE_CONTROLLERS } ,
2022-03-14 08:18:09 +03:00
2016-01-14 13:02:10 +03:00
{ . code = " AP " , . domain_rid = DOMAIN_RID_PROTECTED_USERS } ,
{ . code = " KA " , . domain_rid = DOMAIN_RID_KEY_ADMINS } ,
{ . code = " EK " , . forest_rid = DOMAIN_RID_ENTERPRISE_KEY_ADMINS } ,
2022-03-14 08:18:09 +03:00
2016-01-14 13:02:10 +03:00
{ . code = " RS " , . domain_rid = DOMAIN_RID_RAS_SERVERS }
2005-12-02 06:16:42 +03:00
} ;
/*
decode a SID
It can either be a special 2 letter code , or in S - * format
*/
2022-12-02 02:43:21 +03:00
static struct dom_sid * sddl_transition_decode_sid ( TALLOC_CTX * mem_ctx , const char * * sddlp ,
struct sddl_transition_state * state )
2005-12-02 06:16:42 +03:00
{
const char * sddl = ( * sddlp ) ;
2020-09-29 10:55:22 +03:00
size_t i ;
2005-12-02 06:16:42 +03:00
/* see if its in the numeric format */
if ( strncmp ( sddl , " S- " , 2 ) = = 0 ) {
2023-03-16 05:46:08 +03:00
struct dom_sid * sid = NULL ;
char * sid_str = NULL ;
const char * end = NULL ;
bool ok ;
size_t len = strspn ( sddl + 2 , " -0123456789ABCDEFabcdefxX " ) + 2 ;
if ( len < 5 ) { /* S-1-x */
2007-01-15 12:02:58 +03:00
return NULL ;
}
2023-03-16 05:46:08 +03:00
if ( sddl [ len - 1 ] = = ' D ' & & sddl [ len ] = = ' : ' ) {
/*
* we have run into the " D: " dacl marker , mistaking it
* for a hex digit . There is no other way for this
* pair to occur at the end of a SID in SDDL .
*/
len - - ;
}
sid_str = talloc_strndup ( mem_ctx , sddl , len ) ;
if ( sid_str = = NULL ) {
return NULL ;
}
sid = talloc ( mem_ctx , struct dom_sid ) ;
if ( sid = = NULL ) {
TALLOC_FREE ( sid_str ) ;
return NULL ;
} ;
ok = dom_sid_parse_endp ( sid_str , sid , & end ) ;
if ( ! ok ) {
DBG_WARNING ( " could not parse SID '%s' \n " , sid_str ) ;
TALLOC_FREE ( sid_str ) ;
TALLOC_FREE ( sid ) ;
return NULL ;
}
if ( end - sid_str ! = len ) {
DBG_WARNING ( " trailing junk after SID '%s' \n " , sid_str ) ;
TALLOC_FREE ( sid_str ) ;
TALLOC_FREE ( sid ) ;
return NULL ;
}
TALLOC_FREE ( sid_str ) ;
( * sddlp ) + = len ;
2007-01-15 12:02:58 +03:00
return sid ;
2005-12-02 06:16:42 +03:00
}
/* now check for one of the special codes */
for ( i = 0 ; i < ARRAY_SIZE ( sid_codes ) ; i + + ) {
2005-12-02 07:26:51 +03:00
if ( strncmp ( sid_codes [ i ] . code , sddl , 2 ) = = 0 ) break ;
2005-12-02 06:16:42 +03:00
}
if ( i = = ARRAY_SIZE ( sid_codes ) ) {
2005-12-02 07:26:51 +03:00
DEBUG ( 1 , ( " Unknown sddl sid code '%2.2s' \n " , sddl ) ) ;
2005-12-02 06:16:42 +03:00
return NULL ;
}
( * sddlp ) + = 2 ;
2005-12-02 07:26:51 +03:00
2016-01-14 13:02:10 +03:00
if ( sid_codes [ i ] . machine_rid ! = 0 ) {
return dom_sid_add_rid ( mem_ctx , state - > machine_sid ,
sid_codes [ i ] . machine_rid ) ;
}
if ( sid_codes [ i ] . domain_rid ! = 0 ) {
return dom_sid_add_rid ( mem_ctx , state - > domain_sid ,
sid_codes [ i ] . domain_rid ) ;
}
if ( sid_codes [ i ] . forest_rid ! = 0 ) {
return dom_sid_add_rid ( mem_ctx , state - > forest_sid ,
sid_codes [ i ] . forest_rid ) ;
2005-12-02 07:26:51 +03:00
}
2005-12-02 06:16:42 +03:00
return dom_sid_parse_talloc ( mem_ctx , sid_codes [ i ] . sid ) ;
}
2022-12-02 02:43:21 +03:00
struct dom_sid * sddl_decode_sid ( TALLOC_CTX * mem_ctx , const char * * sddlp ,
const struct dom_sid * domain_sid )
{
struct sddl_transition_state state = {
/*
* TODO : verify . machine_rid values really belong to
* to the machine_sid on a member , once
* we pass machine_sid from the caller . . .
*/
. machine_sid = domain_sid ,
. domain_sid = domain_sid ,
. forest_sid = domain_sid ,
} ;
return sddl_transition_decode_sid ( mem_ctx , sddlp , & state ) ;
}
2005-12-02 06:16:42 +03:00
static const struct flag_map ace_types [ ] = {
{ " AU " , SEC_ACE_TYPE_SYSTEM_AUDIT } ,
{ " AL " , SEC_ACE_TYPE_SYSTEM_ALARM } ,
{ " OA " , SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT } ,
{ " OD " , SEC_ACE_TYPE_ACCESS_DENIED_OBJECT } ,
{ " OU " , SEC_ACE_TYPE_SYSTEM_AUDIT_OBJECT } ,
{ " OL " , SEC_ACE_TYPE_SYSTEM_ALARM_OBJECT } ,
2005-12-02 07:26:51 +03:00
{ " A " , SEC_ACE_TYPE_ACCESS_ALLOWED } ,
{ " D " , SEC_ACE_TYPE_ACCESS_DENIED } ,
2005-12-02 06:16:42 +03:00
{ NULL , 0 }
} ;
static const struct flag_map ace_flags [ ] = {
{ " OI " , SEC_ACE_FLAG_OBJECT_INHERIT } ,
{ " CI " , SEC_ACE_FLAG_CONTAINER_INHERIT } ,
{ " NP " , SEC_ACE_FLAG_NO_PROPAGATE_INHERIT } ,
{ " IO " , SEC_ACE_FLAG_INHERIT_ONLY } ,
{ " ID " , SEC_ACE_FLAG_INHERITED_ACE } ,
{ " SA " , SEC_ACE_FLAG_SUCCESSFUL_ACCESS } ,
{ " FA " , SEC_ACE_FLAG_FAILED_ACCESS } ,
{ NULL , 0 } ,
} ;
static const struct flag_map ace_access_mask [ ] = {
{ " CC " , SEC_ADS_CREATE_CHILD } ,
{ " DC " , SEC_ADS_DELETE_CHILD } ,
{ " LC " , SEC_ADS_LIST } ,
2022-03-15 04:01:13 +03:00
{ " SW " , SEC_ADS_SELF_WRITE } ,
{ " RP " , SEC_ADS_READ_PROP } ,
{ " WP " , SEC_ADS_WRITE_PROP } ,
{ " DT " , SEC_ADS_DELETE_TREE } ,
2005-12-02 06:16:42 +03:00
{ " LO " , SEC_ADS_LIST_OBJECT } ,
2022-03-15 04:01:13 +03:00
{ " CR " , SEC_ADS_CONTROL_ACCESS } ,
{ " SD " , SEC_STD_DELETE } ,
2005-12-09 08:21:47 +03:00
{ " RC " , SEC_STD_READ_CONTROL } ,
2005-12-02 06:16:42 +03:00
{ " WD " , SEC_STD_WRITE_DAC } ,
2022-03-15 04:01:13 +03:00
{ " WO " , SEC_STD_WRITE_OWNER } ,
2005-12-02 07:26:51 +03:00
{ " GA " , SEC_GENERIC_ALL } ,
{ " GX " , SEC_GENERIC_EXECUTE } ,
2022-03-15 04:01:13 +03:00
{ " GW " , SEC_GENERIC_WRITE } ,
{ " GR " , SEC_GENERIC_READ } ,
2005-12-02 06:16:42 +03:00
{ NULL , 0 }
} ;
2021-03-22 16:43:54 +03:00
static const struct flag_map decode_ace_access_mask [ ] = {
2022-08-25 15:52:56 +03:00
{ " FA " , FILE_GENERIC_ALL } ,
2021-03-22 16:43:54 +03:00
{ " FR " , FILE_GENERIC_READ } ,
{ " FW " , FILE_GENERIC_WRITE } ,
{ " FX " , FILE_GENERIC_EXECUTE } ,
{ NULL , 0 } ,
} ;
s3/utils: when encoding ace string use "FA", "FR", "FW", "FX" string rights
prior to this patch rights matching "FA", "FR", "FW", "FX" were
outputted as the hex string representing the bit value.
While outputting the hex string is perfectly fine, it makes it harder
to compare icacls output (which always uses the special string values)
Additionally adjust various tests to deal with use of shortcut access masks
as sddl format now uses FA, FR, FW & FX strings (like icalcs does) instead
of hex representation of the bit mask.
adjust
samba4.blackbox.samba-tool_ntacl
samba3.blackbox.large_acl
samba.tests.samba_tool.ntacl
samba.tests.ntacls
samba.tests.posixacl
so various string comparisons of the sddl format now pass
Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
[abartlet@samba.org Adapted to new stricter SDDL behaviour around leading zeros in hex
numbers, eg 0x001]
2022-08-25 16:29:09 +03:00
static char * sddl_match_file_rights ( TALLOC_CTX * mem_ctx ,
uint32_t flags )
{
int i ;
/* try to find an exact match */
for ( i = 0 ; decode_ace_access_mask [ i ] . name ; i + + ) {
if ( decode_ace_access_mask [ i ] . flag = = flags ) {
return talloc_strdup ( mem_ctx ,
decode_ace_access_mask [ i ] . name ) ;
}
}
return NULL ;
}
2021-04-19 17:00:27 +03:00
static bool sddl_decode_access ( const char * str , uint32_t * pmask )
{
const char * str0 = str ;
2023-04-12 01:46:30 +03:00
char * end = NULL ;
2021-04-19 17:00:27 +03:00
uint32_t mask = 0 ;
2023-03-24 00:28:09 +03:00
unsigned long long numeric_mask ;
int err ;
/*
* The access mask can be a number or a series of flags .
*
* Canonically the number is expressed in hexadecimal ( with 0 x ) , but
* per MS - DTYP and Windows behaviour , octal and decimal numbers are
* also accepted .
*
2023-04-12 01:46:30 +03:00
* Windows has two behaviours we choose not to replicate :
*
* 1. numbers exceeding 0xffffffff are truncated at that point ,
* turning on all access flags .
*
* 2. negative numbers are accepted , so e . g . - 2 becomes 0xfffffffe .
2023-03-24 00:28:09 +03:00
*/
2023-04-12 01:46:30 +03:00
numeric_mask = smb_strtoull ( str , & end , 0 , & err , SMB_STR_STANDARD ) ;
2023-03-24 00:28:09 +03:00
if ( err = = 0 ) {
2023-04-12 01:46:30 +03:00
if ( numeric_mask > UINT32_MAX ) {
DBG_WARNING ( " Bad numeric flag value - %llu in %s \n " ,
numeric_mask , str0 ) ;
return false ;
}
if ( end - str > sizeof ( " 037777777777 " ) ) {
/* here's the tricky thing: if a number is big
* enough to overflow the uint64 , it might end
* up small enough to fit in the uint32 , and
* we ' d miss that it overflowed . So we count
* the digits - - any more than 12 ( for
* " 037777777777 " ) is too long for 32 bits ,
* and the shortest 64 - bit wrapping string is
* 19 ( for " 0x1 " + 16 zeros ) .
*/
2023-04-21 06:47:32 +03:00
DBG_WARNING ( " Bad numeric flag value in '%s' \n " , str0 ) ;
return false ;
}
if ( * end ! = ' \0 ' ) {
DBG_WARNING ( " Bad characters in '%s' \n " , str0 ) ;
2023-04-12 01:46:30 +03:00
return false ;
}
2023-03-24 00:28:09 +03:00
* pmask = numeric_mask ;
2021-04-19 17:00:27 +03:00
return true ;
}
2023-04-12 01:46:30 +03:00
/* It's not a positive number, so we'll look for flags */
2021-04-19 17:00:27 +03:00
2023-04-23 03:36:35 +03:00
while ( ( str [ 0 ] ! = ' \0 ' ) & &
( isupper ( ( unsigned char ) str [ 0 ] ) | | str [ 0 ] = = ' ' ) ) {
2021-04-19 17:00:27 +03:00
uint32_t flags = 0 ;
size_t len = 0 ;
bool found ;
2023-04-23 03:36:35 +03:00
while ( str [ 0 ] = = ' ' ) {
/*
* Following Windows we accept spaces between flags
* but not after flags . Not tabs , though , never tabs .
*/
str + + ;
if ( str [ 0 ] = = ' \0 ' ) {
DBG_WARNING ( " trailing whitespace in flags "
" - '%s' \n " , str0 ) ;
return false ;
}
}
2021-04-19 17:00:27 +03:00
found = sddl_map_flag (
ace_access_mask , str , & len , & flags ) ;
found | = sddl_map_flag (
decode_ace_access_mask , str , & len , & flags ) ;
if ( ! found ) {
DEBUG ( 1 , ( " Unknown flag - %s in %s \n " , str , str0 ) ) ;
return false ;
}
mask | = flags ;
str + = len ;
}
2023-04-21 06:47:32 +03:00
if ( * str ! = ' \0 ' ) {
DBG_WARNING ( " Bad characters in '%s' \n " , str0 ) ;
return false ;
}
2021-04-19 17:00:27 +03:00
* pmask = mask ;
return true ;
}
2023-04-26 01:24:25 +03:00
static bool sddl_decode_guid ( const char * str , struct GUID * guid )
{
if ( strlen ( str ) ! = 36 ) {
return false ;
}
return parse_guid_string ( str , guid ) ;
}
2005-12-02 06:16:42 +03:00
/*
decode an ACE
2007-10-07 02:28:14 +04:00
return true on success , false on failure
2005-12-02 06:16:42 +03:00
note that this routine modifies the string
*/
2023-07-21 07:51:53 +03:00
static bool sddl_decode_ace ( TALLOC_CTX * mem_ctx ,
struct security_ace * ace ,
char * * sddl_copy ,
2020-04-30 20:49:12 +03:00
struct sddl_transition_state * state )
2005-12-02 06:16:42 +03:00
{
2023-07-21 07:51:53 +03:00
const char * tok [ 7 ] ;
2005-12-02 06:16:42 +03:00
const char * s ;
uint32_t v ;
struct dom_sid * sid ;
2021-04-19 17:00:27 +03:00
bool ok ;
2023-03-24 06:18:44 +03:00
size_t len ;
2023-07-21 07:51:53 +03:00
size_t count = 0 ;
char * str = * sddl_copy ;
2005-12-02 07:26:51 +03:00
ZERO_STRUCTP ( ace ) ;
2023-07-21 07:51:53 +03:00
if ( * str ! = ' ( ' ) {
return false ;
}
str + + ;
/*
* First we split apart the 6 tokens .
*
* 0. ace type
* 1. ace flags
* 2. access mask
* 3. object guid
* 4. inherit guid
* 5. sid
*
*/
2005-12-02 06:16:42 +03:00
tok [ 0 ] = str ;
2023-07-21 07:51:53 +03:00
while ( * str ! = ' \0 ' ) {
if ( * str = = ' ; ' ) {
* str = ' \0 ' ;
str + + ;
count + + ;
tok [ count ] = str ;
if ( count = = 6 ) {
/*
* When we get conditional or resource ACEs ,
* this will set a flag and break ;
* for now we just . . .
*/
return false ;
}
continue ;
}
/*
* we are not expecting a ' ) ' in the 6 sections of an
* ordinary ACE , except ending the last one .
*/
if ( * str = = ' ) ' ) {
count + + ;
* str = ' \0 ' ;
str + + ;
break ;
}
str + + ;
}
if ( count ! = 6 ) {
/* we hit the '\0' or ')' before all of ';;;;;)' */
DBG_WARNING ( " malformed ACE with only %zu ';' \n " , count ) ;
return false ;
2005-12-02 06:16:42 +03:00
}
/* parse ace type */
2023-03-24 06:18:44 +03:00
ok = sddl_map_flag ( ace_types , tok [ 0 ] , & len , & v ) ;
if ( ! ok ) {
DBG_WARNING ( " Unknown ACE type - %s \n " , tok [ 0 ] ) ;
return false ;
}
if ( tok [ 0 ] [ len ] ! = ' \0 ' ) {
DBG_WARNING ( " Garbage after ACE type - %s \n " , tok [ 0 ] ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-12-02 06:16:42 +03:00
}
2023-03-24 06:18:44 +03:00
2005-12-02 06:16:42 +03:00
ace - > type = v ;
/* ace flags */
2023-03-16 11:17:56 +03:00
if ( ! sddl_map_flags ( ace_flags , tok [ 1 ] , & v , NULL , false ) ) {
2007-10-07 02:28:14 +04:00
return false ;
2005-12-02 06:16:42 +03:00
}
ace - > flags = v ;
2023-03-03 20:48:25 +03:00
2005-12-02 06:16:42 +03:00
/* access mask */
2021-04-19 17:00:27 +03:00
ok = sddl_decode_access ( tok [ 2 ] , & ace - > access_mask ) ;
if ( ! ok ) {
return false ;
2005-12-02 06:16:42 +03:00
}
/* object */
if ( tok [ 3 ] [ 0 ] ! = 0 ) {
2023-04-26 01:24:25 +03:00
ok = sddl_decode_guid ( tok [ 3 ] , & ace - > object . object . type . type ) ;
if ( ! ok ) {
2007-10-07 02:28:14 +04:00
return false ;
2005-12-02 07:26:51 +03:00
}
2005-12-09 09:22:09 +03:00
ace - > object . object . flags | = SEC_ACE_OBJECT_TYPE_PRESENT ;
2005-12-02 06:16:42 +03:00
}
/* inherit object */
if ( tok [ 4 ] [ 0 ] ! = 0 ) {
2023-04-26 01:24:25 +03:00
ok = sddl_decode_guid ( tok [ 4 ] ,
& ace - > object . object . inherited_type . inherited_type ) ;
if ( ! ok ) {
2007-10-07 02:28:14 +04:00
return false ;
2005-12-02 07:26:51 +03:00
}
2005-12-09 09:22:09 +03:00
ace - > object . object . flags | = SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT ;
2005-12-02 06:16:42 +03:00
}
/* trustee */
s = tok [ 5 ] ;
2022-12-02 02:43:21 +03:00
sid = sddl_transition_decode_sid ( mem_ctx , & s , state ) ;
2005-12-02 06:16:42 +03:00
if ( sid = = NULL ) {
2007-10-07 02:28:14 +04:00
return false ;
2005-12-02 06:16:42 +03:00
}
ace - > trustee = * sid ;
talloc_free ( sid ) ;
2023-04-21 15:47:16 +03:00
if ( * s ! = ' \0 ' ) {
return false ;
}
2023-07-21 07:51:53 +03:00
* sddl_copy = str ;
2007-10-07 02:28:14 +04:00
return true ;
2005-12-02 06:16:42 +03:00
}
static const struct flag_map acl_flags [ ] = {
{ " P " , SEC_DESC_DACL_PROTECTED } ,
{ " AR " , SEC_DESC_DACL_AUTO_INHERIT_REQ } ,
{ " AI " , SEC_DESC_DACL_AUTO_INHERITED } ,
{ NULL , 0 }
} ;
/*
decode an ACL
*/
2023-03-03 20:48:25 +03:00
static struct security_acl * sddl_decode_acl ( struct security_descriptor * sd ,
2005-12-02 07:26:51 +03:00
const char * * sddlp , uint32_t * flags ,
2020-04-30 20:49:12 +03:00
struct sddl_transition_state * state )
2005-12-02 06:16:42 +03:00
{
const char * sddl = * sddlp ;
2023-07-21 07:51:53 +03:00
char * sddl_copy = NULL ;
char * aces_start = NULL ;
2005-12-02 06:16:42 +03:00
struct security_acl * acl ;
size_t len ;
2005-12-09 07:54:30 +03:00
* flags = 0 ;
2005-12-02 06:16:42 +03:00
acl = talloc_zero ( sd , struct security_acl ) ;
2023-07-21 07:51:53 +03:00
if ( acl = = NULL ) {
return NULL ;
}
2010-01-02 04:30:48 +03:00
acl - > revision = SECURITY_ACL_REVISION_ADS ;
2005-12-02 06:16:42 +03:00
2023-07-20 04:26:27 +03:00
if ( isupper ( ( unsigned char ) sddl [ 0 ] ) & & sddl [ 1 ] = = ' : ' ) {
2005-12-02 07:26:51 +03:00
/* its an empty ACL */
return acl ;
}
2005-12-02 06:16:42 +03:00
/* work out the ACL flags */
2023-03-16 11:17:56 +03:00
if ( ! sddl_map_flags ( acl_flags , sddl , flags , & len , true ) ) {
2005-12-02 06:16:42 +03:00
talloc_free ( acl ) ;
return NULL ;
}
sddl + = len ;
2023-07-21 07:51:53 +03:00
if ( sddl [ 0 ] ! = ' ( ' ) {
/* it is empty apart from the flags. */
* sddlp = sddl ;
return acl ;
}
/*
* now the ACEs
*
* For this we make a copy of the rest of the SDDL , which the ACE
* tokeniser will mutilate by putting ' \0 ' where it finds ' ; ' .
*
* We need to copy the rest of the SDDL string because it is not
* possible in general to find where an ACL ends if there are
* conditional ACEs .
*/
sddl_copy = talloc_strdup ( acl , sddl ) ;
if ( sddl_copy = = NULL ) {
TALLOC_FREE ( acl ) ;
return NULL ;
}
aces_start = sddl_copy ;
while ( * sddl_copy = = ' ( ' ) {
bool ok ;
2023-03-03 20:48:25 +03:00
acl - > aces = talloc_realloc ( acl , acl - > aces , struct security_ace ,
2005-12-02 06:16:42 +03:00
acl - > num_aces + 1 ) ;
if ( acl - > aces = = NULL ) {
talloc_free ( acl ) ;
return NULL ;
}
2023-07-21 07:51:53 +03:00
ok = sddl_decode_ace ( acl - > aces , & acl - > aces [ acl - > num_aces ] ,
& sddl_copy , state ) ;
if ( ! ok ) {
2005-12-02 06:16:42 +03:00
talloc_free ( acl ) ;
return NULL ;
}
acl - > num_aces + + ;
}
2023-07-21 07:51:53 +03:00
sddl + = sddl_copy - aces_start ;
TALLOC_FREE ( aces_start ) ;
2005-12-02 06:16:42 +03:00
( * sddlp ) = sddl ;
return acl ;
}
/*
decode a security descriptor in SDDL format
*/
2005-12-02 07:26:51 +03:00
struct security_descriptor * sddl_decode ( TALLOC_CTX * mem_ctx , const char * sddl ,
2005-12-10 02:43:02 +03:00
const struct dom_sid * domain_sid )
2005-12-02 06:16:42 +03:00
{
2020-04-30 20:49:12 +03:00
struct sddl_transition_state state = {
2016-01-14 13:02:10 +03:00
/*
* TODO : verify . machine_rid values really belong to
* to the machine_sid on a member , once
* we pass machine_sid from the caller . . .
*/
. machine_sid = domain_sid ,
2020-04-30 20:49:12 +03:00
. domain_sid = domain_sid ,
2016-01-14 13:02:10 +03:00
. forest_sid = domain_sid ,
2020-04-30 20:49:12 +03:00
} ;
2005-12-02 06:16:42 +03:00
struct security_descriptor * sd ;
sd = talloc_zero ( mem_ctx , struct security_descriptor ) ;
sd - > revision = SECURITY_DESCRIPTOR_REVISION_1 ;
sd - > type = SEC_DESC_SELF_RELATIVE ;
2023-03-03 20:48:25 +03:00
2005-12-02 06:16:42 +03:00
while ( * sddl ) {
uint32_t flags ;
char c = sddl [ 0 ] ;
if ( sddl [ 1 ] ! = ' : ' ) goto failed ;
sddl + = 2 ;
switch ( c ) {
case ' D ' :
if ( sd - > dacl ! = NULL ) goto failed ;
2020-04-30 20:49:12 +03:00
sd - > dacl = sddl_decode_acl ( sd , & sddl , & flags , & state ) ;
2005-12-02 06:16:42 +03:00
if ( sd - > dacl = = NULL ) goto failed ;
sd - > type | = flags | SEC_DESC_DACL_PRESENT ;
break ;
case ' S ' :
if ( sd - > sacl ! = NULL ) goto failed ;
2020-04-30 20:49:12 +03:00
sd - > sacl = sddl_decode_acl ( sd , & sddl , & flags , & state ) ;
2005-12-02 06:16:42 +03:00
if ( sd - > sacl = = NULL ) goto failed ;
/* this relies on the SEC_DESC_SACL_* flags being
1 bit shifted from the SEC_DESC_DACL_ * flags */
sd - > type | = ( flags < < 1 ) | SEC_DESC_SACL_PRESENT ;
break ;
case ' O ' :
if ( sd - > owner_sid ! = NULL ) goto failed ;
2022-12-02 02:43:21 +03:00
sd - > owner_sid = sddl_transition_decode_sid ( sd , & sddl , & state ) ;
2005-12-02 06:16:42 +03:00
if ( sd - > owner_sid = = NULL ) goto failed ;
break ;
case ' G ' :
if ( sd - > group_sid ! = NULL ) goto failed ;
2022-12-02 02:43:21 +03:00
sd - > group_sid = sddl_transition_decode_sid ( sd , & sddl , & state ) ;
2005-12-02 06:16:42 +03:00
if ( sd - > group_sid = = NULL ) goto failed ;
break ;
2023-03-16 05:44:11 +03:00
default :
goto failed ;
2005-12-02 06:16:42 +03:00
}
}
return sd ;
failed :
DEBUG ( 2 , ( " Badly formatted SDDL '%s' \n " , sddl ) ) ;
talloc_free ( sd ) ;
return NULL ;
}
2005-12-09 07:54:30 +03:00
/*
turn a set of flags into a string
*/
static char * sddl_flags_to_string ( TALLOC_CTX * mem_ctx , const struct flag_map * map ,
2007-10-07 02:28:14 +04:00
uint32_t flags , bool check_all )
2005-12-09 07:54:30 +03:00
{
int i ;
char * s ;
/* try to find an exact match */
for ( i = 0 ; map [ i ] . name ; i + + ) {
if ( map [ i ] . flag = = flags ) {
return talloc_strdup ( mem_ctx , map [ i ] . name ) ;
}
}
s = talloc_strdup ( mem_ctx , " " ) ;
/* now by bits */
for ( i = 0 ; map [ i ] . name ; i + + ) {
if ( ( flags & map [ i ] . flag ) ! = 0 ) {
2007-09-15 03:21:00 +04:00
s = talloc_asprintf_append_buffer ( s , " %s " , map [ i ] . name ) ;
2005-12-09 07:54:30 +03:00
if ( s = = NULL ) goto failed ;
flags & = ~ map [ i ] . flag ;
}
}
if ( check_all & & flags ! = 0 ) {
goto failed ;
}
return s ;
failed :
talloc_free ( s ) ;
return NULL ;
}
/*
encode a sid in SDDL format
*/
2023-07-21 07:40:38 +03:00
static char * sddl_transition_encode_sid ( TALLOC_CTX * mem_ctx , const struct dom_sid * sid ,
struct sddl_transition_state * state )
2005-12-09 07:54:30 +03:00
{
2016-01-14 13:02:10 +03:00
bool in_machine = dom_sid_in_domain ( state - > machine_sid , sid ) ;
2022-03-25 16:23:45 +03:00
bool in_domain = dom_sid_in_domain ( state - > domain_sid , sid ) ;
2016-01-14 13:02:10 +03:00
bool in_forest = dom_sid_in_domain ( state - > forest_sid , sid ) ;
2022-03-25 16:23:45 +03:00
struct dom_sid_buf buf ;
const char * sidstr = dom_sid_str_buf ( sid , & buf ) ;
uint32_t rid = 0 ;
2020-09-29 10:55:22 +03:00
size_t i ;
2005-12-09 08:21:47 +03:00
2022-03-25 16:23:45 +03:00
if ( sid - > num_auths > 1 ) {
rid = sid - > sub_auths [ sid - > num_auths - 1 ] ;
}
for ( i = 0 ; i < ARRAY_SIZE ( sid_codes ) ; i + + ) {
/* seen if its a well known sid */
if ( sid_codes [ i ] . sid ! = NULL ) {
int cmp ;
cmp = strcmp ( sidstr , sid_codes [ i ] . sid ) ;
if ( cmp ! = 0 ) {
continue ;
}
2005-12-09 08:21:47 +03:00
return talloc_strdup ( mem_ctx , sid_codes [ i ] . code ) ;
}
2022-03-25 16:23:45 +03:00
if ( rid = = 0 ) {
continue ;
2005-12-09 08:21:47 +03:00
}
2023-03-03 20:48:25 +03:00
2016-01-14 13:02:10 +03:00
if ( in_machine & & sid_codes [ i ] . machine_rid = = rid ) {
return talloc_strdup ( mem_ctx , sid_codes [ i ] . code ) ;
}
if ( in_domain & & sid_codes [ i ] . domain_rid = = rid ) {
return talloc_strdup ( mem_ctx , sid_codes [ i ] . code ) ;
}
if ( in_forest & & sid_codes [ i ] . forest_rid = = rid ) {
2022-03-25 16:23:45 +03:00
return talloc_strdup ( mem_ctx , sid_codes [ i ] . code ) ;
}
}
2005-12-09 08:21:47 +03:00
2022-03-25 16:23:45 +03:00
return talloc_strdup ( mem_ctx , sidstr ) ;
2005-12-09 07:54:30 +03:00
}
2023-07-21 07:40:38 +03:00
char * sddl_encode_sid ( TALLOC_CTX * mem_ctx , const struct dom_sid * sid ,
const struct dom_sid * domain_sid )
{
struct sddl_transition_state state = {
/*
* TODO : verify . machine_rid values really belong to
* to the machine_sid on a member , once
* we pass machine_sid from the caller . . .
*/
. machine_sid = domain_sid ,
. domain_sid = domain_sid ,
. forest_sid = domain_sid ,
} ;
return sddl_transition_encode_sid ( mem_ctx , sid , & state ) ;
}
2005-12-09 07:54:30 +03:00
/*
encode an ACE in SDDL format
*/
2020-04-30 20:49:12 +03:00
static char * sddl_transition_encode_ace ( TALLOC_CTX * mem_ctx , const struct security_ace * ace ,
struct sddl_transition_state * state )
2005-12-09 07:54:30 +03:00
{
2005-12-10 12:18:03 +03:00
char * sddl = NULL ;
2005-12-09 07:54:30 +03:00
TALLOC_CTX * tmp_ctx ;
2021-04-14 18:44:54 +03:00
struct GUID_txt_buf object_buf , iobject_buf ;
2010-03-28 18:22:26 +04:00
const char * sddl_type = " " , * sddl_flags = " " , * sddl_mask = " " ,
* sddl_object = " " , * sddl_iobject = " " , * sddl_trustee = " " ;
2005-12-09 07:54:30 +03:00
tmp_ctx = talloc_new ( mem_ctx ) ;
2005-12-10 12:18:03 +03:00
if ( tmp_ctx = = NULL ) {
DEBUG ( 0 , ( " talloc_new failed \n " ) ) ;
return NULL ;
}
2005-12-09 07:54:30 +03:00
2010-03-28 18:22:26 +04:00
sddl_type = sddl_flags_to_string ( tmp_ctx , ace_types , ace - > type , true ) ;
if ( sddl_type = = NULL ) {
goto failed ;
}
2005-12-09 07:54:30 +03:00
2010-03-28 18:22:26 +04:00
sddl_flags = sddl_flags_to_string ( tmp_ctx , ace_flags , ace - > flags ,
true ) ;
if ( sddl_flags = = NULL ) {
goto failed ;
}
2005-12-09 07:54:30 +03:00
2010-03-28 18:22:26 +04:00
sddl_mask = sddl_flags_to_string ( tmp_ctx , ace_access_mask ,
ace - > access_mask , true ) ;
if ( sddl_mask = = NULL ) {
s3/utils: when encoding ace string use "FA", "FR", "FW", "FX" string rights
prior to this patch rights matching "FA", "FR", "FW", "FX" were
outputted as the hex string representing the bit value.
While outputting the hex string is perfectly fine, it makes it harder
to compare icacls output (which always uses the special string values)
Additionally adjust various tests to deal with use of shortcut access masks
as sddl format now uses FA, FR, FW & FX strings (like icalcs does) instead
of hex representation of the bit mask.
adjust
samba4.blackbox.samba-tool_ntacl
samba3.blackbox.large_acl
samba.tests.samba_tool.ntacl
samba.tests.ntacls
samba.tests.posixacl
so various string comparisons of the sddl format now pass
Signed-off-by: Noel Power <noel.power@suse.com>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
[abartlet@samba.org Adapted to new stricter SDDL behaviour around leading zeros in hex
numbers, eg 0x001]
2022-08-25 16:29:09 +03:00
sddl_mask = sddl_match_file_rights ( tmp_ctx ,
ace - > access_mask ) ;
if ( sddl_mask = = NULL ) {
sddl_mask = talloc_asprintf ( tmp_ctx , " 0x%x " ,
ace - > access_mask ) ;
}
2010-03-28 18:22:26 +04:00
if ( sddl_mask = = NULL ) {
goto failed ;
}
2005-12-09 09:22:09 +03:00
}
2005-12-09 07:54:30 +03:00
2023-07-21 07:58:45 +03:00
if ( sec_ace_object ( ace - > type ) ) {
2021-04-14 18:44:54 +03:00
const struct security_ace_object * object = & ace - > object . object ;
2005-12-09 09:22:09 +03:00
if ( ace - > object . object . flags & SEC_ACE_OBJECT_TYPE_PRESENT ) {
2021-04-14 18:44:54 +03:00
sddl_object = GUID_buf_string (
& object - > type . type , & object_buf ) ;
2005-12-09 08:21:47 +03:00
}
2005-12-09 07:54:30 +03:00
2021-04-14 18:44:54 +03:00
if ( ace - > object . object . flags &
SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT ) {
sddl_iobject = GUID_buf_string (
& object - > inherited_type . inherited_type ,
& iobject_buf ) ;
2005-12-09 08:21:47 +03:00
}
}
2010-03-28 18:22:26 +04:00
2023-07-21 07:40:38 +03:00
sddl_trustee = sddl_transition_encode_sid ( tmp_ctx , & ace - > trustee , state ) ;
2010-03-28 18:22:26 +04:00
if ( sddl_trustee = = NULL ) {
goto failed ;
}
2005-12-09 07:54:30 +03:00
sddl = talloc_asprintf ( mem_ctx , " %s;%s;%s;%s;%s;%s " ,
2010-03-28 18:22:26 +04:00
sddl_type , sddl_flags , sddl_mask , sddl_object ,
sddl_iobject , sddl_trustee ) ;
2005-12-09 07:54:30 +03:00
failed :
talloc_free ( tmp_ctx ) ;
return sddl ;
}
2020-04-30 20:49:12 +03:00
char * sddl_encode_ace ( TALLOC_CTX * mem_ctx , const struct security_ace * ace ,
const struct dom_sid * domain_sid )
{
struct sddl_transition_state state = {
2016-01-14 13:02:10 +03:00
/*
* TODO : verify . machine_rid values really belong to
* to the machine_sid on a member , once
* we pass machine_sid from the caller . . .
*/
. machine_sid = domain_sid ,
2020-04-30 20:49:12 +03:00
. domain_sid = domain_sid ,
2016-01-14 13:02:10 +03:00
. forest_sid = domain_sid ,
2020-04-30 20:49:12 +03:00
} ;
return sddl_transition_encode_ace ( mem_ctx , ace , & state ) ;
}
2005-12-09 07:54:30 +03:00
/*
encode an ACL in SDDL format
*/
static char * sddl_encode_acl ( TALLOC_CTX * mem_ctx , const struct security_acl * acl ,
2020-04-30 20:49:12 +03:00
uint32_t flags , struct sddl_transition_state * state )
2005-12-09 07:54:30 +03:00
{
char * sddl ;
2011-02-16 11:12:17 +03:00
uint32_t i ;
2005-12-09 07:54:30 +03:00
/* add any ACL flags */
2007-10-07 02:28:14 +04:00
sddl = sddl_flags_to_string ( mem_ctx , acl_flags , flags , false ) ;
2005-12-09 07:54:30 +03:00
if ( sddl = = NULL ) goto failed ;
/* now the ACEs, encoded in braces */
for ( i = 0 ; i < acl - > num_aces ; i + + ) {
2020-04-30 20:49:12 +03:00
char * ace = sddl_transition_encode_ace ( sddl , & acl - > aces [ i ] , state ) ;
2005-12-09 07:54:30 +03:00
if ( ace = = NULL ) goto failed ;
2007-09-15 03:21:00 +04:00
sddl = talloc_asprintf_append_buffer ( sddl , " (%s) " , ace ) ;
2005-12-09 07:54:30 +03:00
if ( sddl = = NULL ) goto failed ;
talloc_free ( ace ) ;
}
return sddl ;
failed :
talloc_free ( sddl ) ;
return NULL ;
}
/*
encode a security descriptor to SDDL format
*/
char * sddl_encode ( TALLOC_CTX * mem_ctx , const struct security_descriptor * sd ,
2005-12-10 02:43:02 +03:00
const struct dom_sid * domain_sid )
2005-12-09 07:54:30 +03:00
{
2020-04-30 20:49:12 +03:00
struct sddl_transition_state state = {
2016-01-14 13:02:10 +03:00
/*
* TODO : verify . machine_rid values really belong to
* to the machine_sid on a member , once
* we pass machine_sid from the caller . . .
*/
. machine_sid = domain_sid ,
2020-04-30 20:49:12 +03:00
. domain_sid = domain_sid ,
2016-01-14 13:02:10 +03:00
. forest_sid = domain_sid ,
2020-04-30 20:49:12 +03:00
} ;
2005-12-09 07:54:30 +03:00
char * sddl ;
TALLOC_CTX * tmp_ctx ;
/* start with a blank string */
sddl = talloc_strdup ( mem_ctx , " " ) ;
if ( sddl = = NULL ) goto failed ;
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( sd - > owner_sid ! = NULL ) {
2023-07-21 07:40:38 +03:00
char * sid = sddl_transition_encode_sid ( tmp_ctx , sd - > owner_sid , & state ) ;
2005-12-09 07:54:30 +03:00
if ( sid = = NULL ) goto failed ;
2007-09-15 03:21:00 +04:00
sddl = talloc_asprintf_append_buffer ( sddl , " O:%s " , sid ) ;
2005-12-09 07:54:30 +03:00
if ( sddl = = NULL ) goto failed ;
}
if ( sd - > group_sid ! = NULL ) {
2023-07-21 07:40:38 +03:00
char * sid = sddl_transition_encode_sid ( tmp_ctx , sd - > group_sid , & state ) ;
2005-12-09 07:54:30 +03:00
if ( sid = = NULL ) goto failed ;
2007-09-15 03:21:00 +04:00
sddl = talloc_asprintf_append_buffer ( sddl , " G:%s " , sid ) ;
2005-12-09 07:54:30 +03:00
if ( sddl = = NULL ) goto failed ;
}
if ( ( sd - > type & SEC_DESC_DACL_PRESENT ) & & sd - > dacl ! = NULL ) {
2020-04-30 20:49:12 +03:00
char * acl = sddl_encode_acl ( tmp_ctx , sd - > dacl , sd - > type , & state ) ;
2005-12-09 07:54:30 +03:00
if ( acl = = NULL ) goto failed ;
2007-09-15 03:21:00 +04:00
sddl = talloc_asprintf_append_buffer ( sddl , " D:%s " , acl ) ;
2005-12-09 07:54:30 +03:00
if ( sddl = = NULL ) goto failed ;
}
if ( ( sd - > type & SEC_DESC_SACL_PRESENT ) & & sd - > sacl ! = NULL ) {
2020-04-30 20:49:12 +03:00
char * acl = sddl_encode_acl ( tmp_ctx , sd - > sacl , sd - > type > > 1 , & state ) ;
2005-12-09 07:54:30 +03:00
if ( acl = = NULL ) goto failed ;
2007-09-15 03:21:00 +04:00
sddl = talloc_asprintf_append_buffer ( sddl , " S:%s " , acl ) ;
2005-12-09 07:54:30 +03:00
if ( sddl = = NULL ) goto failed ;
}
talloc_free ( tmp_ctx ) ;
return sddl ;
failed :
talloc_free ( sddl ) ;
return NULL ;
}