Author: gschneider Date: Mon Nov 10 08:25:24 2008 New Revision: 37281
URL: http://svn.reactos.org/svn/reactos?rev=37281&view=rev Log: Implement ConvertSecurityDescriptorToStringSecurityDescriptorW based on Wine code.
Modified: trunk/reactos/dll/win32/advapi32/sec/sid.c
Modified: trunk/reactos/dll/win32/advapi32/sec/sid.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/advapi32/sec/sid.... ============================================================================== --- trunk/reactos/dll/win32/advapi32/sec/sid.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/advapi32/sec/sid.c [iso-8859-1] Mon Nov 10 08:25:24 2008 @@ -50,6 +50,12 @@ WELL_KNOWN_SID_TYPE Type; MAX_SID Sid; } WELLKNOWNSID; + +typedef struct _ACEFLAG +{ + LPCWSTR wstr; + DWORD value; +} ACEFLAG, *LPACEFLAG;
static const WELLKNOWNSID WellKnownSids[] = { @@ -180,6 +186,76 @@ } 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 */ @@ -610,10 +686,289 @@ 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 @@ 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 @@ 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; }
On Mon, Nov 10, 2008 at 9:25 AM, gschneider@svn.reactos.org wrote:
Author: gschneider Date: Mon Nov 10 08:25:24 2008 New Revision: 37281
URL: http://svn.reactos.org/svn/reactos?rev=37281&view=rev Log: Implement ConvertSecurityDescriptorToStringSecurityDescriptorW based on Wine code.
Please add the appropriate copyright headers to the source file stating the original author when implementing code based on third party sources.