reactos/reactos/dll/win32/advapi32/sec/sid.c
Christoph von Wittich c8ee793546 partial advapi32 sid sync to wine 1.1.24
svn path=/trunk/; revision=41568
2009-06-22 22:54:03 +00:00

1945 lines
58 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* WINE COPYRIGHT:
* Copyright 1999, 2000 Juergen Schmied <juergen.schmied@debitel.net>
* Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
* Copyright 2006 Robert Reif
* Copyright 2006 Hervé Poussineau
*
* PROJECT: ReactOS system libraries
* FILE: dll/win32/advapi32/sec/sid.c
* PURPOSE: Security ID functions
*/
#include <advapi32.h>
#include <sddl.h>
#include <wine/debug.h>
#include <wine/unicode.h>
WINE_DEFAULT_DEBUG_CHANNEL(advapi);
#define MAX_GUID_STRING_LEN 39
BOOL WINAPI
AddAuditAccessAceEx(PACL pAcl,
DWORD dwAceRevision,
DWORD AceFlags,
DWORD dwAccessMask,
PSID pSid,
BOOL bAuditSuccess,
BOOL bAuditFailure);
typedef struct RECORD
{
LPCWSTR key;
DWORD value;
} RECORD;
typedef struct _MAX_SID
{
/* same fields as struct _SID */
BYTE Revision;
BYTE SubAuthorityCount;
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
DWORD SubAuthority[SID_MAX_SUB_AUTHORITIES];
} MAX_SID;
typedef struct WELLKNOWNSID
{
WCHAR wstr[2];
WELL_KNOWN_SID_TYPE Type;
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 } } },
{ {'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 } } },
{ {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 } } },
{ {'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 } } },
};
typedef struct WELLKNOWNRID
{
WELL_KNOWN_SID_TYPE Type;
DWORD Rid;
} WELLKNOWNRID;
static const WELLKNOWNRID WellKnownRids[] = {
{ WinAccountAdministratorSid, DOMAIN_USER_RID_ADMIN },
{ WinAccountGuestSid, DOMAIN_USER_RID_GUEST },
{ WinAccountKrbtgtSid, DOMAIN_USER_RID_KRBTGT },
{ WinAccountDomainAdminsSid, DOMAIN_GROUP_RID_ADMINS },
{ WinAccountDomainUsersSid, DOMAIN_GROUP_RID_USERS },
{ WinAccountDomainGuestsSid, DOMAIN_GROUP_RID_GUESTS },
{ WinAccountComputersSid, DOMAIN_GROUP_RID_COMPUTERS },
{ WinAccountControllersSid, DOMAIN_GROUP_RID_CONTROLLERS },
{ WinAccountCertAdminsSid, DOMAIN_GROUP_RID_CERT_ADMINS },
{ WinAccountSchemaAdminsSid, DOMAIN_GROUP_RID_SCHEMA_ADMINS },
{ WinAccountEnterpriseAdminsSid, DOMAIN_GROUP_RID_ENTERPRISE_ADMINS },
{ WinAccountPolicyAdminsSid, DOMAIN_GROUP_RID_POLICY_ADMINS },
{ WinAccountRasAndIasServersSid, DOMAIN_ALIAS_RID_RAS_SERVERS },
};
static const SID sidWorld = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
/*
* ACE types
*/
static const WCHAR SDDL_ACCESS_ALLOWED[] = {'A',0};
static const WCHAR SDDL_ACCESS_DENIED[] = {'D',0};
static const WCHAR SDDL_OBJECT_ACCESS_ALLOWED[] = {'O','A',0};
static const WCHAR SDDL_OBJECT_ACCESS_DENIED[] = {'O','D',0};
static const WCHAR SDDL_AUDIT[] = {'A','U',0};
static const WCHAR SDDL_ALARM[] = {'A','L',0};
static const WCHAR SDDL_OBJECT_AUDIT[] = {'O','U',0};
static const WCHAR SDDL_OBJECT_ALARM[] = {'O','L',0};
/*
* SDDL ADS Rights
*/
#define ADS_RIGHT_DS_CREATE_CHILD 0x0001
#define ADS_RIGHT_DS_DELETE_CHILD 0x0002
#define ADS_RIGHT_ACTRL_DS_LIST 0x0004
#define ADS_RIGHT_DS_SELF 0x0008
#define ADS_RIGHT_DS_READ_PROP 0x0010
#define ADS_RIGHT_DS_WRITE_PROP 0x0020
#define ADS_RIGHT_DS_DELETE_TREE 0x0040
#define ADS_RIGHT_DS_LIST_OBJECT 0x0080
#define ADS_RIGHT_DS_CONTROL_ACCESS 0x0100
/*
* 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};
static const char * debugstr_sid(PSID sid)
{
int auth = 0;
SID * psid = (SID *)sid;
if (psid == NULL)
return "(null)";
auth = psid->IdentifierAuthority.Value[5] +
(psid->IdentifierAuthority.Value[4] << 8) +
(psid->IdentifierAuthority.Value[3] << 16) +
(psid->IdentifierAuthority.Value[2] << 24);
switch (psid->SubAuthorityCount) {
case 0:
return wine_dbg_sprintf("S-%d-%d", psid->Revision, auth);
case 1:
return wine_dbg_sprintf("S-%d-%d-%lu", psid->Revision, auth,
psid->SubAuthority[0]);
case 2:
return wine_dbg_sprintf("S-%d-%d-%lu-%lu", psid->Revision, auth,
psid->SubAuthority[0], psid->SubAuthority[1]);
case 3:
return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu", psid->Revision, auth,
psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2]);
case 4:
return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu", psid->Revision, auth,
psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
psid->SubAuthority[3]);
case 5:
return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
psid->SubAuthority[3], psid->SubAuthority[4]);
case 6:
return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
psid->SubAuthority[3], psid->SubAuthority[1], psid->SubAuthority[2],
psid->SubAuthority[0], psid->SubAuthority[4], psid->SubAuthority[5]);
case 7:
return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
psid->SubAuthority[6]);
case 8:
return wine_dbg_sprintf("S-%d-%d-%lu-%lu-%lu-%lu-%lu-%lu-%lu-%lu", psid->Revision, auth,
psid->SubAuthority[0], psid->SubAuthority[1], psid->SubAuthority[2],
psid->SubAuthority[3], psid->SubAuthority[4], psid->SubAuthority[5],
psid->SubAuthority[6], psid->SubAuthority[7]);
}
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 )
{
if (status) SetLastError( RtlNtStatusToDosError( status ));
return !status;
}
/* Exported functions */
/*
* @implemented
*/
BOOL WINAPI
AllocateLocallyUniqueId(PLUID Luid)
{
NTSTATUS Status;
Status = NtAllocateLocallyUniqueId (Luid);
if (!NT_SUCCESS (Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL WINAPI
AllocateAndInitializeSid(PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
BYTE nSubAuthorityCount,
DWORD dwSubAuthority0,
DWORD dwSubAuthority1,
DWORD dwSubAuthority2,
DWORD dwSubAuthority3,
DWORD dwSubAuthority4,
DWORD dwSubAuthority5,
DWORD dwSubAuthority6,
DWORD dwSubAuthority7,
PSID *pSid)
{
NTSTATUS Status;
Status = RtlAllocateAndInitializeSid(pIdentifierAuthority,
nSubAuthorityCount,
dwSubAuthority0,
dwSubAuthority1,
dwSubAuthority2,
dwSubAuthority3,
dwSubAuthority4,
dwSubAuthority5,
dwSubAuthority6,
dwSubAuthority7,
pSid);
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL WINAPI
CopySid(DWORD nDestinationSidLength,
PSID pDestinationSid,
PSID pSourceSid)
{
NTSTATUS Status;
Status = RtlCopySid(nDestinationSidLength,
pDestinationSid,
pSourceSid);
if (!NT_SUCCESS (Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
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 = 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.@]
* @implemented
*/
BOOL WINAPI
ConvertSecurityDescriptorToStringSecurityDescriptorW(PSECURITY_DESCRIPTOR SecurityDescriptor,
DWORD SDRevision,
SECURITY_INFORMATION SecurityInformation,
LPWSTR *OutputString,
PULONG OutputLen)
{
ULONG len;
WCHAR *wptr, *wstr;
if (SDRevision != SDDL_REVISION_1)
{
ERR("Pogram requested unknown SDDL revision %d\n", SDRevision);
SetLastError(ERROR_UNKNOWN_REVISION);
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;
}
/******************************************************************************
* ConvertSecurityDescriptorToStringSecurityDescriptorA [ADVAPI32.@]
* @implemented
*/
BOOL WINAPI
ConvertSecurityDescriptorToStringSecurityDescriptorA(PSECURITY_DESCRIPTOR SecurityDescriptor,
DWORD SDRevision,
SECURITY_INFORMATION Information,
LPSTR *OutputString,
PULONG OutputLen)
{
LPWSTR wstr;
ULONG len;
if (ConvertSecurityDescriptorToStringSecurityDescriptorW(SecurityDescriptor, SDRevision, Information, &wstr, &len))
{
int lenA;
lenA = WideCharToMultiByte(CP_ACP, 0, wstr, len, NULL, 0, NULL, NULL);
*OutputString = HeapAlloc(GetProcessHeap(), 0, lenA);
WideCharToMultiByte(CP_ACP, 0, wstr, len, *OutputString, lenA, NULL, NULL);
LocalFree(wstr);
if (OutputLen != NULL)
*OutputLen = lenA;
return TRUE;
}
else
{
*OutputString = NULL;
if (OutputLen)
*OutputLen = 0;
return FALSE;
}
}
/******************************************************************************
* 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 < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++)
if (!strncmpW(WellKnownSids[i].wstr, StringSid, 2))
return GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
}
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;
}
*cBytes = ComputeStringSidSize(StringSid);
if (!pisid) /* Simply compute the size */
{
TRACE("only size requested, returning TRUE\n");
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 < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); 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;
}
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;
}
/******************************************************************************
* ParseAclStringFlags
*/
static DWORD ParseAclStringFlags(LPCWSTR* StringAcl)
{
DWORD flags = 0;
LPCWSTR szAcl = *StringAcl;
while (*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_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 (lpaf->wstr &&
(len = strlenW(lpaf->wstr)) &&
strncmpW(lpaf->wstr, szAcl, len))
lpaf++;
if (!lpaf->wstr)
return 0;
*StringAcl += 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 != ';')
{
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 DWORD ParseAceStringRights(LPCWSTR* StringAcl)
{
UINT len = 0;
DWORD rights = 0;
LPCWSTR szAcl = *StringAcl;
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 */
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 != ';')
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 */
if (*StringAcl != ';')
{
FIXME("Support for *_OBJECT_ACE_TYPE not implemented\n");
goto lerr;
}
StringAcl++;
/* Parse ACE inherit object guid */
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_INVALID_ACL);
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[MAX_PATH];
LPCWSTR lptoken;
LPBYTE lpNext = NULL;
DWORD len;
*cBytes = sizeof(SECURITY_DESCRIPTOR);
if (SecurityDescriptor)
lpNext = (LPBYTE)(SecurityDescriptor + 1);
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:
return bret;
}
/******************************************************************************
* ConvertStringSecurityDescriptorToSecurityDescriptorW [ADVAPI32.@]
* @implemented
*/
BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorW(
LPCWSTR StringSecurityDescriptor,
DWORD StringSDRevision,
PSECURITY_DESCRIPTOR* SecurityDescriptor,
PULONG SecurityDescriptorSize)
{
DWORD cBytes;
SECURITY_DESCRIPTOR* psd;
BOOL bret = FALSE;
TRACE("%s\n", debugstr_w(StringSecurityDescriptor));
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;
}
/* Winehq cvs 20050916 */
/******************************************************************************
* ConvertStringSecurityDescriptorToSecurityDescriptorA [ADVAPI32.@]
* @implemented
*/
BOOL WINAPI ConvertStringSecurityDescriptorToSecurityDescriptorA(
LPCSTR StringSecurityDescriptor,
DWORD StringSDRevision,
PSECURITY_DESCRIPTOR* SecurityDescriptor,
PULONG SecurityDescriptorSize)
{
UINT len;
BOOL ret = FALSE;
LPWSTR StringSecurityDescriptorW;
len = MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, NULL, 0);
StringSecurityDescriptorW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
if (StringSecurityDescriptorW)
{
MultiByteToWideChar(CP_ACP, 0, StringSecurityDescriptor, -1, StringSecurityDescriptorW, len);
ret = ConvertStringSecurityDescriptorToSecurityDescriptorW(StringSecurityDescriptorW,
StringSDRevision, SecurityDescriptor,
SecurityDescriptorSize);
HeapFree(GetProcessHeap(), 0, StringSecurityDescriptorW);
}
return ret;
}
/*
* @implemented
*/
BOOL WINAPI
EqualPrefixSid(PSID pSid1,
PSID pSid2)
{
return RtlEqualPrefixSid (pSid1, pSid2);
}
/*
* @implemented
*/
BOOL WINAPI
EqualSid(PSID pSid1,
PSID pSid2)
{
return RtlEqualSid (pSid1, pSid2);
}
/*
* @implemented
*
* RETURNS
* Docs says this function does NOT return a value
* even thou it's defined to return a PVOID...
*/
PVOID WINAPI
FreeSid(PSID pSid)
{
return RtlFreeSid(pSid);
}
/*
* @implemented
*/
DWORD WINAPI
GetLengthSid(PSID pSid)
{
return (DWORD)RtlLengthSid(pSid);
}
/*
* @implemented
*/
PSID_IDENTIFIER_AUTHORITY WINAPI
GetSidIdentifierAuthority(PSID pSid)
{
return RtlIdentifierAuthoritySid(pSid);
}
/*
* @implemented
*/
DWORD WINAPI
GetSidLengthRequired(UCHAR nSubAuthorityCount)
{
return (DWORD)RtlLengthRequiredSid(nSubAuthorityCount);
}
/*
* @implemented
*/
PDWORD WINAPI
GetSidSubAuthority(PSID pSid,
DWORD nSubAuthority)
{
return (PDWORD)RtlSubAuthoritySid(pSid, nSubAuthority);
}
/*
* @implemented
*/
PUCHAR WINAPI
GetSidSubAuthorityCount(PSID pSid)
{
return RtlSubAuthorityCountSid(pSid);
}
/*
* @implemented
*/
BOOL WINAPI
InitializeSid(PSID Sid,
PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
BYTE nSubAuthorityCount)
{
NTSTATUS Status;
Status = RtlInitializeSid(Sid,
pIdentifierAuthority,
nSubAuthorityCount);
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
return TRUE;
}
/*
* @implemented
*/
BOOL WINAPI
IsValidSid(PSID pSid)
{
return (BOOL)RtlValidSid(pSid);
}
/*
* @implemented
*/
BOOL WINAPI
ConvertSidToStringSidW(PSID Sid,
LPWSTR *StringSid)
{
NTSTATUS Status;
UNICODE_STRING UnicodeString;
WCHAR FixedBuffer[64];
if (!RtlValidSid(Sid))
{
SetLastError(ERROR_INVALID_SID);
return FALSE;
}
UnicodeString.Length = 0;
UnicodeString.MaximumLength = sizeof(FixedBuffer);
UnicodeString.Buffer = FixedBuffer;
Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, FALSE);
if (STATUS_BUFFER_TOO_SMALL == Status)
{
Status = RtlConvertSidToUnicodeString(&UnicodeString, Sid, TRUE);
}
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
return FALSE;
}
*StringSid = LocalAlloc(LMEM_FIXED, UnicodeString.Length + sizeof(WCHAR));
if (NULL == *StringSid)
{
if (UnicodeString.Buffer != FixedBuffer)
{
RtlFreeUnicodeString(&UnicodeString);
}
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
MoveMemory(*StringSid, UnicodeString.Buffer, UnicodeString.Length);
ZeroMemory((PCHAR) *StringSid + UnicodeString.Length, sizeof(WCHAR));
if (UnicodeString.Buffer != FixedBuffer)
{
RtlFreeUnicodeString(&UnicodeString);
}
return TRUE;
}
/*
* @implemented
*/
BOOL WINAPI
ConvertSidToStringSidA(PSID Sid,
LPSTR *StringSid)
{
LPWSTR StringSidW;
int Len;
if (!ConvertSidToStringSidW(Sid, &StringSidW))
{
return FALSE;
}
Len = WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, NULL, 0, NULL, NULL);
if (Len <= 0)
{
LocalFree(StringSidW);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
*StringSid = LocalAlloc(LMEM_FIXED, Len);
if (NULL == *StringSid)
{
LocalFree(StringSidW);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
if (!WideCharToMultiByte(CP_ACP, 0, StringSidW, -1, *StringSid, Len, NULL, NULL))
{
LocalFree(StringSid);
LocalFree(StringSidW);
return FALSE;
}
LocalFree(StringSidW);
return TRUE;
}
/*
* @unimplemented
*/
BOOL WINAPI
EqualDomainSid(IN PSID pSid1,
IN PSID pSid2,
OUT BOOL* pfEqual)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
BOOL WINAPI
GetWindowsAccountDomainSid(IN PSID pSid,
OUT PSID ppDomainSid,
IN OUT DWORD* cbSid)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
BOOL WINAPI
CreateWellKnownSid(IN WELL_KNOWN_SID_TYPE WellKnownSidType,
IN PSID DomainSid OPTIONAL,
OUT PSID pSid,
IN OUT DWORD* cbSid)
{
unsigned int i;
TRACE("(%d, %s, %p, %p)\n", WellKnownSidType, debugstr_sid(DomainSid), pSid, cbSid);
if (cbSid == NULL || (DomainSid && !IsValidSid(DomainSid)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
for (i = 0; i < sizeof(WellKnownSids)/sizeof(WellKnownSids[0]); i++) {
if (WellKnownSids[i].Type == WellKnownSidType) {
DWORD length = GetSidLengthRequired(WellKnownSids[i].Sid.SubAuthorityCount);
if (*cbSid < length)
{
*cbSid = length;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
if (!pSid)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
CopyMemory(pSid, &WellKnownSids[i].Sid.Revision, length);
*cbSid = length;
return TRUE;
}
}
if (DomainSid == NULL || *GetSidSubAuthorityCount(DomainSid) == SID_MAX_SUB_AUTHORITIES)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
for (i = 0; i < sizeof(WellKnownRids)/sizeof(WellKnownRids[0]); i++)
if (WellKnownRids[i].Type == WellKnownSidType) {
UCHAR domain_subauth = *GetSidSubAuthorityCount(DomainSid);
DWORD domain_sid_length = GetSidLengthRequired(domain_subauth);
DWORD output_sid_length = GetSidLengthRequired(domain_subauth + 1);
if (*cbSid < output_sid_length)
{
*cbSid = output_sid_length;
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
if (!pSid)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
CopyMemory(pSid, DomainSid, domain_sid_length);
(*GetSidSubAuthorityCount(pSid))++;
(*GetSidSubAuthority(pSid, domain_subauth)) = WellKnownRids[i].Rid;
*cbSid = output_sid_length;
return TRUE;
}
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/*
* @unimplemented
*/
BOOL WINAPI
IsWellKnownSid(IN PSID pSid,
IN WELL_KNOWN_SID_TYPE WellKnownSidType)
{
unsigned int i;
TRACE("(%s, %d)\n", debugstr_sid(pSid), WellKnownSidType);
for (i = 0; i < sizeof(WellKnownSids) / sizeof(WellKnownSids[0]); i++)
{
if (WellKnownSids[i].Type == WellKnownSidType)
{
if (EqualSid(pSid, (PSID)((ULONG_PTR)&WellKnownSids[i].Sid.Revision)))
return TRUE;
}
}
return FALSE;
}
/*
* @implemented
*/
BOOL WINAPI
ConvertStringSidToSidA(IN LPCSTR StringSid,
OUT PSID* sid)
{
BOOL bRetVal = FALSE;
if (!StringSid || !sid)
SetLastError(ERROR_INVALID_PARAMETER);
else
{
UINT len = MultiByteToWideChar(CP_ACP, 0, StringSid, -1, NULL, 0);
LPWSTR wStringSid = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, StringSid, - 1, wStringSid, len);
bRetVal = ConvertStringSidToSidW(wStringSid, sid);
HeapFree(GetProcessHeap(), 0, wStringSid);
}
return bRetVal;
}
static const RECORD SidTable[] =
{
{ SDDL_ACCOUNT_OPERATORS, WinBuiltinAccountOperatorsSid },
{ SDDL_ALIAS_PREW2KCOMPACC, WinBuiltinPreWindows2000CompatibleAccessSid },
{ SDDL_ANONYMOUS, WinAnonymousSid },
{ SDDL_AUTHENTICATED_USERS, WinAuthenticatedUserSid },
{ SDDL_BUILTIN_ADMINISTRATORS, WinBuiltinAdministratorsSid },
{ SDDL_BUILTIN_GUESTS, WinBuiltinGuestsSid },
{ SDDL_BACKUP_OPERATORS, WinBuiltinBackupOperatorsSid },
{ SDDL_BUILTIN_USERS, WinBuiltinUsersSid },
{ SDDL_CERT_SERV_ADMINISTRATORS, WinAccountCertAdminsSid /* FIXME: DOMAIN_GROUP_RID_CERT_ADMINS */ },
{ SDDL_CREATOR_GROUP, WinCreatorGroupSid },
{ SDDL_CREATOR_OWNER, WinCreatorOwnerSid },
{ SDDL_DOMAIN_ADMINISTRATORS, WinAccountDomainAdminsSid /* FIXME: DOMAIN_GROUP_RID_ADMINS */ },
{ SDDL_DOMAIN_COMPUTERS, WinAccountComputersSid /* FIXME: DOMAIN_GROUP_RID_COMPUTERS */ },
{ SDDL_DOMAIN_DOMAIN_CONTROLLERS, WinAccountControllersSid /* FIXME: DOMAIN_GROUP_RID_CONTROLLERS */ },
{ SDDL_DOMAIN_GUESTS, WinAccountDomainGuestsSid /* FIXME: DOMAIN_GROUP_RID_GUESTS */ },
{ SDDL_DOMAIN_USERS, WinAccountDomainUsersSid /* FIXME: DOMAIN_GROUP_RID_USERS */ },
{ SDDL_ENTERPRISE_ADMINS, WinAccountEnterpriseAdminsSid /* FIXME: DOMAIN_GROUP_RID_ENTERPRISE_ADMINS */ },
{ SDDL_ENTERPRISE_DOMAIN_CONTROLLERS, WinLogonIdsSid /* FIXME: SECURITY_SERVER_LOGON_RID */ },
{ SDDL_EVERYONE, WinWorldSid },
{ SDDL_GROUP_POLICY_ADMINS, WinAccountPolicyAdminsSid /* FIXME: DOMAIN_GROUP_RID_POLICY_ADMINS */ },
{ SDDL_INTERACTIVE, WinInteractiveSid },
{ SDDL_LOCAL_ADMIN, WinAccountAdministratorSid /* FIXME: DOMAIN_USER_RID_ADMIN */ },
{ SDDL_LOCAL_GUEST, WinAccountGuestSid /* FIXME: DOMAIN_USER_RID_GUEST */ },
{ SDDL_LOCAL_SERVICE, WinLocalServiceSid },
{ SDDL_LOCAL_SYSTEM, WinLocalSystemSid },
{ SDDL_NETWORK, WinNetworkSid },
{ SDDL_NETWORK_CONFIGURATION_OPS, WinBuiltinNetworkConfigurationOperatorsSid },
{ SDDL_NETWORK_SERVICE, WinNetworkServiceSid },
{ SDDL_PRINTER_OPERATORS, WinBuiltinPrintOperatorsSid },
{ SDDL_PERSONAL_SELF, WinSelfSid },
{ SDDL_POWER_USERS, WinBuiltinPowerUsersSid },
{ SDDL_RAS_SERVERS, WinAccountRasAndIasServersSid /* FIXME: DOMAIN_ALIAS_RID_RAS_SERVERS */ },
{ SDDL_REMOTE_DESKTOP, WinBuiltinRemoteDesktopUsersSid },
{ SDDL_REPLICATOR, WinBuiltinReplicatorSid },
{ SDDL_RESTRICTED_CODE, WinRestrictedCodeSid },
{ SDDL_SCHEMA_ADMINISTRATORS, WinAccountSchemaAdminsSid /* FIXME: DOMAIN_GROUP_RID_SCHEMA_ADMINS */ },
{ SDDL_SERVER_OPERATORS, WinBuiltinSystemOperatorsSid },
{ SDDL_SERVICE, WinServiceSid },
{ NULL, 0 },
};
/*
* @implemented
*/
BOOL WINAPI
ConvertStringSidToSidW(IN LPCWSTR StringSid,
OUT PSID* sid)
{
DWORD size;
DWORD i, cBytes, identAuth, csubauth;
BOOL ret;
SID* pisid;
TRACE("%s %p\n", debugstr_w(StringSid), sid);
if (!StringSid)
{
SetLastError(ERROR_INVALID_SID);
return FALSE;
}
for (i = 0; i < sizeof(SidTable) / sizeof(SidTable[0]) - 1; i++)
{
if (wcscmp(StringSid, SidTable[i].key) == 0)
{
WELL_KNOWN_SID_TYPE knownSid = (WELL_KNOWN_SID_TYPE)SidTable[i].value;
size = SECURITY_MAX_SID_SIZE;
*sid = LocalAlloc(0, size);
if (!*sid)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
ret = CreateWellKnownSid(
knownSid,
NULL,
*sid,
&size);
if (!ret)
{
SetLastError(ERROR_INVALID_SID);
LocalFree(*sid);
}
return ret;
}
}
/* That's probably a string S-R-I-S-S... */
if (StringSid[0] != 'S' || StringSid[1] != '-')
{
SetLastError(ERROR_INVALID_SID);
return FALSE;
}
cBytes = ComputeStringSidSize(StringSid);
pisid = (SID*)LocalAlloc( 0, cBytes );
if (!pisid)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
i = 0;
ret = FALSE;
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++;
pisid->SubAuthority[i] = atoiW(StringSid);
while (*StringSid)
{
while (*StringSid && *StringSid != '-')
StringSid++;
if (*StringSid == '-')
StringSid++;
pisid->SubAuthority[++i] = atoiW(StringSid);
}
if (i != pisid->SubAuthorityCount)
goto lend; /* ERROR_INVALID_SID */
*sid = pisid;
ret = TRUE;
lend:
if (!ret)
SetLastError(ERROR_INVALID_SID);
TRACE("returning %s\n", ret ? "TRUE" : "FALSE");
return ret;
}
/* EOF */