mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 17:05:46 +00:00
Implement ConvertSecurityDescriptorToStringSecurityDescriptorW based on Wine code.
svn path=/trunk/; revision=37281
This commit is contained in:
parent
db0c66dcb0
commit
886c6bd7d5
1 changed files with 393 additions and 4 deletions
|
@ -51,6 +51,12 @@ typedef struct WELLKNOWNSID
|
|||
MAX_SID Sid;
|
||||
} WELLKNOWNSID;
|
||||
|
||||
typedef struct _ACEFLAG
|
||||
{
|
||||
LPCWSTR wstr;
|
||||
DWORD value;
|
||||
} ACEFLAG, *LPACEFLAG;
|
||||
|
||||
static const WELLKNOWNSID WellKnownSids[] =
|
||||
{
|
||||
{ {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } },
|
||||
|
@ -181,6 +187,76 @@ static const char * debugstr_sid(PSID sid)
|
|||
return "(too-big)";
|
||||
}
|
||||
|
||||
static const ACEFLAG AceRights[] =
|
||||
{
|
||||
{ SDDL_GENERIC_ALL, GENERIC_ALL },
|
||||
{ SDDL_GENERIC_READ, GENERIC_READ },
|
||||
{ SDDL_GENERIC_WRITE, GENERIC_WRITE },
|
||||
{ SDDL_GENERIC_EXECUTE, GENERIC_EXECUTE },
|
||||
|
||||
{ SDDL_READ_CONTROL, READ_CONTROL },
|
||||
{ SDDL_STANDARD_DELETE, DELETE },
|
||||
{ SDDL_WRITE_DAC, WRITE_DAC },
|
||||
{ SDDL_WRITE_OWNER, WRITE_OWNER },
|
||||
|
||||
{ SDDL_READ_PROPERTY, ADS_RIGHT_DS_READ_PROP},
|
||||
{ SDDL_WRITE_PROPERTY, ADS_RIGHT_DS_WRITE_PROP},
|
||||
{ SDDL_CREATE_CHILD, ADS_RIGHT_DS_CREATE_CHILD},
|
||||
{ SDDL_DELETE_CHILD, ADS_RIGHT_DS_DELETE_CHILD},
|
||||
{ SDDL_LIST_CHILDREN, ADS_RIGHT_ACTRL_DS_LIST},
|
||||
{ SDDL_SELF_WRITE, ADS_RIGHT_DS_SELF},
|
||||
{ SDDL_LIST_OBJECT, ADS_RIGHT_DS_LIST_OBJECT},
|
||||
{ SDDL_DELETE_TREE, ADS_RIGHT_DS_DELETE_TREE},
|
||||
{ SDDL_CONTROL_ACCESS, ADS_RIGHT_DS_CONTROL_ACCESS},
|
||||
|
||||
{ SDDL_FILE_ALL, FILE_ALL_ACCESS },
|
||||
{ SDDL_FILE_READ, FILE_GENERIC_READ },
|
||||
{ SDDL_FILE_WRITE, FILE_GENERIC_WRITE },
|
||||
{ SDDL_FILE_EXECUTE, FILE_GENERIC_EXECUTE },
|
||||
|
||||
{ SDDL_KEY_ALL, KEY_ALL_ACCESS },
|
||||
{ SDDL_KEY_READ, KEY_READ },
|
||||
{ SDDL_KEY_WRITE, KEY_WRITE },
|
||||
{ SDDL_KEY_EXECUTE, KEY_EXECUTE },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
static const LPCWSTR AceRightBitNames[32] = {
|
||||
SDDL_CREATE_CHILD, /* 0 */
|
||||
SDDL_DELETE_CHILD,
|
||||
SDDL_LIST_CHILDREN,
|
||||
SDDL_SELF_WRITE,
|
||||
SDDL_READ_PROPERTY, /* 4 */
|
||||
SDDL_WRITE_PROPERTY,
|
||||
SDDL_DELETE_TREE,
|
||||
SDDL_LIST_OBJECT,
|
||||
SDDL_CONTROL_ACCESS, /* 8 */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, /* 12 */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
SDDL_STANDARD_DELETE, /* 16 */
|
||||
SDDL_READ_CONTROL,
|
||||
SDDL_WRITE_DAC,
|
||||
SDDL_WRITE_OWNER,
|
||||
NULL, /* 20 */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL, /* 24 */
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
SDDL_GENERIC_ALL, /* 28 */
|
||||
SDDL_GENERIC_EXECUTE,
|
||||
SDDL_GENERIC_WRITE,
|
||||
SDDL_GENERIC_READ
|
||||
};
|
||||
|
||||
|
||||
/* set last error code from NT status and get the proper boolean return value */
|
||||
/* used for functions that are a simple wrapper around the corresponding ntdll API */
|
||||
static __inline BOOL set_ntstatus( NTSTATUS status )
|
||||
|
@ -610,10 +686,289 @@ CopySid(DWORD nDestinationSidLength,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void DumpString(LPCWSTR string, int cch, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
if (cch == -1)
|
||||
cch = strlenW(string);
|
||||
|
||||
if (plen)
|
||||
*plen += cch;
|
||||
|
||||
if (pwptr)
|
||||
{
|
||||
memcpy(*pwptr, string, sizeof(WCHAR)*cch);
|
||||
*pwptr += cch;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL DumpSidNumeric(PSID psid, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
DWORD i;
|
||||
WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 };
|
||||
WCHAR subauthfmt[] = { '-','%','u',0 };
|
||||
WCHAR buf[26];
|
||||
SID *pisid = psid;
|
||||
|
||||
if( !IsValidSid( psid ) || pisid->Revision != SDDL_REVISION)
|
||||
{
|
||||
SetLastError(ERROR_INVALID_SID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (pisid->IdentifierAuthority.Value[0] ||
|
||||
pisid->IdentifierAuthority.Value[1])
|
||||
{
|
||||
FIXME("not matching MS' bugs\n");
|
||||
SetLastError(ERROR_INVALID_SID);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
sprintfW( buf, fmt, pisid->Revision,
|
||||
MAKELONG(
|
||||
MAKEWORD( pisid->IdentifierAuthority.Value[5],
|
||||
pisid->IdentifierAuthority.Value[4] ),
|
||||
MAKEWORD( pisid->IdentifierAuthority.Value[3],
|
||||
pisid->IdentifierAuthority.Value[2] )
|
||||
) );
|
||||
DumpString(buf, -1, pwptr, plen);
|
||||
|
||||
for( i=0; i<pisid->SubAuthorityCount; i++ )
|
||||
{
|
||||
sprintfW( buf, subauthfmt, pisid->SubAuthority[i] );
|
||||
DumpString(buf, -1, pwptr, plen);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DumpSid(PSID psid, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
|
||||
{
|
||||
if (WellKnownSids[i].wstr[0] && EqualSid(psid, (PSID)&(WellKnownSids[i].Sid.Revision)))
|
||||
{
|
||||
DumpString(WellKnownSids[i].wstr, 2, pwptr, plen);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return DumpSidNumeric(psid, pwptr, plen);
|
||||
}
|
||||
|
||||
static void DumpRights(DWORD mask, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
static const WCHAR fmtW[] = {'0','x','%','x',0};
|
||||
WCHAR buf[15];
|
||||
size_t i;
|
||||
|
||||
if (mask == 0)
|
||||
return;
|
||||
|
||||
/* first check if the right have name */
|
||||
for (i = 0; i < sizeof(AceRights)/sizeof(AceRights[0]); i++)
|
||||
{
|
||||
if (AceRights[i].wstr == NULL)
|
||||
break;
|
||||
if (mask == AceRights[i].value)
|
||||
{
|
||||
DumpString(AceRights[i].wstr, -1, pwptr, plen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* then check if it can be built from bit names */
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
if ((mask & (1 << i)) && (AceRightBitNames[i] == NULL))
|
||||
{
|
||||
/* can't be built from bit names */
|
||||
sprintfW(buf, fmtW, mask);
|
||||
DumpString(buf, -1, pwptr, plen);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* build from bit names */
|
||||
for (i = 0; i < 32; i++)
|
||||
if (mask & (1 << i))
|
||||
DumpString(AceRightBitNames[i], -1, pwptr, plen);
|
||||
}
|
||||
|
||||
static BOOL DumpAce(LPVOID pace, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */
|
||||
static const WCHAR openbr = '(';
|
||||
static const WCHAR closebr = ')';
|
||||
static const WCHAR semicolon = ';';
|
||||
|
||||
if (((PACE_HEADER)pace)->AceType > SYSTEM_ALARM_ACE_TYPE || ((PACE_HEADER)pace)->AceSize < sizeof(ACCESS_ALLOWED_ACE))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_ACL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
piace = (ACCESS_ALLOWED_ACE *)pace;
|
||||
DumpString(&openbr, 1, pwptr, plen);
|
||||
switch (piace->Header.AceType)
|
||||
{
|
||||
case ACCESS_ALLOWED_ACE_TYPE:
|
||||
DumpString(SDDL_ACCESS_ALLOWED, -1, pwptr, plen);
|
||||
break;
|
||||
case ACCESS_DENIED_ACE_TYPE:
|
||||
DumpString(SDDL_ACCESS_DENIED, -1, pwptr, plen);
|
||||
break;
|
||||
case SYSTEM_AUDIT_ACE_TYPE:
|
||||
DumpString(SDDL_AUDIT, -1, pwptr, plen);
|
||||
break;
|
||||
case SYSTEM_ALARM_ACE_TYPE:
|
||||
DumpString(SDDL_ALARM, -1, pwptr, plen);
|
||||
break;
|
||||
}
|
||||
DumpString(&semicolon, 1, pwptr, plen);
|
||||
|
||||
if (piace->Header.AceFlags & OBJECT_INHERIT_ACE)
|
||||
DumpString(SDDL_OBJECT_INHERIT, -1, pwptr, plen);
|
||||
if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE)
|
||||
DumpString(SDDL_CONTAINER_INHERIT, -1, pwptr, plen);
|
||||
if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE)
|
||||
DumpString(SDDL_NO_PROPAGATE, -1, pwptr, plen);
|
||||
if (piace->Header.AceFlags & INHERIT_ONLY_ACE)
|
||||
DumpString(SDDL_INHERIT_ONLY, -1, pwptr, plen);
|
||||
if (piace->Header.AceFlags & INHERITED_ACE)
|
||||
DumpString(SDDL_INHERITED, -1, pwptr, plen);
|
||||
if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
|
||||
DumpString(SDDL_AUDIT_SUCCESS, -1, pwptr, plen);
|
||||
if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG)
|
||||
DumpString(SDDL_AUDIT_FAILURE, -1, pwptr, plen);
|
||||
DumpString(&semicolon, 1, pwptr, plen);
|
||||
DumpRights(piace->Mask, pwptr, plen);
|
||||
DumpString(&semicolon, 1, pwptr, plen);
|
||||
/* objects not supported */
|
||||
DumpString(&semicolon, 1, pwptr, plen);
|
||||
/* objects not supported */
|
||||
DumpString(&semicolon, 1, pwptr, plen);
|
||||
if (!DumpSid((PSID)&piace->SidStart, pwptr, plen))
|
||||
return FALSE;
|
||||
DumpString(&closebr, 1, pwptr, plen);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DumpAcl(PACL pacl, WCHAR **pwptr, ULONG *plen, BOOL protected, BOOL autoInheritReq, BOOL autoInherited)
|
||||
{
|
||||
WORD count;
|
||||
int i;
|
||||
|
||||
if (protected)
|
||||
DumpString(SDDL_PROTECTED, -1, pwptr, plen);
|
||||
if (autoInheritReq)
|
||||
DumpString(SDDL_AUTO_INHERIT_REQ, -1, pwptr, plen);
|
||||
if (autoInherited)
|
||||
DumpString(SDDL_AUTO_INHERITED, -1, pwptr, plen);
|
||||
|
||||
if (pacl == NULL)
|
||||
return TRUE;
|
||||
|
||||
if (!IsValidAcl(pacl))
|
||||
return FALSE;
|
||||
|
||||
count = pacl->AceCount;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
LPVOID ace;
|
||||
if (!GetAce(pacl, i, &ace))
|
||||
return FALSE;
|
||||
if (!DumpAce(ace, pwptr, plen))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DumpOwner(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
static const WCHAR prefix[] = {'O',':',0};
|
||||
BOOL bDefaulted;
|
||||
PSID psid;
|
||||
|
||||
if (!GetSecurityDescriptorOwner(SecurityDescriptor, &psid, &bDefaulted))
|
||||
return FALSE;
|
||||
|
||||
if (psid == NULL)
|
||||
return TRUE;
|
||||
|
||||
DumpString(prefix, -1, pwptr, plen);
|
||||
if (!DumpSid(psid, pwptr, plen))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DumpGroup(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
static const WCHAR prefix[] = {'G',':',0};
|
||||
BOOL bDefaulted;
|
||||
PSID psid;
|
||||
|
||||
if (!GetSecurityDescriptorGroup(SecurityDescriptor, &psid, &bDefaulted))
|
||||
return FALSE;
|
||||
|
||||
if (psid == NULL)
|
||||
return TRUE;
|
||||
|
||||
DumpString(prefix, -1, pwptr, plen);
|
||||
if (!DumpSid(psid, pwptr, plen))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DumpDacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
static const WCHAR dacl[] = {'D',':',0};
|
||||
SECURITY_DESCRIPTOR_CONTROL control;
|
||||
BOOL present, defaulted;
|
||||
DWORD revision;
|
||||
PACL pacl;
|
||||
|
||||
if (!GetSecurityDescriptorDacl(SecurityDescriptor, &present, &pacl, &defaulted))
|
||||
return FALSE;
|
||||
|
||||
if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
|
||||
return FALSE;
|
||||
|
||||
if (!present)
|
||||
return TRUE;
|
||||
|
||||
DumpString(dacl, 2, pwptr, plen);
|
||||
if (!DumpAcl(pacl, pwptr, plen, control & SE_DACL_PROTECTED, control & SE_DACL_AUTO_INHERIT_REQ, control & SE_DACL_AUTO_INHERITED))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL DumpSacl(PSECURITY_DESCRIPTOR SecurityDescriptor, WCHAR **pwptr, ULONG *plen)
|
||||
{
|
||||
static const WCHAR sacl[] = {'S',':',0};
|
||||
SECURITY_DESCRIPTOR_CONTROL control;
|
||||
BOOL present, defaulted;
|
||||
DWORD revision;
|
||||
PACL pacl;
|
||||
|
||||
if (!GetSecurityDescriptorSacl(SecurityDescriptor, &present, &pacl, &defaulted))
|
||||
return FALSE;
|
||||
|
||||
if (!GetSecurityDescriptorControl(SecurityDescriptor, &control, &revision))
|
||||
return FALSE;
|
||||
|
||||
if (!present)
|
||||
return TRUE;
|
||||
|
||||
DumpString(sacl, 2, pwptr, plen);
|
||||
if (!DumpAcl(pacl, pwptr, plen, control & SE_SACL_PROTECTED, control & SE_SACL_AUTO_INHERIT_REQ, control & SE_SACL_AUTO_INHERITED))
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* ConvertSecurityDescriptorToStringSecurityDescriptorW [ADVAPI32.@]
|
||||
* @unimplemented
|
||||
* @implemented
|
||||
*/
|
||||
BOOL WINAPI
|
||||
ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
|
||||
|
@ -622,6 +977,9 @@ ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR Securi
|
|||
LPWSTR *OutputString,
|
||||
PULONG OutputLen)
|
||||
{
|
||||
ULONG len;
|
||||
WCHAR *wptr, *wstr;
|
||||
|
||||
if (SDRevision != SDDL_REVISION_1)
|
||||
{
|
||||
ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
|
||||
|
@ -629,9 +987,40 @@ ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR Securi
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
FIXME("%s() not implemented!\n", __FUNCTION__);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
len = 0;
|
||||
if (SecurityInformation & OWNER_SECURITY_INFORMATION)
|
||||
if (!DumpOwner(SecurityDescriptor, NULL, &len))
|
||||
return FALSE;
|
||||
if (SecurityInformation & GROUP_SECURITY_INFORMATION)
|
||||
if (!DumpGroup(SecurityDescriptor, NULL, &len))
|
||||
return FALSE;
|
||||
if (SecurityInformation & DACL_SECURITY_INFORMATION)
|
||||
if (!DumpDacl(SecurityDescriptor, NULL, &len))
|
||||
return FALSE;
|
||||
if (SecurityInformation & SACL_SECURITY_INFORMATION)
|
||||
if (!DumpSacl(SecurityDescriptor, NULL, &len))
|
||||
return FALSE;
|
||||
|
||||
wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR));
|
||||
if (SecurityInformation & OWNER_SECURITY_INFORMATION)
|
||||
if (!DumpOwner(SecurityDescriptor, &wptr, NULL))
|
||||
return FALSE;
|
||||
if (SecurityInformation & GROUP_SECURITY_INFORMATION)
|
||||
if (!DumpGroup(SecurityDescriptor, &wptr, NULL))
|
||||
return FALSE;
|
||||
if (SecurityInformation & DACL_SECURITY_INFORMATION)
|
||||
if (!DumpDacl(SecurityDescriptor, &wptr, NULL))
|
||||
return FALSE;
|
||||
if (SecurityInformation & SACL_SECURITY_INFORMATION)
|
||||
if (!DumpSacl(SecurityDescriptor, &wptr, NULL))
|
||||
return FALSE;
|
||||
*wptr = 0;
|
||||
|
||||
TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len);
|
||||
*OutputString = wstr;
|
||||
if (OutputLen)
|
||||
*OutputLen = strlenW(*OutputString)+1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue