From a67af66aead0cd19e80186ab635c2b698c58aff2 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Fri, 1 May 2020 16:51:40 -0500 Subject: [PATCH] advapi32: Move string SID/SD conversion functions to sechost. Signed-off-by: Zebediah Figura Signed-off-by: Alexandre Julliard --- dlls/advapi32/advapi32.spec | 8 +- dlls/advapi32/security.c | 1314 ----------------------------------- dlls/sechost/Makefile.in | 1 + dlls/sechost/sechost.spec | 8 +- dlls/sechost/security.c | 1247 +++++++++++++++++++++++++++++++++ 5 files changed, 1256 insertions(+), 1322 deletions(-) create mode 100644 dlls/sechost/security.c diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index cd4dedac74d..ac8ea6268a8 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -120,17 +120,17 @@ # @ stub ConvertSecurityDescriptorToAccessNamedW # @ stub ConvertSecurityDescriptorToAccessW @ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorA(ptr long long ptr ptr) -@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr) +@ stdcall -import ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr) @ stdcall ConvertSidToStringSidA(ptr ptr) -@ stdcall ConvertSidToStringSidW(ptr ptr) +@ stdcall -import ConvertSidToStringSidW(ptr ptr) # @ stub ConvertStringSDToSDDomainA # @ stub ConvertStringSDToSDDomainW # @ stub ConvertStringSDToSDRootDomainA # @ stub ConvertStringSDToSDRootDomainW @ stdcall ConvertStringSecurityDescriptorToSecurityDescriptorA(str long ptr ptr) -@ stdcall ConvertStringSecurityDescriptorToSecurityDescriptorW(wstr long ptr ptr) +@ stdcall -import ConvertStringSecurityDescriptorToSecurityDescriptorW(wstr long ptr ptr) @ stdcall ConvertStringSidToSidA(ptr ptr) -@ stdcall ConvertStringSidToSidW(ptr ptr) +@ stdcall -import ConvertStringSidToSidW(ptr ptr) @ stdcall -import ConvertToAutoInheritPrivateObjectSecurity(ptr ptr ptr ptr long ptr) @ stdcall -import CopySid(long ptr ptr) # @ stub CreateCodeAuthzLevel diff --git a/dlls/advapi32/security.c b/dlls/advapi32/security.c index d3c9a6c1e29..fe2f0d92663 100644 --- a/dlls/advapi32/security.c +++ b/dlls/advapi32/security.c @@ -47,15 +47,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(advapi); -static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes); static DWORD trustee_to_sid(DWORD nDestinationSidLength, PSID pDestinationSid, PTRUSTEEW pTrustee); -typedef struct _ACEFLAG -{ - LPCWSTR wstr; - DWORD value; -} ACEFLAG, *LPACEFLAG; - typedef struct _MAX_SID { /* same fields as struct _SID */ @@ -65,97 +58,6 @@ typedef struct _MAX_SID DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES]; } MAX_SID; -typedef struct WELLKNOWNSID -{ - WCHAR wstr[2]; - WELL_KNOWN_SID_TYPE Type; - MAX_SID Sid; -} WELLKNOWNSID; - -static const WELLKNOWNSID WellKnownSids[] = -{ - { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } }, - { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } }, - { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } }, - { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } }, - { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } }, - { {'O','W'}, WinCreatorOwnerRightsSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RIGHTS_RID } } }, - { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } }, - { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } }, - { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } }, - { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } }, - { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } }, - { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } }, - { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } }, - { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } }, - { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } }, - { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } }, - { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } }, - { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } }, - { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } }, - { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } }, - { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } }, - { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } }, - { {0,0}, WinLogonIdsSid, { SID_REVISION, SECURITY_LOGON_IDS_RID_COUNT, { SECURITY_NT_AUTHORITY }, { SECURITY_LOGON_IDS_RID } } }, - { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } }, - { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } }, - { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } }, - { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } }, - { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } }, - { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } }, - { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } }, - { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } }, - { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } }, - { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } }, - { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } }, - { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } }, - { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } }, - { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } }, - { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } }, - { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } }, - { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } }, - { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } }, - { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } }, - { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } }, - { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } }, - { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } }, - { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } }, - { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } }, - { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } }, - { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } }, - { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } }, - { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } }, - { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } }, - { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } }, - { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } }, - { {'A','C'}, WinBuiltinAnyPackageSid, { SID_REVISION, 2, { SECURITY_APP_PACKAGE_AUTHORITY }, { SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } } }, -}; - -/* these SIDs must be constructed as relative to some domain - only the RID is well-known */ -typedef struct WELLKNOWNRID -{ - WCHAR wstr[2]; - WELL_KNOWN_SID_TYPE Type; - DWORD Rid; -} WELLKNOWNRID; - -static const WELLKNOWNRID WellKnownRids[] = { - { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN }, - { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST }, - { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT }, - { {'D','A'}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS }, - { {'D','U'}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS }, - { {'D','G'}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS }, - { {'D','C'}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS }, - { {'D','D'}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS }, - { {'C','A'}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS }, - { {'S','A'}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS }, - { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS }, - { {'P','A'}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS }, - { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS }, -}; - - typedef struct _AccountSid { WELL_KNOWN_SID_TYPE type; LPCWSTR account; @@ -275,69 +177,6 @@ static const AccountSid ACCOUNT_SIDS[] = { { WinBuiltinPerfLoggingUsersSid, Performance_Log_Users, BUILTIN, SidTypeAlias }, { WinBuiltinAnyPackageSid, ALL_APPLICATION_PACKAGES, APPLICATION_PACKAGE_AUTHORITY, SidTypeWellKnownGroup }, }; -/* - * ACE access rights - */ -static const WCHAR SDDL_READ_CONTROL[] = {'R','C',0}; -static const WCHAR SDDL_WRITE_DAC[] = {'W','D',0}; -static const WCHAR SDDL_WRITE_OWNER[] = {'W','O',0}; -static const WCHAR SDDL_STANDARD_DELETE[] = {'S','D',0}; - -static const WCHAR SDDL_READ_PROPERTY[] = {'R','P',0}; -static const WCHAR SDDL_WRITE_PROPERTY[] = {'W','P',0}; -static const WCHAR SDDL_CREATE_CHILD[] = {'C','C',0}; -static const WCHAR SDDL_DELETE_CHILD[] = {'D','C',0}; -static const WCHAR SDDL_LIST_CHILDREN[] = {'L','C',0}; -static const WCHAR SDDL_SELF_WRITE[] = {'S','W',0}; -static const WCHAR SDDL_LIST_OBJECT[] = {'L','O',0}; -static const WCHAR SDDL_DELETE_TREE[] = {'D','T',0}; -static const WCHAR SDDL_CONTROL_ACCESS[] = {'C','R',0}; - -static const WCHAR SDDL_FILE_ALL[] = {'F','A',0}; -static const WCHAR SDDL_FILE_READ[] = {'F','R',0}; -static const WCHAR SDDL_FILE_WRITE[] = {'F','W',0}; -static const WCHAR SDDL_FILE_EXECUTE[] = {'F','X',0}; - -static const WCHAR SDDL_KEY_ALL[] = {'K','A',0}; -static const WCHAR SDDL_KEY_READ[] = {'K','R',0}; -static const WCHAR SDDL_KEY_WRITE[] = {'K','W',0}; -static const WCHAR SDDL_KEY_EXECUTE[] = {'K','X',0}; - -static const WCHAR SDDL_GENERIC_ALL[] = {'G','A',0}; -static const WCHAR SDDL_GENERIC_READ[] = {'G','R',0}; -static const WCHAR SDDL_GENERIC_WRITE[] = {'G','W',0}; -static const WCHAR SDDL_GENERIC_EXECUTE[] = {'G','X',0}; - -static const WCHAR SDDL_NO_READ_UP[] = {'N','R',0}; -static const WCHAR SDDL_NO_WRITE_UP[] = {'N','W',0}; -static const WCHAR SDDL_NO_EXECUTE_UP[] = {'N','X',0}; - -/* - * ACL flags - */ -static const WCHAR SDDL_PROTECTED[] = {'P',0}; -static const WCHAR SDDL_AUTO_INHERIT_REQ[] = {'A','R',0}; -static const WCHAR SDDL_AUTO_INHERITED[] = {'A','I',0}; - -/* - * ACE types - */ -static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0}; -static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0}; -static const WCHAR SDDL_AUDIT[] = {'A','U',0}; -static const WCHAR SDDL_ALARM[] = {'A','L',0}; -static const WCHAR SDDL_MANDATORY_LABEL[] = {'M','L',0}; - -/* - * ACE flags - */ -static const WCHAR SDDL_CONTAINER_INHERIT[] = {'C','I',0}; -static const WCHAR SDDL_OBJECT_INHERIT[] = {'O','I',0}; -static const WCHAR SDDL_NO_PROPAGATE[] = {'N','P',0}; -static const WCHAR SDDL_INHERIT_ONLY[] = {'I','O',0}; -static const WCHAR SDDL_INHERITED[] = {'I','D',0}; -static const WCHAR SDDL_AUDIT_SUCCESS[] = {'S','A',0}; -static const WCHAR SDDL_AUDIT_FAILURE[] = {'F','A',0}; const char * debugstr_sid(PSID sid) { @@ -2807,481 +2646,6 @@ DWORD WINAPI GetAuditedPermissionsFromAclW( PACL pacl, PTRUSTEEW pTrustee, PACCE } -/****************************************************************************** - * ParseAclStringFlags - */ -static DWORD ParseAclStringFlags(LPCWSTR* StringAcl) -{ - DWORD flags = 0; - LPCWSTR szAcl = *StringAcl; - - while (*szAcl && *szAcl != '(') - { - if (*szAcl == 'P') - { - flags |= SE_DACL_PROTECTED; - } - else if (*szAcl == 'A') - { - szAcl++; - if (*szAcl == 'R') - flags |= SE_DACL_AUTO_INHERIT_REQ; - else if (*szAcl == 'I') - flags |= SE_DACL_AUTO_INHERITED; - } - szAcl++; - } - - *StringAcl = szAcl; - return flags; -} - -/****************************************************************************** - * ParseAceStringType - */ -static const ACEFLAG AceType[] = -{ - { SDDL_ALARM, SYSTEM_ALARM_ACE_TYPE }, - { SDDL_AUDIT, SYSTEM_AUDIT_ACE_TYPE }, - { SDDL_ACCESS_ALLOWED, ACCESS_ALLOWED_ACE_TYPE }, - { SDDL_ACCESS_DENIED, ACCESS_DENIED_ACE_TYPE }, - { SDDL_MANDATORY_LABEL,SYSTEM_MANDATORY_LABEL_ACE_TYPE }, - /* - { SDDL_OBJECT_ACCESS_ALLOWED, ACCESS_ALLOWED_OBJECT_ACE_TYPE }, - { SDDL_OBJECT_ACCESS_DENIED, ACCESS_DENIED_OBJECT_ACE_TYPE }, - { SDDL_OBJECT_ALARM, SYSTEM_ALARM_OBJECT_ACE_TYPE }, - { SDDL_OBJECT_AUDIT, SYSTEM_AUDIT_OBJECT_ACE_TYPE }, - */ - { NULL, 0 }, -}; - -static BYTE ParseAceStringType(LPCWSTR* StringAcl) -{ - UINT len = 0; - LPCWSTR szAcl = *StringAcl; - const ACEFLAG *lpaf = AceType; - - while (*szAcl == ' ') - szAcl++; - - while (lpaf->wstr && - (len = strlenW(lpaf->wstr)) && - strncmpW(lpaf->wstr, szAcl, len)) - lpaf++; - - if (!lpaf->wstr) - return 0; - - *StringAcl = szAcl + len; - return lpaf->value; -} - - -/****************************************************************************** - * ParseAceStringFlags - */ -static const ACEFLAG AceFlags[] = -{ - { SDDL_CONTAINER_INHERIT, CONTAINER_INHERIT_ACE }, - { SDDL_AUDIT_FAILURE, FAILED_ACCESS_ACE_FLAG }, - { SDDL_INHERITED, INHERITED_ACE }, - { SDDL_INHERIT_ONLY, INHERIT_ONLY_ACE }, - { SDDL_NO_PROPAGATE, NO_PROPAGATE_INHERIT_ACE }, - { SDDL_OBJECT_INHERIT, OBJECT_INHERIT_ACE }, - { SDDL_AUDIT_SUCCESS, SUCCESSFUL_ACCESS_ACE_FLAG }, - { NULL, 0 }, -}; - -static BYTE ParseAceStringFlags(LPCWSTR* StringAcl) -{ - UINT len = 0; - BYTE flags = 0; - LPCWSTR szAcl = *StringAcl; - - while (*szAcl == ' ') - szAcl++; - - while (*szAcl != ';') - { - const ACEFLAG *lpaf = AceFlags; - - while (lpaf->wstr && - (len = strlenW(lpaf->wstr)) && - strncmpW(lpaf->wstr, szAcl, len)) - lpaf++; - - if (!lpaf->wstr) - return 0; - - flags |= lpaf->value; - szAcl += len; - } - - *StringAcl = szAcl; - return flags; -} - - -/****************************************************************************** - * ParseAceStringRights - */ -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 }, - - { SDDL_NO_READ_UP, SYSTEM_MANDATORY_LABEL_NO_READ_UP }, - { SDDL_NO_WRITE_UP, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP }, - { SDDL_NO_EXECUTE_UP, SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP }, - { NULL, 0 }, -}; - -static DWORD ParseAceStringRights(LPCWSTR* StringAcl) -{ - UINT len = 0; - DWORD rights = 0; - LPCWSTR szAcl = *StringAcl; - - while (*szAcl == ' ') - szAcl++; - - if ((*szAcl == '0') && (*(szAcl + 1) == 'x')) - { - LPCWSTR p = szAcl; - - while (*p && *p != ';') - p++; - - if (p - szAcl <= 10 /* 8 hex digits + "0x" */ ) - { - rights = strtoulW(szAcl, NULL, 16); - szAcl = p; - } - else - WARN("Invalid rights string format: %s\n", debugstr_wn(szAcl, p - szAcl)); - } - else - { - while (*szAcl != ';') - { - const ACEFLAG *lpaf = AceRights; - - while (lpaf->wstr && - (len = strlenW(lpaf->wstr)) && - strncmpW(lpaf->wstr, szAcl, len)) - { - lpaf++; - } - - if (!lpaf->wstr) - return 0; - - rights |= lpaf->value; - szAcl += len; - } - } - - *StringAcl = szAcl; - return rights; -} - - -/****************************************************************************** - * ParseStringAclToAcl - * - * dacl_flags(string_ace1)(string_ace2)... (string_acen) - */ -static BOOL ParseStringAclToAcl(LPCWSTR StringAcl, LPDWORD lpdwFlags, - PACL pAcl, LPDWORD cBytes) -{ - DWORD val; - DWORD sidlen; - DWORD length = sizeof(ACL); - DWORD acesize = 0; - DWORD acecount = 0; - PACCESS_ALLOWED_ACE pAce = NULL; /* pointer to current ACE */ - DWORD error = ERROR_INVALID_ACL; - - TRACE("%s\n", debugstr_w(StringAcl)); - - if (!StringAcl) - return FALSE; - - if (pAcl) /* pAce is only useful if we're setting values */ - pAce = (PACCESS_ALLOWED_ACE) (pAcl + 1); - - /* Parse ACL flags */ - *lpdwFlags = ParseAclStringFlags(&StringAcl); - - /* Parse ACE */ - while (*StringAcl == '(') - { - StringAcl++; - - /* Parse ACE type */ - val = ParseAceStringType(&StringAcl); - if (pAce) - pAce->Header.AceType = (BYTE) val; - if (*StringAcl != ';') - { - error = RPC_S_INVALID_STRING_UUID; - goto lerr; - } - StringAcl++; - - /* Parse ACE flags */ - val = ParseAceStringFlags(&StringAcl); - if (pAce) - pAce->Header.AceFlags = (BYTE) val; - if (*StringAcl != ';') - goto lerr; - StringAcl++; - - /* Parse ACE rights */ - val = ParseAceStringRights(&StringAcl); - if (pAce) - pAce->Mask = val; - if (*StringAcl != ';') - goto lerr; - StringAcl++; - - /* Parse ACE object guid */ - while (*StringAcl == ' ') - StringAcl++; - if (*StringAcl != ';') - { - FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); - goto lerr; - } - StringAcl++; - - /* Parse ACE inherit object guid */ - while (*StringAcl == ' ') - StringAcl++; - if (*StringAcl != ';') - { - FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); - goto lerr; - } - StringAcl++; - - /* Parse ACE account sid */ - if (ParseStringSidToSid(StringAcl, pAce ? &pAce->SidStart : NULL, &sidlen)) - { - while (*StringAcl && *StringAcl != ')') - StringAcl++; - } - - if (*StringAcl != ')') - goto lerr; - StringAcl++; - - acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen; - length += acesize; - if (pAce) - { - pAce->Header.AceSize = acesize; - pAce = (PACCESS_ALLOWED_ACE)((LPBYTE)pAce + acesize); - } - acecount++; - } - - *cBytes = length; - - if (length > 0xffff) - { - ERR("ACL too large\n"); - goto lerr; - } - - if (pAcl) - { - pAcl->AclRevision = ACL_REVISION; - pAcl->Sbz1 = 0; - pAcl->AclSize = length; - pAcl->AceCount = acecount; - pAcl->Sbz2 = 0; - } - return TRUE; - -lerr: - SetLastError(error); - WARN("Invalid ACE string format\n"); - return FALSE; -} - - -/****************************************************************************** - * ParseStringSecurityDescriptorToSecurityDescriptor - */ -static BOOL ParseStringSecurityDescriptorToSecurityDescriptor( - LPCWSTR StringSecurityDescriptor, - SECURITY_DESCRIPTOR_RELATIVE* SecurityDescriptor, - LPDWORD cBytes) -{ - BOOL bret = FALSE; - WCHAR toktype; - WCHAR *tok; - LPCWSTR lptoken; - LPBYTE lpNext = NULL; - DWORD len; - - *cBytes = sizeof(SECURITY_DESCRIPTOR_RELATIVE); - - tok = heap_alloc( (lstrlenW(StringSecurityDescriptor) + 1) * sizeof(WCHAR)); - - if (SecurityDescriptor) - lpNext = (LPBYTE)(SecurityDescriptor + 1); - - while (*StringSecurityDescriptor == ' ') - StringSecurityDescriptor++; - - while (*StringSecurityDescriptor) - { - toktype = *StringSecurityDescriptor; - - /* Expect char identifier followed by ':' */ - StringSecurityDescriptor++; - if (*StringSecurityDescriptor != ':') - { - SetLastError(ERROR_INVALID_PARAMETER); - goto lend; - } - StringSecurityDescriptor++; - - /* Extract token */ - lptoken = StringSecurityDescriptor; - while (*lptoken && *lptoken != ':') - lptoken++; - - if (*lptoken) - lptoken--; - - len = lptoken - StringSecurityDescriptor; - memcpy( tok, StringSecurityDescriptor, len * sizeof(WCHAR) ); - tok[len] = 0; - - switch (toktype) - { - case 'O': - { - DWORD bytes; - - if (!ParseStringSidToSid(tok, lpNext, &bytes)) - goto lend; - - if (SecurityDescriptor) - { - SecurityDescriptor->Owner = lpNext - (LPBYTE)SecurityDescriptor; - lpNext += bytes; /* Advance to next token */ - } - - *cBytes += bytes; - - break; - } - - case 'G': - { - DWORD bytes; - - if (!ParseStringSidToSid(tok, lpNext, &bytes)) - goto lend; - - if (SecurityDescriptor) - { - SecurityDescriptor->Group = lpNext - (LPBYTE)SecurityDescriptor; - lpNext += bytes; /* Advance to next token */ - } - - *cBytes += bytes; - - break; - } - - case 'D': - { - DWORD flags; - DWORD bytes; - - if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes)) - goto lend; - - if (SecurityDescriptor) - { - SecurityDescriptor->Control |= SE_DACL_PRESENT | flags; - SecurityDescriptor->Dacl = lpNext - (LPBYTE)SecurityDescriptor; - lpNext += bytes; /* Advance to next token */ - } - - *cBytes += bytes; - - break; - } - - case 'S': - { - DWORD flags; - DWORD bytes; - - if (!ParseStringAclToAcl(tok, &flags, (PACL)lpNext, &bytes)) - goto lend; - - if (SecurityDescriptor) - { - SecurityDescriptor->Control |= SE_SACL_PRESENT | flags; - SecurityDescriptor->Sacl = lpNext - (LPBYTE)SecurityDescriptor; - lpNext += bytes; /* Advance to next token */ - } - - *cBytes += bytes; - - break; - } - - default: - FIXME("Unknown token\n"); - SetLastError(ERROR_INVALID_PARAMETER); - goto lend; - } - - StringSecurityDescriptor = lptoken; - } - - bret = TRUE; - -lend: - heap_free(tok); - return bret; -} - /****************************************************************************** * ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@] */ @@ -3309,471 +2673,6 @@ BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA( return ret; } -/****************************************************************************** - * ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@] - */ -BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW( - LPCWSTR StringSecurityDescriptor, - DWORD StringSDRevision, - PSECURITY_DESCRIPTOR* SecurityDescriptor, - PULONG SecurityDescriptorSize) -{ - DWORD cBytes; - SECURITY_DESCRIPTOR* psd; - BOOL bret = FALSE; - - TRACE("%s, %u, %p, %p\n", debugstr_w(StringSecurityDescriptor), StringSDRevision, - SecurityDescriptor, SecurityDescriptorSize); - - if (GetVersion() & 0x80000000) - { - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - goto lend; - } - else if (!StringSecurityDescriptor || !SecurityDescriptor) - { - SetLastError(ERROR_INVALID_PARAMETER); - goto lend; - } - else if (StringSDRevision != SID_REVISION) - { - SetLastError(ERROR_UNKNOWN_REVISION); - goto lend; - } - - /* Compute security descriptor length */ - if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor, - NULL, &cBytes)) - goto lend; - - psd = *SecurityDescriptor = LocalAlloc(GMEM_ZEROINIT, cBytes); - if (!psd) goto lend; - - psd->Revision = SID_REVISION; - psd->Control |= SE_SELF_RELATIVE; - - if (!ParseStringSecurityDescriptorToSecurityDescriptor(StringSecurityDescriptor, - (SECURITY_DESCRIPTOR_RELATIVE *)psd, &cBytes)) - { - LocalFree(psd); - goto lend; - } - - if (SecurityDescriptorSize) - *SecurityDescriptorSize = cBytes; - - bret = TRUE; - -lend: - TRACE(" ret=%d\n", bret); - return bret; -} - -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) -{ - static const WCHAR fmt[] = { 'S','-','%','u','-','%','d',0 }; - static const WCHAR subauthfmt[] = { '-','%','u',0 }; - DWORD i; - 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; iSubAuthorityCount; 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 < ARRAY_SIZE(WellKnownSids); 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 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 -}; - -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 < ARRAY_SIZE(AceRights); 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 inline BOOL is_object_ace(BYTE AceType) -{ - switch (AceType) - { - case ACCESS_ALLOWED_OBJECT_ACE_TYPE: - case ACCESS_DENIED_OBJECT_ACE_TYPE: - case ACCESS_AUDIT_OBJECT_ACE_TYPE: - case ACCESS_ALARM_OBJECT_ACE_TYPE: - case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: - case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: - case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: - case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE: - return TRUE; - - default: return FALSE; - } -} - -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 = ';'; - DWORD *SidStart; - - piace = pace; - - if (piace->Header.AceType > ACCESS_MAX_MS_V5_ACE_TYPE || piace->Header.AceSize < sizeof(ACCESS_ALLOWED_ACE)) - { - SetLastError(ERROR_INVALID_ACL); - return FALSE; - } - - 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); - SidStart = &piace->SidStart; - if (is_object_ace(piace->Header.AceType)) - { - ACCESS_ALLOWED_OBJECT_ACE *objace = pace; - - SidStart++; /* Flags */ - if (objace->Flags & ACE_OBJECT_TYPE_PRESENT) - SidStart += sizeof(GUID) / sizeof(*SidStart); /* ObjectType */ - if (objace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) - SidStart += sizeof(GUID) / sizeof(*SidStart); /* InheritedObjectType */ - } - /* objects not supported */ - DumpString(&semicolon, 1, pwptr, plen); - /* objects not supported */ - DumpString(&semicolon, 1, pwptr, plen); - if (!DumpSid(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; - UINT 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; -} - -/****************************************************************************** - * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@] - */ -BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor, DWORD SDRevision, SECURITY_INFORMATION RequestedInformation, LPWSTR *OutputString, PULONG OutputLen) -{ - ULONG len; - WCHAR *wptr, *wstr; - - if (SDRevision != SDDL_REVISION_1) - { - ERR("Program requested unknown SDDL revision %d\n", SDRevision); - SetLastError(ERROR_UNKNOWN_REVISION); - return FALSE; - } - - len = 0; - if (RequestedInformation & OWNER_SECURITY_INFORMATION) - if (!DumpOwner(SecurityDescriptor, NULL, &len)) - return FALSE; - if (RequestedInformation & GROUP_SECURITY_INFORMATION) - if (!DumpGroup(SecurityDescriptor, NULL, &len)) - return FALSE; - if (RequestedInformation & DACL_SECURITY_INFORMATION) - if (!DumpDacl(SecurityDescriptor, NULL, &len)) - return FALSE; - if (RequestedInformation & SACL_SECURITY_INFORMATION) - if (!DumpSacl(SecurityDescriptor, NULL, &len)) - return FALSE; - - wstr = wptr = LocalAlloc(0, (len + 1)*sizeof(WCHAR)); - if (RequestedInformation & OWNER_SECURITY_INFORMATION) - if (!DumpOwner(SecurityDescriptor, &wptr, NULL)) { - LocalFree (wstr); - return FALSE; - } - if (RequestedInformation & GROUP_SECURITY_INFORMATION) - if (!DumpGroup(SecurityDescriptor, &wptr, NULL)) { - LocalFree (wstr); - return FALSE; - } - if (RequestedInformation & DACL_SECURITY_INFORMATION) - if (!DumpDacl(SecurityDescriptor, &wptr, NULL)) { - LocalFree (wstr); - return FALSE; - } - if (RequestedInformation & SACL_SECURITY_INFORMATION) - if (!DumpSacl(SecurityDescriptor, &wptr, NULL)) { - LocalFree (wstr); - return FALSE; - } - *wptr = 0; - - TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len); - *OutputString = wstr; - if (OutputLen) - *OutputLen = strlenW(*OutputString)+1; - return TRUE; -} - /****************************************************************************** * ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@] */ @@ -3803,30 +2702,6 @@ BOOL WINAPI ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCR } } -/****************************************************************************** - * ConvertStringSidToSidW [ADVAPI32.@] - */ -BOOL WINAPI ConvertStringSidToSidW(LPCWSTR StringSid, PSID* Sid) -{ - BOOL bret = FALSE; - DWORD cBytes; - - TRACE("%s, %p\n", debugstr_w(StringSid), Sid); - if (GetVersion() & 0x80000000) - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - else if (!StringSid || !Sid) - SetLastError(ERROR_INVALID_PARAMETER); - else if (ParseStringSidToSid(StringSid, NULL, &cBytes)) - { - PSID pSid = *Sid = LocalAlloc(0, cBytes); - - bret = ParseStringSidToSid(StringSid, pSid, &cBytes); - if (!bret) - LocalFree(*Sid); - } - return bret; -} - /****************************************************************************** * ConvertStringSidToSidA [ADVAPI32.@] */ @@ -3848,34 +2723,6 @@ BOOL WINAPI ConvertStringSidToSidA(LPCSTR StringSid, PSID* Sid) return bret; } -/****************************************************************************** - * ConvertSidToStringSidW [ADVAPI32.@] - * - * format of SID string is: - * S-----... - * where - * is the revision of the SID encoded as decimal - * is the identifier authority encoded as hex - * is the subauthority id encoded as decimal - */ -BOOL WINAPI ConvertSidToStringSidW( PSID pSid, LPWSTR *pstr ) -{ - DWORD len = 0; - LPWSTR wstr, wptr; - - TRACE("%p %p\n", pSid, pstr ); - - len = 0; - if (!DumpSidNumeric(pSid, NULL, &len)) - return FALSE; - wstr = wptr = LocalAlloc(0, (len+1) * sizeof(WCHAR)); - DumpSidNumeric(pSid, &wptr, NULL); - *wptr = 0; - - *pstr = wstr; - return TRUE; -} - /****************************************************************************** * ConvertSidToStringSidA [ADVAPI32.@] */ @@ -3929,167 +2776,6 @@ BOOL WINAPI CreateProcessWithTokenW(HANDLE token, DWORD logon_flags, LPCWSTR app current_directory, startup_info, process_information ); } -/****************************************************************************** - * ComputeStringSidSize - */ -static DWORD ComputeStringSidSize(LPCWSTR StringSid) -{ - if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I(-S)+ */ - { - int ctok = 0; - while (*StringSid) - { - if (*StringSid == '-') - ctok++; - StringSid++; - } - - if (ctok >= 3) - return GetSidLengthRequired(ctok - 2); - } - else /* String constant format - Only available in winxp and above */ - { - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(WellKnownSids); i++) - if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2)) - return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount); - - for (i = 0; i < ARRAY_SIZE(WellKnownRids); i++) - if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2)) - { - MAX_SID local; - ADVAPI_GetComputerSid(&local); - return GetSidLengthRequired(*GetSidSubAuthorityCount(&local) + 1); - } - - } - - return GetSidLengthRequired(0); -} - -/****************************************************************************** - * ParseStringSidToSid - */ -static BOOL ParseStringSidToSid(LPCWSTR StringSid, PSID pSid, LPDWORD cBytes) -{ - BOOL bret = FALSE; - SID* pisid=pSid; - - TRACE("%s, %p, %p\n", debugstr_w(StringSid), pSid, cBytes); - if (!StringSid) - { - SetLastError(ERROR_INVALID_PARAMETER); - TRACE("StringSid is NULL, returning FALSE\n"); - return FALSE; - } - - while (*StringSid == ' ') - StringSid++; - - *cBytes = ComputeStringSidSize(StringSid); - if (!pisid) /* Simply compute the size */ - { - TRACE("only size requested, returning TRUE with %d\n", *cBytes); - return TRUE; - } - - if (StringSid[0] == 'S' && StringSid[1] == '-') /* S-R-I-S-S */ - { - DWORD i = 0, identAuth; - DWORD csubauth = ((*cBytes - GetSidLengthRequired(0)) / sizeof(DWORD)); - - StringSid += 2; /* Advance to Revision */ - pisid->Revision = atoiW(StringSid); - - if (pisid->Revision != SDDL_REVISION) - { - TRACE("Revision %d is unknown\n", pisid->Revision); - goto lend; /* ERROR_INVALID_SID */ - } - if (csubauth == 0) - { - TRACE("SubAuthorityCount is 0\n"); - goto lend; /* ERROR_INVALID_SID */ - } - - pisid->SubAuthorityCount = csubauth; - - /* Advance to identifier authority */ - while (*StringSid && *StringSid != '-') - StringSid++; - if (*StringSid == '-') - StringSid++; - - /* MS' implementation can't handle values greater than 2^32 - 1, so - * we don't either; assume most significant bytes are always 0 - */ - pisid->IdentifierAuthority.Value[0] = 0; - pisid->IdentifierAuthority.Value[1] = 0; - identAuth = atoiW(StringSid); - pisid->IdentifierAuthority.Value[5] = identAuth & 0xff; - pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8; - pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16; - pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24; - - /* Advance to first sub authority */ - while (*StringSid && *StringSid != '-') - StringSid++; - if (*StringSid == '-') - StringSid++; - - while (*StringSid) - { - pisid->SubAuthority[i++] = atoiW(StringSid); - - while (*StringSid && *StringSid != '-') - StringSid++; - if (*StringSid == '-') - StringSid++; - } - - if (i != pisid->SubAuthorityCount) - goto lend; /* ERROR_INVALID_SID */ - - bret = TRUE; - } - else /* String constant format - Only available in winxp and above */ - { - unsigned int i; - pisid->Revision = SDDL_REVISION; - - for (i = 0; i < ARRAY_SIZE(WellKnownSids); i++) - if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2)) - { - DWORD j; - pisid->SubAuthorityCount = WellKnownSids[i].Sid.SubAuthorityCount; - pisid->IdentifierAuthority = WellKnownSids[i].Sid.IdentifierAuthority; - for (j = 0; j < WellKnownSids[i].Sid.SubAuthorityCount; j++) - pisid->SubAuthority[j] = WellKnownSids[i].Sid.SubAuthority[j]; - bret = TRUE; - } - - for (i = 0; i < ARRAY_SIZE(WellKnownRids); i++) - if (!strncmpW(WellKnownRids[i].wstr, StringSid, 2)) - { - ADVAPI_GetComputerSid(pisid); - pisid->SubAuthority[pisid->SubAuthorityCount] = WellKnownRids[i].Rid; - pisid->SubAuthorityCount++; - bret = TRUE; - } - - if (!bret) - FIXME("String constant not supported: %s\n", debugstr_wn(StringSid, 2)); - } - -lend: - if (!bret) - SetLastError(ERROR_INVALID_SID); - - TRACE("returning %s\n", bret ? "TRUE" : "FALSE"); - return bret; -} - /****************************************************************************** * GetNamedSecurityInfoA [ADVAPI32.@] */ diff --git a/dlls/sechost/Makefile.in b/dlls/sechost/Makefile.in index eb98d04859c..91016c67577 100644 --- a/dlls/sechost/Makefile.in +++ b/dlls/sechost/Makefile.in @@ -6,6 +6,7 @@ DELAYIMPORTS = rpcrt4 EXTRADLLFLAGS = -mno-cygwin C_SRCS = \ + security.c \ service.c \ trace.c diff --git a/dlls/sechost/sechost.spec b/dlls/sechost/sechost.spec index df6af1646df..f21e2f1cda8 100644 --- a/dlls/sechost/sechost.spec +++ b/dlls/sechost/sechost.spec @@ -31,13 +31,13 @@ @ stdcall ControlTraceA(int64 str ptr long) @ stdcall ControlTraceW(int64 wstr ptr long) @ stub ConvertSDToStringSDRootDomainW -@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr) advapi32.ConvertSecurityDescriptorToStringSecurityDescriptorW -@ stdcall ConvertSidToStringSidW(ptr ptr) advapi32.ConvertSidToStringSidW +@ stdcall ConvertSecurityDescriptorToStringSecurityDescriptorW(ptr long long ptr ptr) +@ stdcall ConvertSidToStringSidW(ptr ptr) @ stub ConvertStringSDToSDDomainA @ stub ConvertStringSDToSDDomainW @ stub ConvertStringSDToSDRootDomainW -@ stdcall ConvertStringSecurityDescriptorToSecurityDescriptorW(wstr long ptr ptr) advapi32.ConvertStringSecurityDescriptorToSecurityDescriptorW -@ stdcall ConvertStringSidToSidW(ptr ptr) advapi32.ConvertStringSidToSidW +@ stdcall ConvertStringSecurityDescriptorToSecurityDescriptorW(wstr long ptr ptr) +@ stdcall ConvertStringSidToSidW(ptr ptr) @ stdcall CreateServiceA(long str str long long long long str str ptr str str str) @ stub CreateServiceEx @ stdcall CreateServiceW(long wstr wstr long long long long wstr wstr ptr wstr wstr wstr) diff --git a/dlls/sechost/security.c b/dlls/sechost/security.c new file mode 100644 index 00000000000..47ffba9ed52 --- /dev/null +++ b/dlls/sechost/security.c @@ -0,0 +1,1247 @@ +/* + * Security API + * + * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include "windef.h" +#include "winbase.h" +#include "sddl.h" +#include "iads.h" + +#include "wine/debug.h" +#include "wine/heap.h" + +WINE_DEFAULT_DEBUG_CHANNEL(security); + +static const struct +{ + WCHAR str[3]; + DWORD value; +} +ace_rights[] = +{ + { L"GA", GENERIC_ALL }, + { L"GR", GENERIC_READ }, + { L"GW", GENERIC_WRITE }, + { L"GX", GENERIC_EXECUTE }, + + { L"RC", READ_CONTROL }, + { L"SD", DELETE }, + { L"WD", WRITE_DAC }, + { L"WO", WRITE_OWNER }, + + { L"RP", ADS_RIGHT_DS_READ_PROP }, + { L"WP", ADS_RIGHT_DS_WRITE_PROP }, + { L"CC", ADS_RIGHT_DS_CREATE_CHILD }, + { L"DC", ADS_RIGHT_DS_DELETE_CHILD }, + { L"LC", ADS_RIGHT_ACTRL_DS_LIST }, + { L"SW", ADS_RIGHT_DS_SELF }, + { L"LO", ADS_RIGHT_DS_LIST_OBJECT }, + { L"DT", ADS_RIGHT_DS_DELETE_TREE }, + { L"CR", ADS_RIGHT_DS_CONTROL_ACCESS }, + + { L"FA", FILE_ALL_ACCESS }, + { L"FR", FILE_GENERIC_READ }, + { L"FW", FILE_GENERIC_WRITE }, + { L"FX", FILE_GENERIC_EXECUTE }, + + { L"KA", KEY_ALL_ACCESS }, + { L"KR", KEY_READ }, + { L"KW", KEY_WRITE }, + { L"KX", KEY_EXECUTE }, + + { L"NR", SYSTEM_MANDATORY_LABEL_NO_READ_UP }, + { L"NW", SYSTEM_MANDATORY_LABEL_NO_WRITE_UP }, + { L"NX", SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP }, +}; + +struct max_sid +{ + /* same fields as struct _SID */ + BYTE Revision; + BYTE SubAuthorityCount; + SID_IDENTIFIER_AUTHORITY IdentifierAuthority; + DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES]; +}; + +static const struct +{ + WCHAR str[2]; + WELL_KNOWN_SID_TYPE Type; + struct max_sid sid; +} +well_known_sids[] = +{ + { {0,0}, WinNullSid, { SID_REVISION, 1, { SECURITY_NULL_SID_AUTHORITY }, { SECURITY_NULL_RID } } }, + { {'W','D'}, WinWorldSid, { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY }, { SECURITY_WORLD_RID } } }, + { {0,0}, WinLocalSid, { SID_REVISION, 1, { SECURITY_LOCAL_SID_AUTHORITY }, { SECURITY_LOCAL_RID } } }, + { {'C','O'}, WinCreatorOwnerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RID } } }, + { {'C','G'}, WinCreatorGroupSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_RID } } }, + { {'O','W'}, WinCreatorOwnerRightsSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_RIGHTS_RID } } }, + { {0,0}, WinCreatorOwnerServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_OWNER_SERVER_RID } } }, + { {0,0}, WinCreatorGroupServerSid, { SID_REVISION, 1, { SECURITY_CREATOR_SID_AUTHORITY }, { SECURITY_CREATOR_GROUP_SERVER_RID } } }, + { {0,0}, WinNtAuthoritySid, { SID_REVISION, 0, { SECURITY_NT_AUTHORITY }, { SECURITY_NULL_RID } } }, + { {0,0}, WinDialupSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_DIALUP_RID } } }, + { {'N','U'}, WinNetworkSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_RID } } }, + { {0,0}, WinBatchSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BATCH_RID } } }, + { {'I','U'}, WinInteractiveSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_INTERACTIVE_RID } } }, + { {'S','U'}, WinServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_SERVICE_RID } } }, + { {'A','N'}, WinAnonymousSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ANONYMOUS_LOGON_RID } } }, + { {0,0}, WinProxySid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PROXY_RID } } }, + { {'E','D'}, WinEnterpriseControllersSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_ENTERPRISE_CONTROLLERS_RID } } }, + { {'P','S'}, WinSelfSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_PRINCIPAL_SELF_RID } } }, + { {'A','U'}, WinAuthenticatedUserSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_AUTHENTICATED_USER_RID } } }, + { {'R','C'}, WinRestrictedCodeSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_RESTRICTED_CODE_RID } } }, + { {0,0}, WinTerminalServerSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_TERMINAL_SERVER_RID } } }, + { {0,0}, WinRemoteLogonIdSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_REMOTE_LOGON_RID } } }, + { {0,0}, WinLogonIdsSid, { SID_REVISION, SECURITY_LOGON_IDS_RID_COUNT, { SECURITY_NT_AUTHORITY }, { SECURITY_LOGON_IDS_RID } } }, + { {'S','Y'}, WinLocalSystemSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SYSTEM_RID } } }, + { {'L','S'}, WinLocalServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_LOCAL_SERVICE_RID } } }, + { {'N','S'}, WinNetworkServiceSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_NETWORK_SERVICE_RID } } }, + { {0,0}, WinBuiltinDomainSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID } } }, + { {'B','A'}, WinBuiltinAdministratorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS } } }, + { {'B','U'}, WinBuiltinUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS } } }, + { {'B','G'}, WinBuiltinGuestsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_GUESTS } } }, + { {'P','U'}, WinBuiltinPowerUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS } } }, + { {'A','O'}, WinBuiltinAccountOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ACCOUNT_OPS } } }, + { {'S','O'}, WinBuiltinSystemOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_SYSTEM_OPS } } }, + { {'P','O'}, WinBuiltinPrintOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PRINT_OPS } } }, + { {'B','O'}, WinBuiltinBackupOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_BACKUP_OPS } } }, + { {'R','E'}, WinBuiltinReplicatorSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REPLICATOR } } }, + { {'R','U'}, WinBuiltinPreWindows2000CompatibleAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_PREW2KCOMPACCESS } } }, + { {'R','D'}, WinBuiltinRemoteDesktopUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_REMOTE_DESKTOP_USERS } } }, + { {'N','O'}, WinBuiltinNetworkConfigurationOperatorsSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_NETWORK_CONFIGURATION_OPS } } }, + { {0,0}, WinNTLMAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_NTLM_RID } } }, + { {0,0}, WinDigestAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_DIGEST_RID } } }, + { {0,0}, WinSChannelAuthenticationSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_PACKAGE_BASE_RID, SECURITY_PACKAGE_SCHANNEL_RID } } }, + { {0,0}, WinThisOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_THIS_ORGANIZATION_RID } } }, + { {0,0}, WinOtherOrganizationSid, { SID_REVISION, 1, { SECURITY_NT_AUTHORITY }, { SECURITY_OTHER_ORGANIZATION_RID } } }, + { {0,0}, WinBuiltinIncomingForestTrustBuildersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_INCOMING_FOREST_TRUST_BUILDERS } } }, + { {0,0}, WinBuiltinPerfMonitoringUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_MONITORING_USERS } } }, + { {0,0}, WinBuiltinPerfLoggingUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_LOGGING_USERS } } }, + { {0,0}, WinBuiltinAuthorizationAccessSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_AUTHORIZATIONACCESS } } }, + { {0,0}, WinBuiltinTerminalServerLicenseServersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_TS_LICENSE_SERVERS } } }, + { {0,0}, WinBuiltinDCOMUsersSid, { SID_REVISION, 2, { SECURITY_NT_AUTHORITY }, { SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_DCOM_USERS } } }, + { {'L','W'}, WinLowLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_LOW_RID} } }, + { {'M','E'}, WinMediumLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_MEDIUM_RID } } }, + { {'H','I'}, WinHighLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_HIGH_RID } } }, + { {'S','I'}, WinSystemLabelSid, { SID_REVISION, 1, { SECURITY_MANDATORY_LABEL_AUTHORITY}, { SECURITY_MANDATORY_SYSTEM_RID } } }, + { {'A','C'}, WinBuiltinAnyPackageSid, { SID_REVISION, 2, { SECURITY_APP_PACKAGE_AUTHORITY }, { SECURITY_APP_PACKAGE_BASE_RID, SECURITY_BUILTIN_PACKAGE_ANY_PACKAGE } } }, +}; + +/* these SIDs must be constructed as relative to some domain - only the RID is well-known */ +static const struct +{ + WCHAR str[2]; + WELL_KNOWN_SID_TYPE type; + DWORD rid; +} +well_known_rids[] = +{ + { {'L','A'}, WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN }, + { {'L','G'}, WinAccountGuestSid, DOMAIN_USER_RID_GUEST }, + { {0,0}, WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT }, + { {'D','A'}, WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS }, + { {'D','U'}, WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS }, + { {'D','G'}, WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS }, + { {'D','C'}, WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS }, + { {'D','D'}, WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS }, + { {'C','A'}, WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS }, + { {'S','A'}, WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS }, + { {'E','A'}, WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS }, + { {'P','A'}, WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS }, + { {'R','S'}, WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS }, +}; + + +static void print_string(const WCHAR *string, int cch, WCHAR **pwptr, ULONG *plen) +{ + if (cch == -1) + cch = wcslen(string); + + if (plen) + *plen += cch; + + if (pwptr) + { + memcpy(*pwptr, string, sizeof(WCHAR)*cch); + *pwptr += cch; + } +} + +static BOOL print_sid_numeric(PSID psid, WCHAR **pwptr, ULONG *plen) +{ + DWORD i; + 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; + } + + swprintf( buf, ARRAY_SIZE(buf), L"S-%u-%d", pisid->Revision, MAKELONG( + MAKEWORD( pisid->IdentifierAuthority.Value[5], pisid->IdentifierAuthority.Value[4] ), + MAKEWORD( pisid->IdentifierAuthority.Value[3], pisid->IdentifierAuthority.Value[2] ) + ) ); + print_string(buf, -1, pwptr, plen); + + for( i=0; iSubAuthorityCount; i++ ) + { + swprintf( buf, ARRAY_SIZE(buf), L"-%u", pisid->SubAuthority[i] ); + print_string(buf, -1, pwptr, plen); + } + return TRUE; +} + +/****************************************************************************** + * ConvertSidToStringSidW (sechost.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH ConvertSidToStringSidW( PSID sid, WCHAR **pstr ) +{ + DWORD len = 0; + WCHAR *wstr, *wptr; + + TRACE("%p %p\n", sid, pstr ); + + len = 0; + if (!print_sid_numeric( sid, NULL, &len )) + return FALSE; + wstr = wptr = LocalAlloc( 0, (len + 1) * sizeof(WCHAR) ); + print_sid_numeric( sid, &wptr, NULL ); + *wptr = 0; + + *pstr = wstr; + return TRUE; +} + +static BOOL print_sid(PSID psid, WCHAR **pwptr, ULONG *plen) +{ + size_t i; + for (i = 0; i < ARRAY_SIZE(well_known_sids); i++) + { + if (well_known_sids[i].str[0] && EqualSid(psid, (PSID)&well_known_sids[i].sid.Revision)) + { + print_string(well_known_sids[i].str, 2, pwptr, plen); + return TRUE; + } + } + + return print_sid_numeric(psid, pwptr, plen); +} + +static void print_rights(DWORD mask, WCHAR **pwptr, ULONG *plen) +{ + static const WCHAR *bit_names[32] = + { + L"CC", /* 0 */ + L"DC", + L"LC", + L"SW", + L"RP", /* 4 */ + L"WP", + L"DT", + L"LO", + L"CR", /* 8 */ + NULL, + NULL, + NULL, + NULL, /* 12 */ + NULL, + NULL, + NULL, + L"SD", /* 16 */ + L"RC", + L"WD", + L"WO", + NULL, /* 20 */ + NULL, + NULL, + NULL, + NULL, /* 24 */ + NULL, + NULL, + NULL, + L"GA", /* 28 */ + L"GX", + L"GW", + L"GR", + }; + + WCHAR buf[15]; + size_t i; + + if (mask == 0) + return; + + /* first check if the right have name */ + for (i = 0; i < ARRAY_SIZE(ace_rights); i++) + { + if (mask == ace_rights[i].value) + { + print_string(ace_rights[i].str, -1, pwptr, plen); + return; + } + } + + /* then check if it can be built from bit names */ + for (i = 0; i < 32; i++) + { + if ((mask & (1 << i)) && !bit_names[i]) + { + /* can't be built from bit names */ + swprintf(buf, ARRAY_SIZE(buf), L"0x%x", mask); + print_string(buf, -1, pwptr, plen); + return; + } + } + + /* build from bit names */ + for (i = 0; i < 32; i++) + if (mask & (1 << i)) + print_string(bit_names[i], -1, pwptr, plen); +} + +static inline BOOL is_object_ace(BYTE type) +{ + switch (type) + { + case ACCESS_ALLOWED_OBJECT_ACE_TYPE: + case ACCESS_DENIED_OBJECT_ACE_TYPE: + case ACCESS_AUDIT_OBJECT_ACE_TYPE: + case ACCESS_ALARM_OBJECT_ACE_TYPE: + case ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE: + case ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE: + case SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE: + case SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE: + return TRUE; + + default: + return FALSE; + } +} + +static BOOL print_ace(void *pace, WCHAR **pwptr, ULONG *plen) +{ + ACCESS_ALLOWED_ACE *piace; /* all the supported ACEs have the same memory layout */ + DWORD *sid_start; + + piace = pace; + + if (piace->Header.AceType > ACCESS_MAX_MS_V5_ACE_TYPE || piace->Header.AceSize < sizeof(ACCESS_ALLOWED_ACE)) + { + SetLastError(ERROR_INVALID_ACL); + return FALSE; + } + + print_string(L"(", -1, pwptr, plen); + switch (piace->Header.AceType) + { + case ACCESS_ALLOWED_ACE_TYPE: + print_string(L"A", -1, pwptr, plen); + break; + case ACCESS_DENIED_ACE_TYPE: + print_string(L"D", -1, pwptr, plen); + break; + case SYSTEM_AUDIT_ACE_TYPE: + print_string(L"AU", -1, pwptr, plen); + break; + case SYSTEM_ALARM_ACE_TYPE: + print_string(L"AL", -1, pwptr, plen); + break; + } + print_string(L";", -1, pwptr, plen); + + if (piace->Header.AceFlags & OBJECT_INHERIT_ACE) + print_string(L"OI", -1, pwptr, plen); + if (piace->Header.AceFlags & CONTAINER_INHERIT_ACE) + print_string(L"CI", -1, pwptr, plen); + if (piace->Header.AceFlags & NO_PROPAGATE_INHERIT_ACE) + print_string(L"NP", -1, pwptr, plen); + if (piace->Header.AceFlags & INHERIT_ONLY_ACE) + print_string(L"IO", -1, pwptr, plen); + if (piace->Header.AceFlags & INHERITED_ACE) + print_string(L"ID", -1, pwptr, plen); + if (piace->Header.AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG) + print_string(L"SA", -1, pwptr, plen); + if (piace->Header.AceFlags & FAILED_ACCESS_ACE_FLAG) + print_string(L"FA", -1, pwptr, plen); + print_string(L";", -1, pwptr, plen); + print_rights(piace->Mask, pwptr, plen); + print_string(L";", -1, pwptr, plen); + sid_start = &piace->SidStart; + if (is_object_ace(piace->Header.AceType)) + { + ACCESS_ALLOWED_OBJECT_ACE *objace = pace; + + sid_start++; /* Flags */ + if (objace->Flags & ACE_OBJECT_TYPE_PRESENT) + sid_start += sizeof(GUID) / sizeof(*sid_start); /* ObjectType */ + if (objace->Flags & ACE_INHERITED_OBJECT_TYPE_PRESENT) + sid_start += sizeof(GUID) / sizeof(*sid_start); /* InheritedObjectType */ + } + /* objects not supported */ + print_string(L";", -1, pwptr, plen); + /* objects not supported */ + print_string(L";", -1, pwptr, plen); + if (!print_sid(sid_start, pwptr, plen)) + return FALSE; + print_string(L")", -1, pwptr, plen); + return TRUE; +} + +static BOOL print_acl(ACL *pacl, WCHAR **pwptr, ULONG *plen, SECURITY_DESCRIPTOR_CONTROL control) +{ + WORD count; + UINT i; + + if (control & SE_DACL_PROTECTED) + print_string(L"P", -1, pwptr, plen); + if (control & SE_DACL_AUTO_INHERIT_REQ) + print_string(L"AR", -1, pwptr, plen); + if (control & SE_DACL_AUTO_INHERITED) + print_string(L"AI", -1, pwptr, plen); + + if (pacl == NULL) + return TRUE; + + if (!IsValidAcl(pacl)) + return FALSE; + + count = pacl->AceCount; + for (i = 0; i < count; i++) + { + void *ace; + if (!GetAce(pacl, i, &ace)) + return FALSE; + if (!print_ace(ace, pwptr, plen)) + return FALSE; + } + + return TRUE; +} + +static BOOL print_owner(PSECURITY_DESCRIPTOR sd, WCHAR **pwptr, ULONG *plen) +{ + BOOL defaulted; + PSID psid; + + if (!GetSecurityDescriptorOwner(sd, &psid, &defaulted)) + return FALSE; + + if (psid == NULL) + return TRUE; + + print_string(L"O:", -1, pwptr, plen); + if (!print_sid(psid, pwptr, plen)) + return FALSE; + return TRUE; +} + +static BOOL print_group(PSECURITY_DESCRIPTOR sd, WCHAR **pwptr, ULONG *plen) +{ + BOOL defaulted; + PSID psid; + + if (!GetSecurityDescriptorGroup(sd, &psid, &defaulted)) + return FALSE; + + if (psid == NULL) + return TRUE; + + print_string(L"G:", -1, pwptr, plen); + if (!print_sid(psid, pwptr, plen)) + return FALSE; + return TRUE; +} + +static BOOL print_dacl(PSECURITY_DESCRIPTOR sd, WCHAR **pwptr, ULONG *plen) +{ + SECURITY_DESCRIPTOR_CONTROL control; + BOOL present, defaulted; + DWORD revision; + ACL *pacl; + + if (!GetSecurityDescriptorDacl(sd, &present, &pacl, &defaulted)) + return FALSE; + + if (!GetSecurityDescriptorControl(sd, &control, &revision)) + return FALSE; + + if (!present) + return TRUE; + + print_string(L"D:", -1, pwptr, plen); + if (!print_acl(pacl, pwptr, plen, control)) + return FALSE; + return TRUE; +} + +static BOOL print_sacl(PSECURITY_DESCRIPTOR sd, WCHAR **pwptr, ULONG *plen) +{ + SECURITY_DESCRIPTOR_CONTROL control; + BOOL present, defaulted; + DWORD revision; + ACL *pacl; + + if (!GetSecurityDescriptorSacl(sd, &present, &pacl, &defaulted)) + return FALSE; + + if (!GetSecurityDescriptorControl(sd, &control, &revision)) + return FALSE; + + if (!present) + return TRUE; + + print_string(L"S:", -1, pwptr, plen); + if (!print_acl(pacl, pwptr, plen, control)) + return FALSE; + return TRUE; +} + +/****************************************************************************** + * ConvertSecurityDescriptorToStringSecurityDescriptorW (sechost.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH ConvertSecurityDescriptorToStringSecurityDescriptorW( PSECURITY_DESCRIPTOR sd, + DWORD revision, SECURITY_INFORMATION flags, WCHAR **string, ULONG *ret_len ) +{ + ULONG len = 0; + WCHAR *wptr, *wstr; + + if (revision != SDDL_REVISION_1) + { + ERR("Unhandled SDDL revision %d\n", revision); + SetLastError( ERROR_UNKNOWN_REVISION ); + return FALSE; + } + + if ((flags & OWNER_SECURITY_INFORMATION) && !print_owner(sd, NULL, &len)) + return FALSE; + if ((flags & GROUP_SECURITY_INFORMATION) && !print_group(sd, NULL, &len)) + return FALSE; + if ((flags & DACL_SECURITY_INFORMATION) && !print_dacl(sd, NULL, &len)) + return FALSE; + if ((flags & SACL_SECURITY_INFORMATION) && !print_sacl(sd, NULL, &len)) + return FALSE; + + wstr = wptr = LocalAlloc( 0, (len + 1) * sizeof(WCHAR) ); + if ((flags & OWNER_SECURITY_INFORMATION) && !print_owner(sd, &wptr, NULL)) + { + LocalFree(wstr); + return FALSE; + } + if ((flags & GROUP_SECURITY_INFORMATION) && !print_group(sd, &wptr, NULL)) + { + LocalFree(wstr); + return FALSE; + } + if ((flags & DACL_SECURITY_INFORMATION) && !print_dacl(sd, &wptr, NULL)) + { + LocalFree(wstr); + return FALSE; + } + if ((flags & SACL_SECURITY_INFORMATION) && !print_sacl(sd, &wptr, NULL)) + { + LocalFree(wstr); + return FALSE; + } + *wptr = 0; + + TRACE("ret: %s, %d\n", wine_dbgstr_w(wstr), len); + *string = wstr; + if (ret_len) *ret_len = wcslen(*string) + 1; + return TRUE; +} + +static BOOL get_computer_sid( PSID sid ) +{ + static const struct /* same fields as struct SID */ + { + BYTE Revision; + BYTE SubAuthorityCount; + SID_IDENTIFIER_AUTHORITY IdentifierAuthority; + DWORD SubAuthority[4]; + } computer_sid = + { SID_REVISION, 4, { SECURITY_NT_AUTHORITY }, { SECURITY_NT_NON_UNIQUE, 0, 0, 0 } }; + + memcpy( sid, &computer_sid, sizeof(computer_sid) ); + return TRUE; +} + +static DWORD get_sid_size( const WCHAR *string ) +{ + if (string[0] == 'S' && string[1] == '-') /* S-R-I(-S)+ */ + { + int token_count = 0; + while (*string) + { + if (*string == '-') + token_count++; + string++; + } + + if (token_count >= 3) + return GetSidLengthRequired( token_count - 2 ); + } + else /* String constant format - Only available in winxp and above */ + { + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(well_known_sids); i++) + { + if (!wcsncmp( well_known_sids[i].str, string, 2 )) + return GetSidLengthRequired( well_known_sids[i].sid.SubAuthorityCount ); + } + + for (i = 0; i < ARRAY_SIZE(well_known_rids); i++) + { + if (!wcsncmp( well_known_rids[i].str, string, 2 )) + { + struct max_sid local; + get_computer_sid(&local); + return GetSidLengthRequired( *GetSidSubAuthorityCount(&local) + 1 ); + } + } + } + + return GetSidLengthRequired( 0 ); +} + +static BOOL parse_sid( const WCHAR *string, SID *pisid, DWORD *size ) +{ + while (*string == ' ') + string++; + + *size = get_sid_size( string ); + if (!pisid) /* Simply compute the size */ + return TRUE; + + if (string[0] == 'S' && string[1] == '-') /* S-R-I-S-S */ + { + DWORD i = 0, identAuth; + DWORD csubauth = ((*size - GetSidLengthRequired(0)) / sizeof(DWORD)); + + string += 2; /* Advance to Revision */ + pisid->Revision = wcstoul( string, NULL, 10 ); + + if (pisid->Revision != SDDL_REVISION) + { + TRACE("Revision %d is unknown\n", pisid->Revision); + SetLastError( ERROR_INVALID_SID ); + return FALSE; + } + if (csubauth == 0) + { + TRACE("SubAuthorityCount is 0\n"); + SetLastError( ERROR_INVALID_SID ); + return FALSE; + } + + pisid->SubAuthorityCount = csubauth; + + /* Advance to identifier authority */ + while (*string && *string != '-') + string++; + if (*string == '-') + string++; + + /* MS' implementation can't handle values greater than 2^32 - 1, so + * we don't either; assume most significant bytes are always 0 + */ + pisid->IdentifierAuthority.Value[0] = 0; + pisid->IdentifierAuthority.Value[1] = 0; + identAuth = wcstoul( string, NULL, 10 ); + pisid->IdentifierAuthority.Value[5] = identAuth & 0xff; + pisid->IdentifierAuthority.Value[4] = (identAuth & 0xff00) >> 8; + pisid->IdentifierAuthority.Value[3] = (identAuth & 0xff0000) >> 16; + pisid->IdentifierAuthority.Value[2] = (identAuth & 0xff000000) >> 24; + + /* Advance to first sub authority */ + while (*string && *string != '-') + string++; + if (*string == '-') + string++; + + while (*string) + { + pisid->SubAuthority[i++] = wcstoul( string, NULL, 10 ); + + while (*string && *string != '-') + string++; + if (*string == '-') + string++; + } + + if (i != pisid->SubAuthorityCount) + { + SetLastError( ERROR_INVALID_SID ); + return FALSE; + } + + return TRUE; + } + else /* String constant format - Only available in winxp and above */ + { + unsigned int i; + pisid->Revision = SDDL_REVISION; + + for (i = 0; i < ARRAY_SIZE(well_known_sids); i++) + { + if (!wcsncmp(well_known_sids[i].str, string, 2)) + { + DWORD j; + pisid->SubAuthorityCount = well_known_sids[i].sid.SubAuthorityCount; + pisid->IdentifierAuthority = well_known_sids[i].sid.IdentifierAuthority; + for (j = 0; j < well_known_sids[i].sid.SubAuthorityCount; j++) + pisid->SubAuthority[j] = well_known_sids[i].sid.SubAuthority[j]; + return TRUE; + } + } + + for (i = 0; i < ARRAY_SIZE(well_known_rids); i++) + { + if (!wcsncmp(well_known_rids[i].str, string, 2)) + { + get_computer_sid(pisid); + pisid->SubAuthority[pisid->SubAuthorityCount] = well_known_rids[i].rid; + pisid->SubAuthorityCount++; + return TRUE; + } + } + + FIXME("String constant not supported: %s\n", debugstr_wn(string, 2)); + SetLastError( ERROR_INVALID_SID ); + return FALSE; + } +} + +/****************************************************************************** + * ConvertStringSidToSidW (sechost.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH ConvertStringSidToSidW( const WCHAR *string, PSID *sid ) +{ + DWORD size; + + TRACE("%s, %p\n", debugstr_w(string), sid); + + if (GetVersion() & 0x80000000) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + if (!string || !sid) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (!parse_sid( string, NULL, &size )) + return FALSE; + + *sid = LocalAlloc( 0, size ); + + if (!parse_sid( string, *sid, &size )) + { + LocalFree( *sid ); + return FALSE; + } + return TRUE; +} + +static DWORD parse_acl_flags( const WCHAR **string_ptr ) +{ + DWORD flags = 0; + const WCHAR *string = *string_ptr; + + while (*string && *string != '(') + { + if (*string == 'P') + { + flags |= SE_DACL_PROTECTED; + } + else if (*string == 'A') + { + string++; + if (*string == 'R') + flags |= SE_DACL_AUTO_INHERIT_REQ; + else if (*string == 'I') + flags |= SE_DACL_AUTO_INHERITED; + } + string++; + } + + *string_ptr = string; + return flags; +} + +static BYTE parse_ace_type( const WCHAR **string_ptr ) +{ + static const struct + { + const WCHAR *str; + DWORD value; + } + ace_types[] = + { + { L"AL", SYSTEM_ALARM_ACE_TYPE }, + { L"AU", SYSTEM_AUDIT_ACE_TYPE }, + { L"A", ACCESS_ALLOWED_ACE_TYPE }, + { L"D", ACCESS_DENIED_ACE_TYPE }, + { L"ML", SYSTEM_MANDATORY_LABEL_ACE_TYPE }, + /* + { ACCESS_ALLOWED_OBJECT_ACE_TYPE }, + { ACCESS_DENIED_OBJECT_ACE_TYPE }, + { SYSTEM_ALARM_OBJECT_ACE_TYPE }, + { SYSTEM_AUDIT_OBJECT_ACE_TYPE }, + */ + }; + + const WCHAR *string = *string_ptr; + unsigned int i; + + while (*string == ' ') + string++; + + for (i = 0; i < ARRAY_SIZE(ace_types); ++i) + { + size_t len = wcslen( ace_types[i].str ); + if (!wcsncmp( string, ace_types[i].str, len )) + { + *string_ptr = string + len; + return ace_types[i].value; + } + } + return 0; +} + +static DWORD parse_ace_flag( const WCHAR *string ) +{ + static const struct + { + WCHAR str[3]; + DWORD value; + } + ace_flags[] = + { + { L"CI", CONTAINER_INHERIT_ACE }, + { L"FA", FAILED_ACCESS_ACE_FLAG }, + { L"ID", INHERITED_ACE }, + { L"IO", INHERIT_ONLY_ACE }, + { L"NP", NO_PROPAGATE_INHERIT_ACE }, + { L"OI", OBJECT_INHERIT_ACE }, + { L"SA", SUCCESSFUL_ACCESS_ACE_FLAG }, + }; + + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(ace_flags); ++i) + { + if (!wcsncmp( string, ace_flags[i].str, 2 )) + return ace_flags[i].value; + } + return 0; +} + +static DWORD parse_ace_right( const WCHAR *string ) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(ace_rights); ++i) + { + if (!wcsncmp( string, ace_rights[i].str, 2 )) + return ace_rights[i].value; + } + return 0; +} + +static BYTE parse_ace_flags( const WCHAR **string_ptr ) +{ + const WCHAR *string = *string_ptr; + BYTE flags = 0; + + while (*string == ' ') + string++; + + while (*string != ';') + { + DWORD flag = parse_ace_flag( string ); + if (!flag) return 0; + flags |= flag; + string += 2; + } + + *string_ptr = string; + return flags; +} + +static DWORD parse_ace_rights( const WCHAR **string_ptr ) +{ + DWORD rights = 0; + const WCHAR *string = *string_ptr; + + while (*string == ' ') + string++; + + if (string[0] == '0' && string[1] == 'x') + { + const WCHAR *p = string; + + while (*p && *p != ';') + p++; + + if (p - string <= 10 /* 8 hex digits + "0x" */ ) + { + rights = wcstoul( string, NULL, 16 ); + string = p; + } + else + WARN("Invalid rights string format: %s\n", debugstr_wn(string, p - string)); + } + else + { + while (*string != ';') + { + DWORD right = parse_ace_right( string ); + if (!right) return 0; + rights |= right; + string += 2; + } + } + + *string_ptr = string; + return rights; +} + +static BOOL parse_acl( const WCHAR *string, DWORD *flags, ACL *acl, DWORD *ret_size ) +{ + DWORD val; + DWORD sidlen; + DWORD length = sizeof(ACL); + DWORD acesize = 0; + DWORD acecount = 0; + ACCESS_ALLOWED_ACE *ace = NULL; /* pointer to current ACE */ + + TRACE("%s\n", debugstr_w(string)); + + if (acl) /* ace is only useful if we're setting values */ + ace = (ACCESS_ALLOWED_ACE *)(acl + 1); + + /* Parse ACL flags */ + *flags = parse_acl_flags( &string ); + + /* Parse ACE */ + while (*string == '(') + { + string++; + + /* Parse ACE type */ + val = parse_ace_type( &string ); + if (ace) + ace->Header.AceType = val; + if (*string != ';') + { + SetLastError( RPC_S_INVALID_STRING_UUID ); + return FALSE; + } + string++; + + /* Parse ACE flags */ + val = parse_ace_flags( &string ); + if (ace) + ace->Header.AceFlags = val; + if (*string != ';') + goto err; + string++; + + /* Parse ACE rights */ + val = parse_ace_rights( &string ); + if (ace) + ace->Mask = val; + if (*string != ';') + goto err; + string++; + + /* Parse ACE object guid */ + while (*string == ' ') + string++; + if (*string != ';') + { + FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); + goto err; + } + string++; + + /* Parse ACE inherit object guid */ + while (*string == ' ') + string++; + if (*string != ';') + { + FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n"); + goto err; + } + string++; + + /* Parse ACE account sid */ + if (parse_sid( string, ace ? (SID *)&ace->SidStart : NULL, &sidlen )) + { + while (*string && *string != ')') + string++; + } + + if (*string != ')') + goto err; + string++; + + acesize = sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + sidlen; + length += acesize; + if (ace) + { + ace->Header.AceSize = acesize; + ace = (ACCESS_ALLOWED_ACE *)((BYTE *)ace + acesize); + } + acecount++; + } + + *ret_size = length; + + if (length > 0xffff) + { + ERR("ACL too large\n"); + goto err; + } + + if (acl) + { + acl->AclRevision = ACL_REVISION; + acl->Sbz1 = 0; + acl->AclSize = length; + acl->AceCount = acecount; + acl->Sbz2 = 0; + } + return TRUE; + +err: + SetLastError( ERROR_INVALID_ACL ); + WARN("Invalid ACE string format\n"); + return FALSE; +} + +static BOOL parse_sd( const WCHAR *string, SECURITY_DESCRIPTOR_RELATIVE *sd, DWORD *size) +{ + BOOL ret = FALSE; + WCHAR toktype; + WCHAR *tok; + const WCHAR *lptoken; + BYTE *next = NULL; + DWORD len; + + *size = sizeof(SECURITY_DESCRIPTOR_RELATIVE); + + tok = heap_alloc( (wcslen(string) + 1) * sizeof(WCHAR) ); + if (!tok) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + if (sd) + next = (BYTE *)(sd + 1); + + while (*string == ' ') + string++; + + while (*string) + { + toktype = *string; + + /* Expect char identifier followed by ':' */ + string++; + if (*string != ':') + { + SetLastError( ERROR_INVALID_PARAMETER ); + goto out; + } + string++; + + /* Extract token */ + lptoken = string; + while (*lptoken && *lptoken != ':') + lptoken++; + + if (*lptoken) + lptoken--; + + len = lptoken - string; + memcpy( tok, string, len * sizeof(WCHAR) ); + tok[len] = 0; + + switch (toktype) + { + case 'O': + { + DWORD bytes; + + if (!parse_sid( tok, (SID *)next, &bytes )) + goto out; + + if (sd) + { + sd->Owner = next - (BYTE *)sd; + next += bytes; /* Advance to next token */ + } + + *size += bytes; + + break; + } + + case 'G': + { + DWORD bytes; + + if (!parse_sid( tok, (SID *)next, &bytes )) + goto out; + + if (sd) + { + sd->Group = next - (BYTE *)sd; + next += bytes; /* Advance to next token */ + } + + *size += bytes; + + break; + } + + case 'D': + { + DWORD flags; + DWORD bytes; + + if (!parse_acl( tok, &flags, (ACL *)next, &bytes )) + goto out; + + if (sd) + { + sd->Control |= SE_DACL_PRESENT | flags; + sd->Dacl = next - (BYTE *)sd; + next += bytes; /* Advance to next token */ + } + + *size += bytes; + + break; + } + + case 'S': + { + DWORD flags; + DWORD bytes; + + if (!parse_acl( tok, &flags, (ACL *)next, &bytes )) + goto out; + + if (sd) + { + sd->Control |= SE_SACL_PRESENT | flags; + sd->Sacl = next - (BYTE *)sd; + next += bytes; /* Advance to next token */ + } + + *size += bytes; + + break; + } + + default: + FIXME("Unknown token\n"); + SetLastError( ERROR_INVALID_PARAMETER ); + goto out; + } + + string = lptoken; + } + + ret = TRUE; + +out: + heap_free(tok); + return ret; +} + +/****************************************************************************** + * ConvertStringSecurityDescriptorToSecurityDescriptorW (sechost.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH ConvertStringSecurityDescriptorToSecurityDescriptorW( + const WCHAR *string, DWORD revision, PSECURITY_DESCRIPTOR *sd, ULONG *ret_size ) +{ + DWORD size; + SECURITY_DESCRIPTOR *psd; + + TRACE("%s, %u, %p, %p\n", debugstr_w(string), revision, sd, ret_size); + + if (GetVersion() & 0x80000000) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + if (!string || !sd) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + if (revision != SID_REVISION) + { + SetLastError(ERROR_UNKNOWN_REVISION); + return FALSE; + } + + /* Compute security descriptor length */ + if (!parse_sd( string, NULL, &size )) + return FALSE; + + psd = *sd = LocalAlloc( GMEM_ZEROINIT, size ); + if (!psd) + { + SetLastError( ERROR_NOT_ENOUGH_MEMORY ); + return FALSE; + } + + psd->Revision = SID_REVISION; + psd->Control |= SE_SELF_RELATIVE; + + if (!parse_sd( string, (SECURITY_DESCRIPTOR_RELATIVE *)psd, &size )) + { + LocalFree(psd); + return FALSE; + } + + if (ret_size) *ret_size = size; + return TRUE; +}