You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1588 lines
47 KiB
1588 lines
47 KiB
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 1995 - 1996
|
|
//
|
|
// File: tcertpro.cpp
|
|
//
|
|
// Contents: Cert Protection Tests
|
|
//
|
|
// See Usage() for a list of test options.
|
|
//
|
|
//
|
|
// Functions: main
|
|
//
|
|
// History: 30-Nov-97 philh created
|
|
//--------------------------------------------------------------------------
|
|
|
|
|
|
#include <windows.h>
|
|
#include <assert.h>
|
|
#include "wincrypt.h"
|
|
#include "certtest.h"
|
|
#include "unicode.h"
|
|
#include "certprot.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <memory.h>
|
|
#include <time.h>
|
|
|
|
static void PrintLastError(LPCSTR pszMsg, LONG lErr)
|
|
{
|
|
printf(" %s failed => 0x%x (%d) \n", pszMsg, lErr, lErr);
|
|
}
|
|
|
|
static void PrintLastError(LPCSTR pszMsg)
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
printf(" %s failed => 0x%x (%d) \n", pszMsg, dwErr, dwErr);
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
SetPrivilege(
|
|
HANDLE hToken, // token handle
|
|
LPCSTR Privilege, // Privilege to enable/disable
|
|
BOOL bEnablePrivilege // to enable or disable privilege
|
|
)
|
|
{
|
|
TOKEN_PRIVILEGES tp;
|
|
LUID luid;
|
|
TOKEN_PRIVILEGES tpPrevious;
|
|
DWORD cbPrevious=sizeof(TOKEN_PRIVILEGES);
|
|
|
|
if(!LookupPrivilegeValueA( NULL, Privilege, &luid )) return FALSE;
|
|
|
|
//
|
|
// first pass. get current privilege setting
|
|
//
|
|
tp.PrivilegeCount = 1;
|
|
tp.Privileges[0].Luid = luid;
|
|
tp.Privileges[0].Attributes = 0;
|
|
|
|
AdjustTokenPrivileges(
|
|
hToken,
|
|
FALSE,
|
|
&tp,
|
|
sizeof(TOKEN_PRIVILEGES),
|
|
&tpPrevious,
|
|
&cbPrevious
|
|
);
|
|
|
|
if (GetLastError() != ERROR_SUCCESS) return FALSE;
|
|
|
|
//
|
|
// second pass. set privilege based on previous setting
|
|
//
|
|
tpPrevious.PrivilegeCount = 1;
|
|
tpPrevious.Privileges[0].Luid = luid;
|
|
|
|
if(bEnablePrivilege) {
|
|
tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
|
|
}
|
|
else {
|
|
tpPrevious.Privileges[0].Attributes ^= (SE_PRIVILEGE_ENABLED &
|
|
tpPrevious.Privileges[0].Attributes);
|
|
}
|
|
|
|
AdjustTokenPrivileges(
|
|
hToken,
|
|
FALSE,
|
|
&tpPrevious,
|
|
cbPrevious,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
if (GetLastError() != ERROR_SUCCESS) return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
SetCurrentPrivilege(
|
|
LPCSTR Privilege, // Privilege to enable/disable
|
|
BOOL bEnablePrivilege // to enable or disable privilege
|
|
)
|
|
{
|
|
BOOL bSuccess=FALSE; // assume failure
|
|
HANDLE hToken;
|
|
|
|
if(OpenProcessToken(
|
|
GetCurrentProcess(),
|
|
TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
|
&hToken
|
|
))
|
|
{
|
|
|
|
if(SetPrivilege(hToken, Privilege, bEnablePrivilege)) bSuccess=TRUE;
|
|
|
|
CloseHandle(hToken);
|
|
}
|
|
|
|
return bSuccess;
|
|
}
|
|
|
|
|
|
static void Usage(void)
|
|
{
|
|
printf("Usage: tcertpro [options] <TestName> <RegPath>\n");
|
|
printf("Options are:\n");
|
|
printf(" -h - This message\n");
|
|
// printf(" -r - Recurse subkeys\n");
|
|
printf(" -lCU - CurrentUser (default)\n");
|
|
printf(" -lLM - LocalMachine\n");
|
|
printf("TestNames (case insensitive):\n");
|
|
printf(" GetKey - Get Registry Key Security Information\n");
|
|
printf(" SetKey - Set Registry Key Security Information\n");
|
|
printf(" PurgeLMRoots - Purge LocalMachine Roots From CurrentUser\n");
|
|
printf(" DeleteUnknownRoots - Delete Unknown Roots From Protected List\n");
|
|
printf(" CheckProtectedRoots - Check ProtectedRoots ACLs\n");
|
|
printf(" ServiceUI - Cert protect service UI\n");
|
|
printf(" ServiceTokenInfo - Get Cert protect service token info\n");
|
|
printf(" ServiceInvalid - Invalid Cert protect function\n");
|
|
printf("\n");
|
|
}
|
|
|
|
#if 0
|
|
#define OWNER_SECURITY_INFORMATION (0X00000001L)
|
|
#define GROUP_SECURITY_INFORMATION (0X00000002L)
|
|
#define DACL_SECURITY_INFORMATION (0X00000004L)
|
|
#define SACL_SECURITY_INFORMATION (0X00000008L)
|
|
#endif
|
|
|
|
|
|
static PSECURITY_DESCRIPTOR AllocAndGetSecurityDescriptor(
|
|
IN HKEY hKey,
|
|
SECURITY_INFORMATION SecInf
|
|
)
|
|
{
|
|
LONG err;
|
|
PSECURITY_DESCRIPTOR psd = NULL;
|
|
DWORD cbsd = 0;
|
|
|
|
err = RegGetKeySecurity(
|
|
hKey,
|
|
SecInf,
|
|
NULL, // psd
|
|
&cbsd
|
|
);
|
|
if (!(ERROR_SUCCESS == err || ERROR_INSUFFICIENT_BUFFER == err)) {
|
|
PrintLastError("RegGetKeySecurity", err);
|
|
return NULL;
|
|
}
|
|
if (0 == cbsd)
|
|
return NULL;
|
|
|
|
if (NULL == (psd = (PSECURITY_DESCRIPTOR) TestAlloc(cbsd)))
|
|
return NULL;
|
|
|
|
if (ERROR_SUCCESS != (err = RegGetKeySecurity(
|
|
hKey,
|
|
SecInf,
|
|
psd,
|
|
&cbsd
|
|
))) {
|
|
PrintLastError("RegGetKeySecurity", err);
|
|
TestFree(psd);
|
|
}
|
|
return psd;
|
|
}
|
|
|
|
#if 0
|
|
#define SE_OWNER_DEFAULTED (0x0001)
|
|
#define SE_GROUP_DEFAULTED (0x0002)
|
|
#define SE_DACL_PRESENT (0x0004)
|
|
#define SE_DACL_DEFAULTED (0x0008)
|
|
#define SE_SACL_PRESENT (0x0010)
|
|
#define SE_SACL_DEFAULTED (0x0020)
|
|
#define SE_DACL_AUTO_INHERIT_REQ (0x0100)
|
|
#define SE_SACL_AUTO_INHERIT_REQ (0x0200)
|
|
#define SE_DACL_AUTO_INHERITED (0x0400)
|
|
#define SE_SACL_AUTO_INHERITED (0x0800)
|
|
#define SE_DACL_PROTECTED (0x1000)
|
|
#define SE_SACL_PROTECTED (0x2000)
|
|
#define SE_SELF_RELATIVE (0x8000)
|
|
#endif
|
|
|
|
//
|
|
// Where:
|
|
//
|
|
// SE_OWNER_DEFAULTED - This boolean flag, when set, indicates that the
|
|
// SID pointed to by the Owner field was provided by a
|
|
// defaulting mechanism rather than explicitly provided by the
|
|
// original provider of the security descriptor. This may
|
|
// affect the treatment of the SID with respect to inheritence
|
|
// of an owner.
|
|
//
|
|
// SE_GROUP_DEFAULTED - This boolean flag, when set, indicates that the
|
|
// SID in the Group field was provided by a defaulting mechanism
|
|
// rather than explicitly provided by the original provider of
|
|
// the security descriptor. This may affect the treatment of
|
|
// the SID with respect to inheritence of a primary group.
|
|
//
|
|
// SE_DACL_PRESENT - This boolean flag, when set, indicates that the
|
|
// security descriptor contains a discretionary ACL. If this
|
|
// flag is set and the Dacl field of the SECURITY_DESCRIPTOR is
|
|
// null, then a null ACL is explicitly being specified.
|
|
//
|
|
// SE_DACL_DEFAULTED - This boolean flag, when set, indicates that the
|
|
// ACL pointed to by the Dacl field was provided by a defaulting
|
|
// mechanism rather than explicitly provided by the original
|
|
// provider of the security descriptor. This may affect the
|
|
// treatment of the ACL with respect to inheritence of an ACL.
|
|
// This flag is ignored if the DaclPresent flag is not set.
|
|
//
|
|
// SE_SACL_PRESENT - This boolean flag, when set, indicates that the
|
|
// security descriptor contains a system ACL pointed to by the
|
|
// Sacl field. If this flag is set and the Sacl field of the
|
|
// SECURITY_DESCRIPTOR is null, then an empty (but present)
|
|
// ACL is being specified.
|
|
//
|
|
// SE_SACL_DEFAULTED - This boolean flag, when set, indicates that the
|
|
// ACL pointed to by the Sacl field was provided by a defaulting
|
|
// mechanism rather than explicitly provided by the original
|
|
// provider of the security descriptor. This may affect the
|
|
// treatment of the ACL with respect to inheritence of an ACL.
|
|
// This flag is ignored if the SaclPresent flag is not set.
|
|
//
|
|
// SE_SELF_RELATIVE - This boolean flag, when set, indicates that the
|
|
// security descriptor is in self-relative form. In this form,
|
|
// all fields of the security descriptor are contiguous in memory
|
|
// and all pointer fields are expressed as offsets from the
|
|
// beginning of the security descriptor. This form is useful
|
|
// for treating security descriptors as opaque data structures
|
|
// for transmission in communication protocol or for storage on
|
|
// secondary media.
|
|
//
|
|
|
|
#if 0
|
|
typedef enum _SID_NAME_USE {
|
|
SidTypeUser = 1,
|
|
SidTypeGroup,
|
|
SidTypeDomain,
|
|
SidTypeAlias,
|
|
SidTypeWellKnownGroup,
|
|
SidTypeDeletedAccount,
|
|
SidTypeInvalid,
|
|
SidTypeUnknown
|
|
} SID_NAME_USE, *PSID_NAME_USE;
|
|
#endif
|
|
|
|
static void DisplayControl(
|
|
PSECURITY_DESCRIPTOR psd
|
|
)
|
|
{
|
|
SECURITY_DESCRIPTOR_CONTROL sdc;
|
|
DWORD dwRevision;
|
|
|
|
if (!GetSecurityDescriptorControl(psd, &sdc, &dwRevision))
|
|
PrintLastError("GetSecurityDescriptorControl");
|
|
else {
|
|
printf(" Control: 0x%x", sdc);
|
|
if (sdc & SE_OWNER_DEFAULTED)
|
|
printf(" OWNER_DEFAULTED");
|
|
if (sdc & SE_GROUP_DEFAULTED)
|
|
printf(" GROUP_DEFAULTED");
|
|
if (sdc & SE_DACL_PRESENT)
|
|
printf(" DACL_PRESENT");
|
|
if (sdc & SE_DACL_DEFAULTED)
|
|
printf(" DACL_DEFAULTED");
|
|
if (sdc & SE_SACL_PRESENT)
|
|
printf(" SACL_PRESENT");
|
|
if (sdc & SE_SACL_DEFAULTED)
|
|
printf(" SACL_DEFAULTED");
|
|
if (sdc & SE_DACL_AUTO_INHERIT_REQ)
|
|
printf(" DACL_AUTO_INHERIT_REQ");
|
|
if (sdc & SE_SACL_AUTO_INHERIT_REQ)
|
|
printf(" SACL_AUTO_INHERIT_REQ");
|
|
if (sdc & SE_DACL_AUTO_INHERITED)
|
|
printf(" DACL_AUTO_INHERITED");
|
|
if (sdc & SE_SACL_AUTO_INHERITED)
|
|
printf(" SACL_AUTO_INHERITED");
|
|
if (sdc & SE_DACL_PROTECTED)
|
|
printf(" DACL_PROTECTED");
|
|
if (sdc & SE_SACL_PROTECTED)
|
|
printf(" SACL_PROTECTED");
|
|
if (sdc & SE_SELF_RELATIVE)
|
|
printf(" SELF_RELATIVE");
|
|
printf("\n");
|
|
printf(" Revision: %d\n", dwRevision);
|
|
}
|
|
}
|
|
|
|
static void DisplaySid(
|
|
PSID pSid
|
|
)
|
|
{
|
|
PSID_IDENTIFIER_AUTHORITY psia;
|
|
DWORD dwSubAuthorities;
|
|
DWORD dwCounter;
|
|
|
|
char szAccount[_MAX_PATH];
|
|
DWORD cchAccount;
|
|
char szDomain[_MAX_PATH];
|
|
DWORD cchDomain;
|
|
SID_NAME_USE snu;
|
|
|
|
if (!IsValidSid(pSid)) {
|
|
printf("Invalid SID\n");
|
|
return;
|
|
}
|
|
|
|
// obtain SidIdentifierAuthority
|
|
psia = GetSidIdentifierAuthority(pSid);
|
|
|
|
// obtain sidsubauthority count
|
|
dwSubAuthorities = *GetSidSubAuthorityCount(pSid);
|
|
|
|
//
|
|
// prepare S-SID_REVISION-
|
|
//
|
|
printf("S-%lu-", SID_REVISION);
|
|
|
|
//
|
|
// prepare SidIdentifierAuthority
|
|
//
|
|
if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) {
|
|
printf("0x%02hx%02hx%02hx%02hx%02hx%02hx",
|
|
(USHORT)psia->Value[0],
|
|
(USHORT)psia->Value[1],
|
|
(USHORT)psia->Value[2],
|
|
(USHORT)psia->Value[3],
|
|
(USHORT)psia->Value[4],
|
|
(USHORT)psia->Value[5]);
|
|
} else {
|
|
printf("%lu",
|
|
(ULONG)(psia->Value[5] ) +
|
|
(ULONG)(psia->Value[4] << 8) +
|
|
(ULONG)(psia->Value[3] << 16) +
|
|
(ULONG)(psia->Value[2] << 24) );
|
|
}
|
|
|
|
//
|
|
// loop through SidSubAuthorities
|
|
//
|
|
for (dwCounter = 0 ; dwCounter < dwSubAuthorities ; dwCounter++) {
|
|
printf("-%lu", *GetSidSubAuthority(pSid, dwCounter) );
|
|
}
|
|
|
|
|
|
cchAccount = sizeof(szAccount) - 1;
|
|
memset(szAccount, 0, sizeof(szAccount));
|
|
cchDomain = sizeof(szDomain) - 1;
|
|
memset(szDomain, 0, sizeof(szDomain));
|
|
snu = (SID_NAME_USE) 0;
|
|
if (LookupAccountSidA(
|
|
NULL, // lpSystemName
|
|
pSid,
|
|
szAccount,
|
|
&cchAccount,
|
|
szDomain,
|
|
&cchDomain,
|
|
&snu
|
|
))
|
|
printf(" Account: %s Domain: %s SNU: %d", szAccount, szDomain, snu);
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
static void DisplayOwnerSecurityInfo(
|
|
IN PSECURITY_DESCRIPTOR psd
|
|
)
|
|
{
|
|
PSID pSid = NULL;
|
|
BOOL fOwnerDefaulted;
|
|
|
|
if (!GetSecurityDescriptorOwner(psd, &pSid, &fOwnerDefaulted)) {
|
|
PrintLastError("GetSecurityDescriptorOwner");
|
|
return;
|
|
}
|
|
|
|
if (NULL == pSid)
|
|
printf(" NO OWNER\n");
|
|
else {
|
|
printf(" Owner: ");
|
|
DisplaySid(pSid);
|
|
if (fOwnerDefaulted)
|
|
printf(" Owner Defaulted\n");
|
|
}
|
|
}
|
|
|
|
static void DisplayGroupSecurityInfo(
|
|
IN PSECURITY_DESCRIPTOR psd
|
|
)
|
|
{
|
|
PSID pSid = NULL;
|
|
BOOL fGroupDefaulted;
|
|
|
|
if (!GetSecurityDescriptorGroup(psd, &pSid, &fGroupDefaulted)) {
|
|
PrintLastError("GetSecurityDescriptorGroup");
|
|
return;
|
|
}
|
|
|
|
if (NULL == pSid)
|
|
printf(" NO Group\n");
|
|
else {
|
|
printf(" Group: ");
|
|
DisplaySid(pSid);
|
|
if (fGroupDefaulted)
|
|
printf(" Group Defaulted\n");
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static LPCSTR GetAceTypeString(
|
|
IN BYTE AceType
|
|
)
|
|
{
|
|
switch (AceType) {
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
return "ACCESS_ALLOWED";
|
|
break;
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
return "ACCESS_DENIED_ACE_TYPE";
|
|
break;
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
return "SYSTEM_AUDIT_ACE_TYPE";
|
|
break;
|
|
case SYSTEM_ALARM_ACE_TYPE:
|
|
return "SYSTEM_ALARM_ACE_TYPE";
|
|
break;
|
|
case ACCESS_ALLOWED_COMPOUND_ACE_TYPE:
|
|
return "ACCESS_ALLOWED_COMPOUND_ACE_TYPE";
|
|
break;
|
|
case ACCESS_ALLOWED_OBJECT_ACE_TYPE:
|
|
return "ACCESS_ALLOWED_OBJECT_ACE_TYPE";
|
|
break;
|
|
case ACCESS_DENIED_OBJECT_ACE_TYPE:
|
|
return "ACCESS_DENIED_OBJECT_ACE_TYPE";
|
|
break;
|
|
case SYSTEM_AUDIT_OBJECT_ACE_TYPE:
|
|
return "SYSTEM_AUDIT_OBJECT_ACE_TYPE";
|
|
break;
|
|
case SYSTEM_ALARM_OBJECT_ACE_TYPE:
|
|
return "SYSTEM_ALARM_OBJECT_ACE_TYPE";
|
|
break;
|
|
default:
|
|
return "???";
|
|
}
|
|
|
|
}
|
|
|
|
static void DisplayAceFlags(
|
|
IN BYTE AceFlags
|
|
)
|
|
{
|
|
if (AceFlags & OBJECT_INHERIT_ACE)
|
|
printf(" OBJECT_INHERIT");
|
|
if (AceFlags & CONTAINER_INHERIT_ACE)
|
|
printf(" CONTAINER_INHERIT");
|
|
if (AceFlags & NO_PROPAGATE_INHERIT_ACE)
|
|
printf(" NO_PROPAGATE_INHERIT");
|
|
if (AceFlags & INHERIT_ONLY_ACE)
|
|
printf(" INHERIT_ONLY");
|
|
if (AceFlags & INHERITED_ACE)
|
|
printf(" INHERITED");
|
|
if (AceFlags & SUCCESSFUL_ACCESS_ACE_FLAG)
|
|
printf(" SUCCESSFUL_ACCESS");
|
|
if (AceFlags & FAILED_ACCESS_ACE_FLAG)
|
|
printf(" FAILED_ACCESS");
|
|
}
|
|
|
|
static void DisplayAccessMask(
|
|
IN ACCESS_MASK Mask
|
|
)
|
|
{
|
|
if (Mask & SYNCHRONIZE)
|
|
printf(" SYNCHRONIZE");
|
|
if (Mask & ACCESS_SYSTEM_SECURITY)
|
|
printf(" ACCESS_SYSTEM_SECURITY");
|
|
if (Mask & MAXIMUM_ALLOWED)
|
|
printf(" MAXIMUM_ALLOWED");
|
|
if (Mask & GENERIC_READ)
|
|
printf(" GENERIC_READ");
|
|
if (Mask & GENERIC_WRITE)
|
|
printf(" GENERIC_WRITE");
|
|
if (Mask & GENERIC_EXECUTE)
|
|
printf(" GENERIC_EXECUTE");
|
|
if (Mask & GENERIC_ALL)
|
|
printf(" GENERIC_ALL");
|
|
|
|
if (KEY_ALL_ACCESS == (Mask & KEY_ALL_ACCESS)) {
|
|
printf(" KEY_ALL_ACCESS");
|
|
return;
|
|
}
|
|
|
|
if (KEY_READ == (Mask & KEY_READ))
|
|
printf(" KEY_READ");
|
|
if (KEY_WRITE == (Mask & KEY_WRITE))
|
|
printf(" KEY_WRITE");
|
|
if (KEY_EXECUTE == (Mask & KEY_EXECUTE))
|
|
printf(" KEY_EXECUTE");
|
|
|
|
if (Mask & DELETE)
|
|
printf(" DELETE");
|
|
if (Mask & READ_CONTROL)
|
|
printf(" READ_CONTROL");
|
|
if (Mask & WRITE_DAC)
|
|
printf(" WRITE_DAC");
|
|
if (Mask & WRITE_OWNER)
|
|
printf(" WRITE_OWNER");
|
|
|
|
|
|
if (Mask & KEY_QUERY_VALUE)
|
|
printf(" KEY_QUERY_VALUE");
|
|
if (Mask & KEY_SET_VALUE)
|
|
printf(" KEY_SET_VALUE");
|
|
if (Mask & KEY_CREATE_SUB_KEY)
|
|
printf(" KEY_CREATE_SUB_KEY");
|
|
if (Mask & KEY_ENUMERATE_SUB_KEYS)
|
|
printf(" KEY_ENUMERATE_SUB_KEYS");
|
|
if (Mask & KEY_NOTIFY)
|
|
printf(" KEY_NOTIFY");
|
|
if (Mask & KEY_CREATE_LINK)
|
|
printf(" KEY_CREATE_LINK");
|
|
}
|
|
|
|
static void DisplayAcl(
|
|
IN BOOL fDaclPresent,
|
|
IN PACL pAcl,
|
|
IN BOOL fDaclDefaulted
|
|
)
|
|
{
|
|
DWORD dwAceIndex;
|
|
|
|
if (!fDaclPresent) {
|
|
printf(" NO ACL\n");
|
|
return;
|
|
}
|
|
|
|
if (NULL == pAcl) {
|
|
printf(" NULL ACL\n");
|
|
return;
|
|
}
|
|
|
|
printf(" AclRevision: %d", pAcl->AclRevision);
|
|
if (fDaclDefaulted)
|
|
printf(" Defaulted ACL");
|
|
printf("\n");
|
|
|
|
for (dwAceIndex = 0; dwAceIndex < pAcl->AceCount; dwAceIndex++) {
|
|
PACE_HEADER pAceHdr;
|
|
PACCESS_ALLOWED_ACE pAce;
|
|
if (!GetAce(pAcl, dwAceIndex, (void **) &pAceHdr)) {
|
|
PrintLastError("GetAce");
|
|
return;
|
|
}
|
|
|
|
printf(" Ace[%d]\n", dwAceIndex);
|
|
printf(" Type: 0x%x %s\n", pAceHdr->AceType,
|
|
GetAceTypeString(pAceHdr->AceType));
|
|
printf(" Flags: 0x%x ", pAceHdr->AceFlags);
|
|
DisplayAceFlags(pAceHdr->AceFlags);
|
|
printf("\n");
|
|
switch (pAceHdr->AceType) {
|
|
case ACCESS_ALLOWED_ACE_TYPE:
|
|
case ACCESS_DENIED_ACE_TYPE:
|
|
case SYSTEM_AUDIT_ACE_TYPE:
|
|
case SYSTEM_ALARM_ACE_TYPE:
|
|
pAce = (PACCESS_ALLOWED_ACE) pAceHdr;
|
|
printf(" Mask: 0x%x", pAce->Mask);
|
|
DisplayAccessMask(pAce->Mask);
|
|
printf("\n");
|
|
printf(" SID: ");
|
|
DisplaySid((PSID) &pAce->SidStart);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void DisplayDaclSecurityInfo(
|
|
IN PSECURITY_DESCRIPTOR psd
|
|
)
|
|
{
|
|
BOOL fDaclPresent;
|
|
PACL pAcl;
|
|
BOOL fDaclDefaulted;
|
|
DWORD dwAceIndex;
|
|
|
|
printf(" --- DACLs ---\n");
|
|
if (!GetSecurityDescriptorDacl(psd, &fDaclPresent, &pAcl,
|
|
&fDaclDefaulted)) {
|
|
PrintLastError("GetSecurityDescriptorDacl");
|
|
return;
|
|
}
|
|
DisplayAcl(fDaclPresent, pAcl, fDaclDefaulted);
|
|
}
|
|
|
|
static void DisplaySaclSecurityInfo(
|
|
IN PSECURITY_DESCRIPTOR psd
|
|
)
|
|
{
|
|
BOOL fSaclPresent;
|
|
PACL pAcl;
|
|
BOOL fSaclDefaulted;
|
|
DWORD dwAceIndex;
|
|
|
|
printf(" --- SACLs ---\n");
|
|
if (!GetSecurityDescriptorSacl(psd, &fSaclPresent, &pAcl,
|
|
&fSaclDefaulted)) {
|
|
PrintLastError("GetSecurityDescriptorSacl");
|
|
return;
|
|
}
|
|
DisplayAcl(fSaclPresent, pAcl, fSaclDefaulted);
|
|
}
|
|
|
|
static void DisplayRegQueryInfo(
|
|
IN HKEY hKey
|
|
)
|
|
{
|
|
FILETIME ftLastWriteTime;
|
|
LONG err;
|
|
|
|
memset(&ftLastWriteTime, 0, sizeof(ftLastWriteTime));
|
|
if (ERROR_SUCCESS == (err = RegQueryInfoKeyA(
|
|
hKey,
|
|
NULL, // lpszClass
|
|
NULL, // lpcchClass
|
|
NULL, // lpdwReserved
|
|
NULL, // lpcSubKeys
|
|
NULL, // lpcchMaxSubKey
|
|
NULL, // lpcchMaxClass
|
|
NULL, // lpcValues
|
|
NULL, // lpcchMaxValuesName
|
|
NULL, // lpcbMaxValueData
|
|
NULL, // lpcbSecurityDescriptor
|
|
&ftLastWriteTime
|
|
))) {
|
|
printf("LastWriteTime:: %s\n", FileTimeText(&ftLastWriteTime));
|
|
}
|
|
}
|
|
|
|
static void DisplayRegSecurityInfo(
|
|
IN HKEY hKey,
|
|
IN LPCSTR pszKeyBase,
|
|
IN LPCSTR pszRegPath,
|
|
SECURITY_INFORMATION SecInf,
|
|
IN BOOL fRecurse
|
|
)
|
|
{
|
|
PSECURITY_DESCRIPTOR psd = NULL;
|
|
|
|
printf("%s\\%s\n", pszKeyBase, pszRegPath);
|
|
|
|
if (NULL == (psd = AllocAndGetSecurityDescriptor(
|
|
hKey, SecInf)))
|
|
return;
|
|
|
|
DisplayRegQueryInfo(hKey);
|
|
|
|
DisplayControl(psd);
|
|
|
|
DisplayOwnerSecurityInfo(psd);
|
|
DisplayGroupSecurityInfo(psd);
|
|
DisplayDaclSecurityInfo(psd);
|
|
if (SecInf & SACL_SECURITY_INFORMATION)
|
|
DisplaySaclSecurityInfo(psd);
|
|
|
|
TestFree(psd);
|
|
if (fRecurse) {
|
|
}
|
|
}
|
|
|
|
static void * AllocAndGetTokenInfo(
|
|
IN HANDLE hToken,
|
|
IN TOKEN_INFORMATION_CLASS tic
|
|
)
|
|
{
|
|
void *pvInfo = NULL;
|
|
DWORD cbInfo = 0;
|
|
DWORD cbInfo2;
|
|
|
|
if (!GetTokenInformation(
|
|
hToken,
|
|
tic,
|
|
pvInfo,
|
|
0, // cbInfo
|
|
&cbInfo
|
|
)) {
|
|
if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) {
|
|
PrintLastError("GetTokenInformation");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
if (0 == cbInfo) {
|
|
printf("No Information\n");
|
|
return NULL;
|
|
}
|
|
if (NULL == (pvInfo = TestAlloc(cbInfo)))
|
|
return NULL;
|
|
|
|
cbInfo2 = cbInfo;
|
|
if (!GetTokenInformation(
|
|
hToken,
|
|
tic,
|
|
pvInfo,
|
|
cbInfo,
|
|
&cbInfo2
|
|
)) {
|
|
PrintLastError("GetTokenInformation");
|
|
TestFree(pvInfo);
|
|
return NULL;
|
|
}
|
|
|
|
return pvInfo;
|
|
}
|
|
|
|
|
|
static void GetProcessTokenInfo()
|
|
{
|
|
HANDLE hToken = NULL;
|
|
void *pvInfo = NULL;
|
|
|
|
printf("Get Process Token Information\n\n");
|
|
if (!OpenProcessToken(
|
|
GetCurrentProcess(),
|
|
TOKEN_QUERY,
|
|
&hToken
|
|
)) {
|
|
PrintLastError("OpenProcessToken");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
printf("TokenUser: ");
|
|
if (pvInfo = AllocAndGetTokenInfo(hToken, TokenUser)) {
|
|
PTOKEN_USER pTokenUser = (PTOKEN_USER) pvInfo;
|
|
if (pTokenUser->User.Attributes)
|
|
printf("Attributes(0x%x) ", pTokenUser->User.Attributes);
|
|
|
|
DisplaySid(pTokenUser->User.Sid);
|
|
TestFree(pvInfo);
|
|
pvInfo = NULL;
|
|
}
|
|
|
|
printf("TokenOwner: ");
|
|
if (pvInfo = AllocAndGetTokenInfo(hToken, TokenOwner)) {
|
|
PTOKEN_OWNER pTokenOwner = (PTOKEN_OWNER) pvInfo;
|
|
|
|
DisplaySid(pTokenOwner->Owner);
|
|
TestFree(pvInfo);
|
|
pvInfo = NULL;
|
|
}
|
|
|
|
printf("TokenPrimaryGroup: ");
|
|
if (pvInfo = AllocAndGetTokenInfo(hToken, TokenPrimaryGroup)) {
|
|
PTOKEN_PRIMARY_GROUP pTokenPrimaryGroup = (PTOKEN_PRIMARY_GROUP) pvInfo;
|
|
|
|
DisplaySid(pTokenPrimaryGroup->PrimaryGroup);
|
|
TestFree(pvInfo);
|
|
pvInfo = NULL;
|
|
}
|
|
|
|
printf("TokenGroups\n");
|
|
if (pvInfo = AllocAndGetTokenInfo(hToken, TokenGroups)) {
|
|
PTOKEN_GROUPS pTokenGroups = (PTOKEN_GROUPS) pvInfo;
|
|
DWORD GroupCount = pTokenGroups->GroupCount;
|
|
if (0 == GroupCount)
|
|
printf(" No Groups\n");
|
|
else {
|
|
DWORD i;
|
|
for (i = 0; i < GroupCount; i++) {
|
|
printf(" Group[%d]: ", i);
|
|
if (pTokenGroups->Groups[i].Attributes)
|
|
printf("Attributes(0x%x) ",
|
|
pTokenGroups->Groups[i].Attributes);
|
|
|
|
DisplaySid(pTokenGroups->Groups[i].Sid);
|
|
}
|
|
}
|
|
TestFree(pvInfo);
|
|
pvInfo = NULL;
|
|
}
|
|
|
|
printf("TokenPrivileges\n");
|
|
if (pvInfo = AllocAndGetTokenInfo(hToken, TokenPrivileges)) {
|
|
PTOKEN_PRIVILEGES pTokenPrivileges = (PTOKEN_PRIVILEGES) pvInfo;
|
|
DWORD PrivilegeCount = pTokenPrivileges->PrivilegeCount;
|
|
if (0 == PrivilegeCount)
|
|
printf(" No Privileges\n");
|
|
else {
|
|
DWORD i;
|
|
for (i = 0; i < PrivilegeCount; i++) {
|
|
char szName[_MAX_PATH];
|
|
DWORD cchName;
|
|
printf(" Privilege[%d]: ", i);
|
|
if (pTokenPrivileges->Privileges[i].Attributes)
|
|
printf("Attributes(0x%x) ",
|
|
pTokenPrivileges->Privileges[i].Attributes);
|
|
|
|
cchName = sizeof(szName);
|
|
if (LookupPrivilegeName(
|
|
NULL, // pszSystemName
|
|
&pTokenPrivileges->Privileges[i].Luid,
|
|
szName,
|
|
&cchName
|
|
))
|
|
printf("%s\n", szName);
|
|
else
|
|
PrintLastError("LookupPrivlegeName");
|
|
}
|
|
}
|
|
TestFree(pvInfo);
|
|
pvInfo = NULL;
|
|
}
|
|
|
|
printf("TokenDefaultDacl\n");
|
|
if (pvInfo = AllocAndGetTokenInfo(hToken, TokenDefaultDacl)) {
|
|
PTOKEN_DEFAULT_DACL pTokenDacl = (PTOKEN_DEFAULT_DACL) pvInfo;
|
|
|
|
DisplayAcl(TRUE, pTokenDacl->DefaultDacl, FALSE);
|
|
TestFree(pvInfo);
|
|
pvInfo = NULL;
|
|
}
|
|
|
|
ErrorReturn:
|
|
if (hToken)
|
|
CloseHandle(hToken);
|
|
TestFree(pvInfo);
|
|
}
|
|
|
|
|
|
static void SetOwner(
|
|
IN HKEY hKeyBase,
|
|
IN LPCSTR pszRegPath
|
|
)
|
|
{
|
|
LONG err;
|
|
HKEY hKey = NULL;
|
|
HANDLE hToken = NULL;
|
|
void *pvInfo = NULL;
|
|
|
|
SECURITY_DESCRIPTOR sd;
|
|
PSID pSid; // not allocated
|
|
|
|
printf("SetOwner\n");
|
|
|
|
if (!SetCurrentPrivilege(SE_TAKE_OWNERSHIP_NAME, TRUE))
|
|
PrintLastError("SetCurrentPrivilege(SE_TAKE_OWNERSHIP_NAME)");
|
|
|
|
if (ERROR_SUCCESS != (err = RegOpenKeyExA(
|
|
hKeyBase,
|
|
pszRegPath,
|
|
0, // dwReserved
|
|
WRITE_OWNER,
|
|
&hKey))) {
|
|
if (ERROR_FILE_NOT_FOUND == err) {
|
|
DWORD dwDisposition;
|
|
if (ERROR_SUCCESS == (err = RegCreateKeyExA(
|
|
hKeyBase,
|
|
pszRegPath,
|
|
0, // dwReserved
|
|
NULL, // lpClass
|
|
REG_OPTION_NON_VOLATILE,
|
|
WRITE_OWNER,
|
|
NULL, // lpSecurityAttributes
|
|
&hKey,
|
|
&dwDisposition)))
|
|
printf("Created Subkey\n");
|
|
}
|
|
}
|
|
|
|
if (ERROR_SUCCESS != err) {
|
|
PrintLastError("RegOpenKeyExA(WRITE_OWNER)", err);
|
|
hKey = NULL;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
PrintLastError("InitializeSecurityDescriptor");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!OpenProcessToken(
|
|
GetCurrentProcess(),
|
|
TOKEN_QUERY,
|
|
&hToken
|
|
)) {
|
|
PrintLastError("OpenProcessToken");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (NULL == (pvInfo = AllocAndGetTokenInfo(hToken, TokenUser)))
|
|
goto ErrorReturn;
|
|
else {
|
|
PTOKEN_USER pTokenUser = (PTOKEN_USER) pvInfo;
|
|
pSid = pTokenUser->User.Sid;
|
|
}
|
|
|
|
if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) {
|
|
PrintLastError("SetSecurityDescriptorOwner");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != (err = RegSetKeySecurity(
|
|
hKey,
|
|
OWNER_SECURITY_INFORMATION,
|
|
&sd
|
|
))) {
|
|
PrintLastError("RegSetKeySecurity(OWNER)", err);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
ErrorReturn:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
if (hToken)
|
|
CloseHandle(hToken);
|
|
TestFree(pvInfo);
|
|
}
|
|
|
|
static void SetGroupDaclSacl(
|
|
IN HKEY hKeyBase,
|
|
IN LPCSTR pszRegPath
|
|
)
|
|
{
|
|
LONG err;
|
|
HKEY hKey = NULL;
|
|
HANDLE hToken = NULL;
|
|
void *pvGroupInfo = NULL;
|
|
void *pvUserInfo = NULL;
|
|
|
|
SECURITY_DESCRIPTOR sd;
|
|
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority =
|
|
SECURITY_WORLD_SID_AUTHORITY;
|
|
PSID psidLocalSystem = NULL;
|
|
PSID psidAdministrators = NULL;
|
|
PSID psidEveryone = NULL;
|
|
PSID psidUser; // Not allocated
|
|
|
|
PACL pDacl = NULL;
|
|
PACCESS_ALLOWED_ACE pAce;
|
|
DWORD dwAclSize;
|
|
DWORD i;
|
|
|
|
SECURITY_INFORMATION SecInf = DACL_SECURITY_INFORMATION |
|
|
GROUP_SECURITY_INFORMATION;
|
|
REGSAM samDesired = WRITE_OWNER | WRITE_DAC;
|
|
|
|
printf("SetGroupDaclSacl\n");
|
|
|
|
if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) {
|
|
PrintLastError("InitializeSecurityDescriptor");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!SetCurrentPrivilege(SE_SECURITY_NAME, TRUE))
|
|
PrintLastError("SetCurrentPrivilege(SE_SECURITY_NAME)");
|
|
else {
|
|
SecInf |= SACL_SECURITY_INFORMATION;
|
|
samDesired |= ACCESS_SYSTEM_SECURITY;
|
|
if (!SetSecurityDescriptorSacl(&sd, FALSE, NULL, FALSE)) {
|
|
PrintLastError("SetSecurityDescriptorSacl");
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
if (ERROR_SUCCESS != (err = RegOpenKeyExA(
|
|
hKeyBase,
|
|
pszRegPath,
|
|
0, // dwReserved
|
|
samDesired,
|
|
&hKey))) {
|
|
PrintLastError("RegOpenKeyExA(WRITE_OWNER | WRITE_DAC)", err);
|
|
hKey = NULL;
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!OpenProcessToken(
|
|
GetCurrentProcess(),
|
|
TOKEN_QUERY,
|
|
&hToken
|
|
)) {
|
|
PrintLastError("OpenProcessToken");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (NULL == (pvGroupInfo = AllocAndGetTokenInfo(hToken, TokenPrimaryGroup)))
|
|
goto ErrorReturn;
|
|
else {
|
|
PTOKEN_PRIMARY_GROUP pTokenPrimaryGroup =
|
|
(PTOKEN_PRIMARY_GROUP) pvGroupInfo;
|
|
PSID pSid = pTokenPrimaryGroup->PrimaryGroup;
|
|
|
|
if (!SetSecurityDescriptorGroup(&sd, pSid, FALSE)) {
|
|
PrintLastError("SetSecurityDescriptorGroup");
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
if (NULL == (pvUserInfo = AllocAndGetTokenInfo(hToken, TokenUser)))
|
|
goto ErrorReturn;
|
|
else {
|
|
PTOKEN_USER pTokenUser = (PTOKEN_USER) pvUserInfo;
|
|
psidUser = pTokenUser->User.Sid;
|
|
}
|
|
|
|
|
|
//
|
|
// prepare the SIDS for LocalSystem, Administrators and Everyone
|
|
//
|
|
if (!AllocateAndInitializeSid(
|
|
&siaNtAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&psidLocalSystem
|
|
)) {
|
|
PrintLastError("AllocateAndInitializeSid(LocalSystem)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AllocateAndInitializeSid(
|
|
&siaNtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&psidAdministrators
|
|
)) {
|
|
PrintLastError("AllocateAndInitializeSid(Administrators)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AllocateAndInitializeSid(
|
|
&siaWorldSidAuthority,
|
|
1,
|
|
SECURITY_WORLD_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&psidEveryone
|
|
)) {
|
|
PrintLastError("AllocateAndInitializeSid(Everyone)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// compute size of new acl
|
|
//
|
|
|
|
dwAclSize = sizeof(ACL) +
|
|
4 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) +
|
|
GetLengthSid(psidLocalSystem) +
|
|
GetLengthSid(psidAdministrators) +
|
|
GetLengthSid(psidEveryone) +
|
|
GetLengthSid(psidUser)
|
|
;
|
|
|
|
//
|
|
// allocate storage for Acl
|
|
//
|
|
if (NULL == (pDacl = (PACL) TestAlloc(dwAclSize)))
|
|
goto ErrorReturn;
|
|
|
|
if (!InitializeAcl(pDacl, dwAclSize, ACL_REVISION)) {
|
|
PrintLastError("InitializeAcl");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AddAccessAllowedAce(
|
|
pDacl,
|
|
ACL_REVISION,
|
|
KEY_ALL_ACCESS,
|
|
psidLocalSystem
|
|
)) {
|
|
PrintLastError("AddAccessAllowedAce(LocalSystem)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AddAccessAllowedAce(
|
|
pDacl,
|
|
ACL_REVISION,
|
|
KEY_ALL_ACCESS,
|
|
psidAdministrators
|
|
)) {
|
|
PrintLastError("AddAccessAllowedAce(Administrators)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AddAccessAllowedAce(
|
|
pDacl,
|
|
ACL_REVISION,
|
|
KEY_READ,
|
|
psidEveryone
|
|
)) {
|
|
PrintLastError("AddAccessAllowedAce(Everyone)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AddAccessAllowedAce(
|
|
pDacl,
|
|
ACL_REVISION,
|
|
KEY_ALL_ACCESS,
|
|
psidUser
|
|
)) {
|
|
PrintLastError("AddAccessAllowedAce(User)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
//
|
|
// make containers inherit.
|
|
//
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if(!GetAce(pDacl, i, (void **) &pAce)) {
|
|
PrintLastError("GetAce");
|
|
goto ErrorReturn;
|
|
}
|
|
pAce->Header.AceFlags = CONTAINER_INHERIT_ACE;
|
|
}
|
|
|
|
if (!SetSecurityDescriptorDacl(&sd, TRUE, pDacl, FALSE)) {
|
|
PrintLastError("SetSecurityDescriptorDacl");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (ERROR_SUCCESS != (err = RegSetKeySecurity(
|
|
hKey,
|
|
SecInf,
|
|
&sd
|
|
))) {
|
|
PrintLastError("RegSetKeySecurity(Group, DACL, SACL)", err);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
ErrorReturn:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
if (hToken)
|
|
CloseHandle(hToken);
|
|
TestFree(pvGroupInfo);
|
|
TestFree(pvUserInfo);
|
|
|
|
if (psidLocalSystem)
|
|
FreeSid(psidLocalSystem);
|
|
if (psidAdministrators)
|
|
FreeSid(psidAdministrators);
|
|
if (psidEveryone)
|
|
FreeSid(psidEveryone);
|
|
TestFree(pDacl);
|
|
}
|
|
|
|
#define PROT_ROOT_SUBKEY_NAME L"ProtectedRoots"
|
|
#define SYSTEM_STORE_REGPATH L"Software\\Microsoft\\SystemCertificates"
|
|
#define PROT_ROOT_REGPATH \
|
|
SYSTEM_STORE_REGPATH L"\\Root\\" PROT_ROOT_SUBKEY_NAME
|
|
|
|
#define PSID_PROT_OWNER psidAdministrators
|
|
#define PSID_PROT_SYSTEM psidLocalSystem
|
|
#define PSID_PROT_EVERYONE psidEveryone
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// ACL definitions used to set security on the "ProtectedRoots" SubKey.
|
|
//--------------------------------------------------------------------------
|
|
#define PROT_SYSTEM_ACE_MASK KEY_ALL_ACCESS
|
|
#define PROT_EVERYONE_ACE_MASK KEY_READ
|
|
#define PROT_ACE_FLAGS CONTAINER_INHERIT_ACE
|
|
|
|
#define PROT_ACE_COUNT 2
|
|
#define PROT_SYSTEM_ACE_INDEX 0
|
|
#define PROT_EVERYONE_ACE_INDEX 1
|
|
|
|
|
|
static void CheckProtectedRoots()
|
|
{
|
|
LONG lErr;
|
|
HKEY hKeyProtRoot = NULL;
|
|
PSECURITY_DESCRIPTOR psd = NULL;
|
|
PSID psidOwner; // not allocated
|
|
BOOL fOwnerDefaulted;
|
|
BOOL fDaclPresent;
|
|
PACL pAcl; // not allocated
|
|
BOOL fDaclDefaulted;
|
|
DWORD dwAceIndex;
|
|
PACCESS_ALLOWED_ACE rgpAce[PROT_ACE_COUNT];
|
|
|
|
PSID psidLocalSystem = NULL;
|
|
PSID psidAdministrators = NULL;
|
|
PSID psidEveryone = NULL;
|
|
|
|
SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority =
|
|
SECURITY_WORLD_SID_AUTHORITY;
|
|
|
|
if (ERROR_SUCCESS != (lErr = RegOpenKeyExU(
|
|
HKEY_CURRENT_USER,
|
|
PROT_ROOT_REGPATH,
|
|
0, // dwReserved
|
|
KEY_READ,
|
|
&hKeyProtRoot))) {
|
|
PrintLastError("OpenProtectedRootKey", lErr);
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (NULL == (psd = AllocAndGetSecurityDescriptor(
|
|
hKeyProtRoot,
|
|
OWNER_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION
|
|
)))
|
|
goto ErrorReturn;
|
|
|
|
//
|
|
// prepare the SIDS for LocalSystem, Administrators and Everyone
|
|
//
|
|
if (!AllocateAndInitializeSid(
|
|
&siaNtAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&psidLocalSystem
|
|
)) {
|
|
PrintLastError("AllocateAndInitializeSid(LocalSystem)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AllocateAndInitializeSid(
|
|
&siaNtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0, 0, 0, 0, 0, 0,
|
|
&psidAdministrators
|
|
)) {
|
|
PrintLastError("AllocateAndInitializeSid(Administrators)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
if (!AllocateAndInitializeSid(
|
|
&siaWorldSidAuthority,
|
|
1,
|
|
SECURITY_WORLD_RID,
|
|
0, 0, 0, 0, 0, 0, 0,
|
|
&psidEveryone
|
|
)) {
|
|
PrintLastError("AllocateAndInitializeSid(Everyone)");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
// Verify owner
|
|
if (!GetSecurityDescriptorOwner(psd, &psidOwner, &fOwnerDefaulted)) {
|
|
PrintLastError("GetSecurityDescriptorOwner");
|
|
goto ErrorReturn;
|
|
}
|
|
if (NULL == psidOwner || !EqualSid(psidOwner, PSID_PROT_OWNER)) {
|
|
printf("failed => invalid Owner\n");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
// Verify DACL
|
|
if (!GetSecurityDescriptorDacl(psd, &fDaclPresent, &pAcl,
|
|
&fDaclDefaulted)) {
|
|
PrintLastError("GetSecurityDescriptorDacl");
|
|
goto ErrorReturn;
|
|
}
|
|
if (!fDaclPresent || NULL == pAcl) {
|
|
printf("failed => missing Dacl\n");
|
|
goto ErrorReturn;
|
|
}
|
|
if (PROT_ACE_COUNT != pAcl->AceCount) {
|
|
printf("failed => invalid AceCount\n");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
for (dwAceIndex = 0; dwAceIndex < PROT_ACE_COUNT; dwAceIndex++) {
|
|
PACCESS_ALLOWED_ACE pAce;
|
|
if (!GetAce(pAcl, dwAceIndex, (void **) &pAce)) {
|
|
printf("failed => invalid Acl\n");
|
|
goto ErrorReturn;
|
|
}
|
|
rgpAce[dwAceIndex] = pAce;
|
|
|
|
if (ACCESS_ALLOWED_ACE_TYPE != pAce->Header.AceType ||
|
|
PROT_ACE_FLAGS != pAce->Header.AceFlags) {
|
|
printf("failed => invalid Acl\n");
|
|
goto ErrorReturn;
|
|
}
|
|
}
|
|
|
|
if (PROT_SYSTEM_ACE_MASK != rgpAce[PROT_SYSTEM_ACE_INDEX]->Mask ||
|
|
!EqualSid(PSID_PROT_SYSTEM,
|
|
(PSID) &rgpAce[PROT_SYSTEM_ACE_INDEX]->SidStart) ||
|
|
PROT_EVERYONE_ACE_MASK != rgpAce[PROT_EVERYONE_ACE_INDEX]->Mask ||
|
|
!EqualSid(PSID_PROT_EVERYONE,
|
|
(PSID) &rgpAce[PROT_EVERYONE_ACE_INDEX]->SidStart)) {
|
|
printf("failed => invalid Acl\n");
|
|
goto ErrorReturn;
|
|
}
|
|
|
|
printf("Success => ProtectedRoots has correct ACLs\n");
|
|
CommonReturn:
|
|
if (psidLocalSystem)
|
|
FreeSid(psidLocalSystem);
|
|
if (psidAdministrators)
|
|
FreeSid(psidAdministrators);
|
|
if (psidEveryone)
|
|
FreeSid(psidEveryone);
|
|
|
|
TestFree(psd);
|
|
if (hKeyProtRoot)
|
|
RegCloseKey(hKeyProtRoot);
|
|
return;
|
|
|
|
ErrorReturn:
|
|
printf("Failed => ProtectedRoots has the following BAD ACLs\n");
|
|
if (hKeyProtRoot)
|
|
DisplayRegQueryInfo(hKeyProtRoot);
|
|
|
|
if (psd) {
|
|
DisplayControl(psd);
|
|
DisplayOwnerSecurityInfo(psd);
|
|
DisplayGroupSecurityInfo(psd);
|
|
DisplayDaclSecurityInfo(psd);
|
|
}
|
|
goto CommonReturn;
|
|
}
|
|
|
|
|
|
int _cdecl main(int argc, char * argv[])
|
|
{
|
|
int status;
|
|
|
|
#define TEST_NAME_INDEX 0
|
|
#define PATH_NAME_INDEX 1
|
|
#define MAX_NAME_CNT 2
|
|
DWORD dwNameCnt = 0;
|
|
LPCSTR rgpszName[MAX_NAME_CNT];
|
|
LPCSTR pszTestName; // not allocated
|
|
LPCSTR pszRegPath; // not allocated
|
|
|
|
HKEY hKeyBase = HKEY_CURRENT_USER;
|
|
LPCSTR pszKeyBase = "HKEY_CURRENT_USER";
|
|
BOOL fRecurse = FALSE;
|
|
HKEY hKey = NULL;
|
|
|
|
while (--argc>0) {
|
|
if (**++argv == '-')
|
|
{
|
|
switch(argv[0][1])
|
|
{
|
|
case 'l':
|
|
if (argv[0][2]) {
|
|
if (0 == _stricmp(argv[0]+2, "CU")) {
|
|
hKeyBase = HKEY_CURRENT_USER;
|
|
pszKeyBase = "HKEY_CURRENT_USER";
|
|
} else if (0 == _stricmp(argv[0]+2, "LM")) {
|
|
hKeyBase = HKEY_LOCAL_MACHINE;
|
|
pszKeyBase = "HKEY_LOCAL_MACHINE";
|
|
} else {
|
|
printf("Need to specify -lCU or -lLM\n");
|
|
goto BadUsage;
|
|
}
|
|
} else {
|
|
printf("Need to specify -lCU or -lLM\n");
|
|
goto BadUsage;
|
|
}
|
|
break;
|
|
case 'r':
|
|
fRecurse = TRUE;
|
|
break;
|
|
|
|
case 'h':
|
|
default:
|
|
goto BadUsage;
|
|
}
|
|
} else {
|
|
if (MAX_NAME_CNT <= dwNameCnt) {
|
|
printf("Too many names starting with:: %s\n", argv[0]);
|
|
goto BadUsage;
|
|
}
|
|
rgpszName[dwNameCnt++] = argv[0];
|
|
}
|
|
}
|
|
|
|
|
|
printf("command line: %s\n", GetCommandLine());
|
|
|
|
if (0 == dwNameCnt) {
|
|
printf("Missing <TestName>\n");
|
|
goto BadUsage;
|
|
} else
|
|
pszTestName = rgpszName[TEST_NAME_INDEX];
|
|
|
|
if (0 == _stricmp("PurgeLMRoots", pszTestName)) {
|
|
printf("Purge LocalMachine Duplicate Roots from CurrentUser\n");
|
|
if (!I_CertProtectFunction(
|
|
CERT_PROT_PURGE_LM_ROOTS_FUNC_ID,
|
|
0, // dwFlags
|
|
NULL, // pwszIn
|
|
NULL, // pbIn
|
|
0, // cbIn
|
|
NULL, // ppbOut
|
|
NULL // pcbOut
|
|
))
|
|
PrintLastError(
|
|
"I_CertProtectFunction(CERT_PROT_PURGE_LM_ROOTS_FUNC_ID)");
|
|
goto SuccessReturn;
|
|
} else if (0 == _stricmp("DeleteUnknownRoots", pszTestName)) {
|
|
printf("Delete unknown CurrentUser roots from Protected List\n");
|
|
if (!I_CertProtectFunction(
|
|
CERT_PROT_DELETE_UNKNOWN_ROOTS_FUNC_ID,
|
|
0, // dwFlags
|
|
NULL, // pwszIn
|
|
NULL, // pbIn
|
|
0, // cbIn
|
|
NULL, // ppbOut
|
|
NULL // pcbOut
|
|
))
|
|
PrintLastError(
|
|
"I_CertProtectFunction(CERT_PROT_DELETE_UNKNOWN_ROOTS_FUNC_ID)");
|
|
goto SuccessReturn;
|
|
} else if (0 == _stricmp("CheckProtectedRoots", pszTestName)) {
|
|
printf("Check ProtectedRoots ACLs\n");
|
|
CheckProtectedRoots();
|
|
goto SuccessReturn;
|
|
} else if (0 == _stricmp("ServiceUI", pszTestName)) {
|
|
BYTE *pbOut = NULL;
|
|
DWORD cbOut = 0;
|
|
|
|
printf("Certificate Protect Service UI\n");
|
|
if (!I_CertProtectFunction(
|
|
1000,
|
|
0, // dwFlags
|
|
L"Root test", // pwszIn
|
|
NULL, // pbIn
|
|
0, // cbIn
|
|
&pbOut,
|
|
&cbOut
|
|
))
|
|
PrintLastError("I_CertProtectFunction(UI)");
|
|
else if (pbOut) {
|
|
PrintBytes("DataOut", pbOut, cbOut);
|
|
CryptMemFree(pbOut);
|
|
}
|
|
goto SuccessReturn;
|
|
} else if (0 == _stricmp("ServiceTokenInfo", pszTestName)) {
|
|
BYTE *pbOut = NULL;
|
|
DWORD cbOut = 0;
|
|
|
|
printf("Certificate Protect Service's Token Info\n");
|
|
if (!I_CertProtectFunction(
|
|
1001,
|
|
0, // dwFlags
|
|
NULL, // pwszIn
|
|
NULL, // pbIn
|
|
0, // cbIn
|
|
&pbOut,
|
|
&cbOut
|
|
))
|
|
PrintLastError("I_CertProtectFunction(GetTokenInfo)");
|
|
else if (pbOut) {
|
|
if (cbOut)
|
|
puts((LPCSTR) pbOut);
|
|
CryptMemFree(pbOut);
|
|
}
|
|
goto SuccessReturn;
|
|
} else if (0 == _stricmp("ServiceInvalid", pszTestName)) {
|
|
printf("Calling Invalid Certificate Protect Function\n");
|
|
if (!I_CertProtectFunction(
|
|
1002,
|
|
0, // dwFlags
|
|
NULL, // pwszIn
|
|
NULL, // pbIn
|
|
0, // cbIn
|
|
NULL, // ppbOut
|
|
NULL // pcbOut
|
|
))
|
|
PrintLastError("I_CertProtectFunction(1002)");
|
|
goto SuccessReturn;
|
|
} else if (1 == dwNameCnt) {
|
|
printf("Missing <RegPath>\n");
|
|
goto BadUsage;
|
|
} else
|
|
pszRegPath = rgpszName[PATH_NAME_INDEX];
|
|
|
|
printf("\n");
|
|
if (0 == _stricmp("GetKey", pszTestName)) {
|
|
LONG err;
|
|
REGSAM samDesired = READ_CONTROL | ACCESS_SYSTEM_SECURITY;
|
|
SECURITY_INFORMATION SecInf = OWNER_SECURITY_INFORMATION |
|
|
GROUP_SECURITY_INFORMATION |
|
|
DACL_SECURITY_INFORMATION |
|
|
SACL_SECURITY_INFORMATION;
|
|
|
|
if (!SetCurrentPrivilege(SE_SECURITY_NAME, TRUE)) {
|
|
PrintLastError("SetCurrentPrivilege(SE_SECURITY_NAME)");
|
|
samDesired = READ_CONTROL;
|
|
SecInf &= ~SACL_SECURITY_INFORMATION;
|
|
}
|
|
|
|
if (!SetCurrentPrivilege(SE_TAKE_OWNERSHIP_NAME, TRUE))
|
|
PrintLastError("SetCurrentPrivilege(SE_TAKE_OWNERSHIP_NAME)");
|
|
|
|
GetProcessTokenInfo();
|
|
|
|
printf("\n\nGet Registry Key Security Information\n\n");
|
|
if (ERROR_SUCCESS != (err = RegOpenKeyExA(
|
|
hKeyBase,
|
|
pszRegPath,
|
|
0, // dwReserved
|
|
KEY_READ | samDesired,
|
|
&hKey))) {
|
|
if (ERROR_ACCESS_DENIED == err) {
|
|
if (ERROR_SUCCESS == (err = RegOpenKeyExA(
|
|
hKeyBase,
|
|
pszRegPath,
|
|
0, // dwReserved
|
|
samDesired,
|
|
&hKey))) {
|
|
printf("No Read Access\n");
|
|
fRecurse = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (ERROR_SUCCESS != err) {
|
|
printf("RegOpenKeyExA(%s\\%s) failed => 0x%x (%d)\n",
|
|
pszKeyBase, pszRegPath, err, err);
|
|
hKey = NULL;
|
|
} else
|
|
DisplayRegSecurityInfo(
|
|
hKey,
|
|
pszKeyBase,
|
|
pszRegPath,
|
|
SecInf,
|
|
fRecurse
|
|
);
|
|
} else if (0 == _stricmp("SetKey", pszTestName)) {
|
|
printf("Set Registry Key Security Information\n\n");
|
|
|
|
SetOwner(hKeyBase, pszRegPath);
|
|
SetGroupDaclSacl(hKeyBase, pszRegPath);
|
|
|
|
} else {
|
|
printf("Invalid TestName: %s\n", pszTestName);
|
|
goto BadUsage;
|
|
}
|
|
|
|
SuccessReturn:
|
|
status = 0;
|
|
CommonReturn:
|
|
if (hKey)
|
|
RegCloseKey(hKey);
|
|
return status;
|
|
BadUsage:
|
|
Usage();
|
|
status = -1;
|
|
goto CommonReturn;
|
|
}
|
|
|