bool CreateKeyDescriptor(IntPtr pOldSD, ACCOUNT_PERM Account, ref MEM_DATA MemData) { // reconstruct security descriptor bool bDefault = false; bool bPresent = false; int iControlBits = 0; int iControlSet = 0; int iDomain = 0; int iFlag = 0; int iLength = 0; int iRevision = 0; int iSidLen = 0; int iTotal = 0; int iUse = 0; StringBuilder sDomain = new StringBuilder(256); IntPtr pNewACL = IntPtr.Zero; IntPtr pAcl = IntPtr.Zero; IntPtr pSid = IntPtr.Zero; IntPtr pPnt = IntPtr.Zero; ACL_SIZE_INFORMATION tAclSize = new ACL_SIZE_INFORMATION(); ACL tTempACL = new ACL(); ACE tTempAce = new ACE(); try { MemData.pAcl = IntPtr.Zero; MemData.pSd = IntPtr.Zero; // get size pSid = LocalAlloc(LMEM_INITIALIZED, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSid == IntPtr.Zero) { return false; } // store pointer MemData.pSd = pSid; // init descriptor if (InitializeSecurityDescriptor(pSid, SECURITY_DESCRIPTOR_REVISION) == 0) { return false; } // check for existing sd if (pOldSD != IntPtr.Zero) { if (GetSecurityDescriptorDacl(pOldSD, out bPresent, ref pAcl, out bDefault) == true) { // extract dacl if ((bPresent == true) && (pAcl != IntPtr.Zero)) { if (GetAclInformation(pAcl, ref tAclSize, Marshal.SizeOf(tAclSize), ACL_INFORMATION_CLASS.AclSizeInformation) == false) { return false; } else { iTotal = tAclSize.AclBytesInUse; } } else { iTotal = Marshal.SizeOf(tTempACL); } } else { return false; } } // allocate sid // // get callers sid if (Account.pSid == IntPtr.Zero) { iDomain = 256; // get size LookupAccountName(null, Account.AccountName, IntPtr.Zero, ref iSidLen, sDomain, ref iDomain, out iUse); Account.pSid = LocalAlloc(LMEM_INITIALIZED, iSidLen); if (Account.pSid == IntPtr.Zero) { return false; } // get the sid if (LookupAccountName(null, Account.AccountName, Account.pSid, ref iSidLen, sDomain, ref iDomain, out iUse) == false) { return false; } } // ace buffer iLength = (Marshal.SizeOf(tTempAce) + GetLengthSid(Account.pSid)) - 4; iTotal += iLength; pNewACL = LocalAlloc(LMEM_INITIALIZED, iTotal); if (pNewACL == IntPtr.Zero) { return false; } // store pointer MemData.pAcl = pNewACL; // init acl if (InitializeAcl(pNewACL, iTotal, ACL_REVISION) == false) { return false; } // build dacl in sequence if (Account.AceType == ACCESS_DENIED_ACE_TYPE) { if (BuildACE(pNewACL, Account.AceType, Account.AceFlags, Account.AccessMask, Account.pSid) == false) { return false; } } // copy non-inherited ace if ((bPresent == true) && (pAcl != IntPtr.Zero) && (tAclSize.AceCount > 0)) { // combine old and new ACE entries for (int count = 0; count < tAclSize.AceCount; count++) { // next ace GetAce(pAcl, count, out pPnt); if (pPnt == IntPtr.Zero) { return false; } RtlMoveMemory(ref tTempAce, pPnt, Marshal.SizeOf(tTempAce)); // exit on inherited ace if (((int)tTempAce.Header.AceFlags & INHERITED_ACE) == INHERITED_ACE) { break; } int x = (int)pPnt + 8; IntPtr pPt = new IntPtr(x); // check ace value if (!SidIsEqual(Account.pSid, pPt)) { // add ace AddAce(pNewACL, ACL_REVISION, MAXDWORD, pPnt, tTempAce.Header.AceSize); } } } // add explicit permit if (Account.AceType == ACCESS_ALLOWED_ACE_TYPE) { BuildACE(pNewACL, Account.AceType, Account.AceFlags, Account.AccessMask, Account.pSid); } // enties with inheritence flag if ((bPresent == true) && (pAcl != IntPtr.Zero) && (tAclSize.AceCount > 0)) { for (int count = 0; count < tAclSize.AceCount; count++) { GetAce(pAcl, count, out pPnt); RtlMoveMemory(ref tTempAce, pPnt, Marshal.SizeOf(tTempAce)); AddAce(pNewACL, ACL_REVISION, MAXDWORD, pPnt, tTempAce.Header.AceSize); } } // descriptor flags if (pOldSD != IntPtr.Zero) { if (GetSecurityDescriptorControl(pOldSD, out iFlag, out iRevision) != 0) { if ((iFlag & SE_DACL_AUTO_INHERITED) == SE_DACL_AUTO_INHERITED) { iControlBits = SE_DACL_AUTO_INHERIT_REQ | SE_DACL_AUTO_INHERITED; iControlSet = iControlBits; } else if ((iFlag & SE_DACL_PROTECTED) == SE_DACL_PROTECTED) { iControlBits = SE_DACL_PROTECTED; iControlSet = iControlBits; } if (iControlSet != 0) { SetSecurityDescriptorControl(pSid, iControlBits, iControlSet); } } } // add dacl return SetSecurityDescriptorDacl(pSid, 1, pNewACL, 0); } finally { if (Account.pSid != IntPtr.Zero) { LocalFree(Account.pSid); Account.pSid = IntPtr.Zero; } } }
bool SetKeyPermissions(IntPtr hKey, ACCOUNT_PERM Account) { // apply key permissions int iLength = 0; int iReturn = 0; IntPtr pOldSD = IntPtr.Zero; IntPtr pSec = IntPtr.Zero; MEM_DATA tMem = new MEM_DATA(); try { tMem.pAcl = IntPtr.Zero; tMem.pSd = IntPtr.Zero; // allocate space iReturn = RegGetKeySecurity(hKey, DACL_SECURITY_INFORMATION, pOldSD, ref iLength); if (iLength > 0) { pOldSD = (LocalAlloc(LMEM_INITIALIZED, iLength)); if (pOldSD != IntPtr.Zero) { // load structure if ((RegGetKeySecurity(hKey, DACL_SECURITY_INFORMATION, pOldSD, ref iLength) == 0)) { // create dacl if (CreateKeyDescriptor(pOldSD, Account, ref tMem)) { // set descriptor return (RegSetKeySecurity(hKey, DACL_SECURITY_INFORMATION, tMem.pSd) == ERROR_SUCCESS); } } } } return false; } finally { // cleanup if (pOldSD != IntPtr.Zero) { LocalFree(pOldSD); pOldSD = IntPtr.Zero; } if (tMem.pSd != IntPtr.Zero) { LocalFree(tMem.pSd); tMem.pSd = IntPtr.Zero; } if (tMem.pAcl != IntPtr.Zero) { LocalFree(tMem.pAcl); tMem.pAcl = IntPtr.Zero; } } }
/// <summary> /// Changes key permissions /// </summary> /// <param name="RootKey"></param> /// <param name="SubKey"></param> /// <param name="AccountName"></param> /// <param name="AccessMask"></param> /// <param name="accessTypes"></param> /// <param name="Inheritence"></param> /// <returns></returns> public bool ChangeKeyPermissions(ROOT_KEY RootKey, string SubKey, string AccountName, RegistryAccess AccessMask, AccessTypes accessTypes, InheritenceFlags Inheritence) { // set key permissions (gate) IntPtr lKey = IntPtr.Zero; ACCOUNT_PERM tAccount = new ACCOUNT_PERM(); SID_IDENTIFIER_AUTHORITY tAuthority = new SID_IDENTIFIER_AUTHORITY(); try { // default account tAccount.AccountName = ""; tAccount.AccessMask = (uint)ACCESS_MASK.GENERIC_READ; tAccount.AceFlags = (byte)CONTAINER_INHERIT_ACE; tAccount.AceType = (byte)ACCESS_ALLOWED_ACE_TYPE; tAccount.pSid = IntPtr.Zero; tAuthority.Value = new byte[] { 0, 0, 0, 0, 0, (byte)SECURITY_WORLD_SID_AUTHORITY }; // test access if (AllocateAndInitializeSid(ref tAuthority, (byte)1, (int)SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, ref tAccount.pSid) == true) { // set up account tAccount.AccountName = AccountName; tAccount.AccessMask = (uint)AccessMask; tAccount.AceFlags = (byte)Inheritence; tAccount.AceType = (byte)accessTypes; tAccount.pSid = IntPtr.Zero; tAccount.SidPassedByCaller = false; // apply change to key if ((RegOpenKeyEx(RootKey, SubKey, 0, (int)(READ_CONTROL | WRITE_DAC), ref lKey) == 0)) { return SetKeyPermissions(lKey, tAccount); } } return false; } finally { // cleanup if (lKey != IntPtr.Zero) { RegCloseKey(lKey); } if ((tAccount.pSid != IntPtr.Zero) && (tAccount.SidPassedByCaller == true)) { FreeSid(tAccount.pSid); tAccount.pSid = IntPtr.Zero; } } }