Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

cmse.c File Reference

#include "cmp.h"

Go to the source code of this file.

Defines

#define SECURITY_CELL_LENGTH(pDescriptor)

Functions

NTSTATUS CmpSetSecurityDescriptorInfo (IN PCM_KEY_CONTROL_BLOCK kcb, IN PSECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR ModificationDescriptor, IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, IN POOL_TYPE PoolType, IN PGENERIC_MAPPING GenericMapping)
NTSTATUS CmpQuerySecurityDescriptorInfo (IN PCM_KEY_CONTROL_BLOCK kcb, IN PSECURITY_INFORMATION SecurityInformation, OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PULONG Length, IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor)
PCM_KEY_SECURITY CmpGetKeySecurity (IN PHHIVE Hive, IN PCM_KEY_NODE Key, OUT PHCELL_INDEX SecurityCell OPTIONAL)
VOID CmpGetObjectSecurity (IN HCELL_INDEX Cell, IN PHHIVE Hive, OUT PCM_KEY_SECURITY *Security, OUT PHCELL_INDEX SecurityCell OPTIONAL)
BOOLEAN CmpFindMatchingDescriptorCell (IN PHHIVE Hive, IN PCM_KEY_NODE Node, IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN ULONG Type, OUT PHCELL_INDEX MatchingCell)
BOOLEAN CmpInsertSecurityCellList (IN PHHIVE Hive, IN HCELL_INDEX NodeCell, IN HCELL_INDEX SecurityCell)
VOID CmpRemoveSecurityCellList (IN PHHIVE Hive, IN HCELL_INDEX SecurityCell)
ULONG CmpSecurityExceptionFilter (IN PEXCEPTION_POINTERS ExceptionPointers)
NTSTATUS CmpSecurityMethod (IN PVOID Object, IN SECURITY_OPERATION_CODE OperationCode, IN PSECURITY_INFORMATION SecurityInformation, IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PULONG CapturedLength, IN OUT PSECURITY_DESCRIPTOR *ObjectsSecurityDescriptor, IN POOL_TYPE PoolType, IN PGENERIC_MAPPING GenericMapping)
NTSTATUS CmpAssignSecurityDescriptor (IN PHHIVE Hive, IN HCELL_INDEX Cell, IN PCM_KEY_NODE Node, IN PSECURITY_DESCRIPTOR SecurityDescriptor)
BOOLEAN CmpCheckCreateAccess (IN PUNICODE_STRING RelativeName, IN PSECURITY_DESCRIPTOR Descriptor, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE PreviousMode, IN ACCESS_MASK AdditionalAccess, OUT PNTSTATUS AccessStatus)
BOOLEAN CmpCheckNotifyAccess (IN PCM_NOTIFY_BLOCK NotifyBlock, IN PHHIVE Hive, IN PCM_KEY_NODE Node)
PSECURITY_DESCRIPTOR CmpHiveRootSecurityDescriptor (VOID)
VOID CmpFreeSecurityDescriptor (IN PHHIVE Hive, IN HCELL_INDEX Cell)


Define Documentation

#define SECURITY_CELL_LENGTH pDescriptor   ) 
 

Value:

FIELD_OFFSET(CM_KEY_SECURITY,Descriptor) + \ RtlLengthSecurityDescriptor(pDescriptor)

Definition at line 95 of file cmse.c.

Referenced by CmpAssignSecurityDescriptor(), CmpSetSecurityDescriptorInfo(), and EhpAttachSecurity().


Function Documentation

NTSTATUS CmpAssignSecurityDescriptor IN PHHIVE  Hive,
IN HCELL_INDEX  Cell,
IN PCM_KEY_NODE  Node,
IN PSECURITY_DESCRIPTOR  SecurityDescriptor
 

Definition at line 697 of file cmse.c.

References ASSERT, ASSERT_NODE, Cell, CM_KEY_SECURITY_SIGNATURE, CML_FLOW, CMLOG, CmpDumpSecurityDescriptor, CmpFindMatchingDescriptorCell(), CmpInsertSecurityCellList(), CMS_SEC, _CM_KEY_SECURITY::Descriptor, _CM_KEY_SECURITY::DescriptorLength, HCELL_INDEX, HCELL_NIL, Hive, HvAllocateCell(), HvFreeCell(), HvGetCell, HvGetCellType, HvMarkCellDirty(), Name, PAGED_CODE, _CM_KEY_SECURITY::ReferenceCount, RtlLengthSecurityDescriptor(), SECURITY_CELL_LENGTH, and _CM_KEY_SECURITY::Signature.

Referenced by CmpCopyKeyPartial(), CmpSecurityMethod(), and CmpSyncKeyValues().

00706 : 00707 00708 This routine assigns the given security descriptor to the specified 00709 node in the configuration tree. 00710 00711 Arguments: 00712 00713 Hive - Supplies a pointer to the Hive for the node whose security 00714 descriptor will be assigned. 00715 00716 Cell - Supplies the HCELL_INDEX of the node whose security descriptor 00717 will be assigned. 00718 00719 Node - Supplies a pointer to the node whose security descriptor will 00720 be assigned. 00721 00722 SecurityDescriptor - Supplies a pointer to the security descriptor to 00723 be assigned to the node. 00724 00725 PoolType - Supplies the type of pool the SecurityDescriptor was a 00726 allocated from. 00727 00728 Return Value: 00729 00730 NTSTATUS - STATUS_SUCCESS if successful and an appropriate error value 00731 otherwise 00732 00733 --*/ 00734 00735 { 00736 HCELL_INDEX SecurityCell; 00737 PCM_KEY_SECURITY Security; 00738 ULONG DescriptorLength; 00739 ULONG Type; 00740 00741 PAGED_CODE(); 00742 // 00743 // Map the node that we need to assign the security descriptor to. 00744 // 00745 if (! HvMarkCellDirty(Hive, Cell)) { 00746 return STATUS_NO_LOG_SPACE; 00747 } 00748 ASSERT_NODE(Node); 00749 00750 CMLOG(CML_FLOW, CMS_SEC) { 00751 #if DBG 00752 UNICODE_STRING Name; 00753 00754 Name.MaximumLength = Name.Length = Node->NameLength; 00755 Name.Buffer = Node->Name; 00756 KdPrint(("CmpAssignSecurityDescriptor: '%wZ' (H %lx C %lx)\n",&Name,Hive,Cell )); 00757 KdPrint(("\tSecurityCell = %lx\n",Node->Security)); 00758 #endif 00759 } 00760 00761 ASSERT(Node->Security==HCELL_NIL); 00762 00763 // 00764 // This is a CreateKey, so the registry node has just been created and 00765 // the security descriptor we have been passed needs to be associated 00766 // with the new registry node and inserted into the hive. 00767 // 00768 CMLOG(CML_FLOW, CMS_SEC) { 00769 CmpDumpSecurityDescriptor(SecurityDescriptor, "ASSIGN DESCRIPTOR\n"); 00770 } 00771 00772 // 00773 // Try to find an existing security descriptor that matches this one. 00774 // If successful, then we don't need to allocate a new cell, we can 00775 // just point to the existing one and increment its reference count. 00776 // 00777 Type = HvGetCellType(Cell); 00778 if (!CmpFindMatchingDescriptorCell( Hive, 00779 Node, 00780 SecurityDescriptor, 00781 Type, 00782 &SecurityCell )) { 00783 // 00784 // No matching descriptor found, allocate and initialize a new one. 00785 // 00786 SecurityCell = HvAllocateCell(Hive, 00787 SECURITY_CELL_LENGTH(SecurityDescriptor), 00788 Type); 00789 if (SecurityCell == HCELL_NIL) { 00790 return STATUS_INSUFFICIENT_RESOURCES; 00791 } 00792 00793 // 00794 // Map the security cell 00795 // 00796 Security = (PCM_KEY_SECURITY) HvGetCell(Hive, SecurityCell); 00797 00798 // 00799 // Initialize the security cell 00800 // 00801 DescriptorLength = RtlLengthSecurityDescriptor(SecurityDescriptor); 00802 00803 Security->Signature = CM_KEY_SECURITY_SIGNATURE; 00804 Security->ReferenceCount = 1; 00805 Security->DescriptorLength = DescriptorLength; 00806 RtlMoveMemory( &(Security->Descriptor), 00807 SecurityDescriptor, 00808 DescriptorLength ); 00809 00810 // 00811 // Insert the new security descriptor into the list of security 00812 // cells. 00813 // 00814 if (!CmpInsertSecurityCellList(Hive,Cell,SecurityCell)) 00815 { 00816 HvFreeCell(Hive, SecurityCell); 00817 return STATUS_NO_LOG_SPACE; 00818 } 00819 00820 } else { 00821 00822 // 00823 // Found identical descriptor already existing. Map it in and 00824 // increment its reference count. 00825 // 00826 if (! HvMarkCellDirty(Hive, SecurityCell)) { 00827 return STATUS_NO_LOG_SPACE; 00828 } 00829 Security = (PCM_KEY_SECURITY) HvGetCell(Hive, SecurityCell); 00830 Security->ReferenceCount += 1; 00831 } 00832 00833 // 00834 // Initialize the reference in the node cell 00835 // 00836 Node->Security = SecurityCell; 00837 00838 CMLOG(CML_FLOW, CMS_SEC) { 00839 KdPrint(("\tSecurityCell = %lx\n",Node->Security)); 00840 } 00841 00842 return(STATUS_SUCCESS); 00843 }

BOOLEAN CmpCheckCreateAccess IN PUNICODE_STRING  RelativeName,
IN PSECURITY_DESCRIPTOR  Descriptor,
IN PACCESS_STATE  AccessState,
IN KPROCESSOR_MODE  PreviousMode,
IN ACCESS_MASK  AdditionalAccess,
OUT PNTSTATUS  AccessStatus
 

Definition at line 917 of file cmse.c.

References CML_FLOW, CMLOG, CmpDumpSecurityDescriptor, CmpKeyObjectType, CMS_SEC, FALSE, _OBJECT_TYPE_INITIALIZER::GenericMapping, NULL, PAGED_CODE, SeAccessCheck(), SeCreateObjectAuditAlarm(), SeLockSubjectContext(), SeUnlockSubjectContext(), TRUE, and _OBJECT_TYPE::TypeInfo.

Referenced by CmpDoCreate().

00928 : 00929 00930 This routine checks to see if we are allowed to create a sub-key in the 00931 given key, and performs auditing as appropriate. 00932 00933 Arguments: 00934 00935 RelativeName - Supplies the relative name of the key being created. 00936 00937 Descriptor - Supplies the security descriptor of the key in which 00938 the sub-key is to be created. 00939 00940 CreateAccess - The access mask corresponding to create access for 00941 this directory type. 00942 00943 AccessState - Checks for traverse access will typically be incidental 00944 to some other access attempt. Information on the current state of 00945 that access attempt is required so that the constituent access 00946 attempts may be associated with each other in the audit log. 00947 00948 PreviousMode - The previous processor mode. 00949 00950 AdditionalAccess - access rights in addition to KEY_CREATE_SUB_KEY 00951 that are required. (e.g. KEY_CREATE_LINK) 00952 00953 AccessStatus - Pointer to a variable to return the status code of the 00954 access attempt. In the case of failure this status code must be 00955 propagated back to the user. 00956 00957 Return Value: 00958 00959 BOOLEAN - TRUE if access is allowed and FALSE otherwise. AccessStatus 00960 contains the status code to be passed back to the caller. It is not 00961 correct to simply pass back STATUS_ACCESS_DENIED, since this will have 00962 to change with the advent of mandatory access control. 00963 00964 --*/ 00965 00966 { 00967 BOOLEAN AccessAllowed; 00968 ACCESS_MASK GrantedAccess = 0; 00969 BOOLEAN AuditPerformed = FALSE; 00970 00971 PAGED_CODE(); 00972 CMLOG(CML_FLOW, CMS_SEC) { 00973 KdPrint(("CmpCheckCreateAccess:\n")); 00974 } 00975 00976 SeLockSubjectContext( &AccessState->SubjectSecurityContext ); 00977 00978 AccessAllowed = SeAccessCheck( 00979 Descriptor, 00980 &AccessState->SubjectSecurityContext, 00981 TRUE, // Token is read locked 00982 (KEY_CREATE_SUB_KEY | AdditionalAccess), 00983 0, 00984 NULL, 00985 &CmpKeyObjectType->TypeInfo.GenericMapping, 00986 PreviousMode, 00987 &GrantedAccess, 00988 AccessStatus 00989 ); 00990 00991 // 00992 // if the security guys ever get around to implementing this, 00993 // put this call back in. 00994 // 00995 #if 0 00996 // 00997 // WARNNOTE John Vert (jvert) 22-Jan-92 00998 // We don't have a Directory Object handy, and the auditing currently 00999 // ignores it anyway. 01000 // 01001 01002 SeCreateObjectAuditAlarm( 01003 &AccessState->OperationID, 01004 NULL, // <- see WARNNOTE 01005 NULL, // Need component name 01006 Descriptor, 01007 &AccessState->SubjectSecurityContext, 01008 KEY_CREATE_SUB_KEY, 01009 AccessState->PrivilegesUsed, 01010 AccessAllowed, 01011 &AuditPerformed, 01012 PreviousMode 01013 ); 01014 #endif 01015 01016 SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); 01017 01018 CMLOG(CML_FLOW, CMS_SEC) { 01019 KdPrint(("Create access %s\n",AccessAllowed ? "granted" : "denied")); 01020 #if DBG 01021 if (!AccessAllowed) { 01022 CmpDumpSecurityDescriptor(Descriptor, "DENYING DESCRIPTOR"); 01023 } 01024 #endif 01025 } 01026 01027 return(AccessAllowed); 01028 }

BOOLEAN CmpCheckNotifyAccess IN PCM_NOTIFY_BLOCK  NotifyBlock,
IN PHHIVE  Hive,
IN PCM_KEY_NODE  Node
 

Definition at line 1032 of file cmse.c.

References ASSERT_CM_LOCK_OWNED, CML_FLOW, CMLOG, CmpDumpSecurityDescriptor, CmpGetKeySecurity(), CmpKeyObjectType, CMS_SEC, _CM_KEY_SECURITY::Descriptor, _OBJECT_TYPE_INITIALIZER::GenericMapping, Hive, NTSTATUS(), NULL, PAGED_CODE, SeAccessCheck(), SeLockSubjectContext(), SeUnlockSubjectContext(), Status, TRUE, _OBJECT_TYPE::TypeInfo, and UserMode.

Referenced by CmpNotifyTriggerCheck().

01039 : 01040 01041 Check whether the subject process/thread/user specified by the 01042 security data in the NotifyBlock has required access to the 01043 key specified by Hive.Cell. 01044 01045 Arguments: 01046 01047 NotifyBlock - pointer to structure that describes the notify 01048 operation, including the identity of the subject 01049 that opened the notify. 01050 01051 Hive - Supplies pointer to hive containing Node. 01052 01053 Node - Supplies pointer to key of interest. 01054 01055 Return Value: 01056 01057 TRUE if RequiredAccess is in fact possessed by the subject, 01058 else FALSE. 01059 01060 --*/ 01061 { 01062 PCM_KEY_SECURITY Security; 01063 PSECURITY_DESCRIPTOR SecurityDescriptor; 01064 NTSTATUS Status; 01065 BOOLEAN AccessAllowed; 01066 ACCESS_MASK GrantedAccess = 0; 01067 01068 ASSERT_CM_LOCK_OWNED(); 01069 PAGED_CODE(); 01070 01071 01072 CMLOG(CML_FLOW, CMS_SEC) { 01073 KdPrint(("CmpCheckAccessForNotify:\n")); 01074 } 01075 Security = CmpGetKeySecurity(Hive, 01076 Node, 01077 NULL); 01078 01079 SeLockSubjectContext( &NotifyBlock->SubjectContext ); 01080 01081 SecurityDescriptor = &Security->Descriptor; 01082 AccessAllowed = SeAccessCheck( SecurityDescriptor, 01083 &NotifyBlock->SubjectContext, 01084 TRUE, 01085 KEY_NOTIFY, 01086 0, 01087 NULL, 01088 &CmpKeyObjectType->TypeInfo.GenericMapping, 01089 UserMode, 01090 &GrantedAccess, 01091 &Status ); 01092 01093 SeUnlockSubjectContext( &NotifyBlock->SubjectContext ); 01094 01095 CMLOG(CML_FLOW, CMS_SEC) { 01096 KdPrint(("Notify access %s\n",AccessAllowed ? "granted" : "denied")); 01097 #if DBG 01098 if (!AccessAllowed) { 01099 CmpDumpSecurityDescriptor(SecurityDescriptor, "DENYING DESCRIPTOR"); 01100 } 01101 #endif 01102 } 01103 01104 return AccessAllowed; 01105 }

BOOLEAN CmpFindMatchingDescriptorCell IN PHHIVE  Hive,
IN PCM_KEY_NODE  Node,
IN PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN ULONG  Type,
OUT PHCELL_INDEX  MatchingCell
 

Definition at line 1545 of file cmse.c.

References CML_FLOW, CMLOG, CmpFindSubKeyByNumber(), CmpGetKeySecurity(), CMS_SEC, _CM_KEY_SECURITY::Descriptor, _CM_KEY_SECURITY::DescriptorLength, FALSE, HCELL_INDEX, HCELL_NIL, Hive, HvGetCell, HvGetCellType, KEY_HIVE_ENTRY, NTSTATUS(), PAGED_CODE, RtlLengthSecurityDescriptor(), Status, and TRUE.

Referenced by CmpAssignSecurityDescriptor(), and CmpSetSecurityDescriptorInfo().

01555 : 01556 01557 This routine attempts to find a security descriptor in the hive that 01558 is identical to the one passed in. If it finds one, it returns its 01559 cell index. 01560 01561 Currently, this routine checks the security descriptors of the parent 01562 and siblings of the node to find a match. 01563 01564 Arguments: 01565 01566 Hive - Supplies a pointer to the hive control structure for the node. 01567 01568 Cell - Supplies the cell index of the node 01569 01570 SecurityDescriptor - Supplies the cooked security descriptor which 01571 should be searched for. 01572 01573 Type - Indicates whether the Security Descriptor that matches must 01574 be in Stable or Volatile store 01575 01576 MatchingCell - Returns the cell index of a security cell whose 01577 security descriptor is identical to SecurityDescriptor. 01578 Valid only if TRUE is returned. 01579 01580 Return Value: 01581 01582 TRUE - Matching security descriptor found. MatchingCell returns the 01583 cell index of the matching security descriptor. 01584 01585 FALSE - No matching security descriptor found. MatchingCell is invalid. 01586 01587 --*/ 01588 01589 { 01590 PCM_KEY_NODE ChildCheckNode; 01591 PCM_KEY_NODE SiblingNode; 01592 PCM_KEY_SECURITY Security; 01593 PCM_KEY_NODE ParentNode; 01594 HCELL_INDEX SiblingCell; 01595 NTSTATUS Status; 01596 ULONG DescriptorLength; 01597 ULONG index; 01598 01599 PAGED_CODE(); 01600 01601 DescriptorLength = RtlLengthSecurityDescriptor(SecurityDescriptor); 01602 01603 // 01604 // Check to see if it's a root node or not. 01605 // 01606 if (Node->Flags & KEY_HIVE_ENTRY) { 01607 01608 // 01609 // Never share security descriptors across hive boundaries. 01610 // Go directly to the child key check. 01611 // 01612 ChildCheckNode = Node; 01613 goto RetryMyChildren; 01614 } 01615 01616 ParentNode = (PCM_KEY_NODE)HvGetCell(Hive,Node->Parent); 01617 01618 Security = CmpGetKeySecurity(Hive, 01619 ParentNode, 01620 MatchingCell); 01621 01622 if ((DescriptorLength==Security->DescriptorLength) && 01623 (Type == HvGetCellType(*MatchingCell)) && 01624 (RtlEqualMemory(SecurityDescriptor, 01625 &(Security->Descriptor), 01626 DescriptorLength))) { 01627 // 01628 // We have found a match. 01629 // 01630 CMLOG(CML_FLOW, CMS_SEC) { 01631 KdPrint(("CmpFindMatchingDescriptor: Cell's descriptor matched parent\n")); 01632 } 01633 return(TRUE); 01634 } 01635 01636 // 01637 // Parent didn't match. Go check all the siblings. 01638 // 01639 ChildCheckNode = ParentNode; 01640 01641 // 01642 // Below loop gets executed twice. The first time we check the siblings of 01643 // the target node's parents. The second time, we check the target node's 01644 // own children. 01645 // 01646 RetryMyChildren: 01647 index=0; 01648 while (TRUE) { 01649 SiblingCell = CmpFindSubKeyByNumber(Hive,ChildCheckNode,index++); 01650 if (SiblingCell == HCELL_NIL) { 01651 // 01652 // out of siblings 01653 // 01654 return(FALSE); 01655 } 01656 SiblingNode = (PCM_KEY_NODE)HvGetCell(Hive,SiblingCell); 01657 01658 if (SiblingNode != Node) { 01659 01660 // 01661 // We have a sibling, so get its security descriptor 01662 // 01663 Security = CmpGetKeySecurity(Hive, 01664 SiblingNode, 01665 MatchingCell); 01666 01667 // 01668 // Compare its security descriptor to ours 01669 // 01670 01671 if ((DescriptorLength==Security->DescriptorLength) && 01672 (Type == HvGetCellType(*MatchingCell)) && 01673 (RtlEqualMemory(SecurityDescriptor, 01674 &(Security->Descriptor), 01675 DescriptorLength))) { 01676 // 01677 // We have found a match. 01678 // 01679 CMLOG(CML_FLOW, CMS_SEC) { 01680 KdPrint(("CmpFindMatchingDescriptor: Cell's descriptor ")); 01681 KdPrint(("matched sibling %d\n",index)); 01682 } 01683 return(TRUE); 01684 } 01685 } 01686 } 01687 01688 if (ChildCheckNode == ParentNode) { 01689 // 01690 // Do the second iteration. 01691 // 01692 ChildCheckNode = Node; 01693 goto RetryMyChildren; 01694 } 01695 01696 CMLOG(CML_FLOW, CMS_SEC) { 01697 KdPrint(("CmpFindMatchingDescriptor: no matching descriptor found\n")); 01698 } 01699 return(FALSE); 01700 }

VOID CmpFreeSecurityDescriptor IN PHHIVE  Hive,
IN HCELL_INDEX  Cell
 

Definition at line 1464 of file cmse.c.

References ASSERT_NODE, ASSERT_SECURITY, Cell, CML_FLOW, CMLOG, CmpRemoveSecurityCellList(), CMS_SEC, HCELL_INDEX, HCELL_NIL, Hive, HvFreeCell(), HvGetCell, _CELL_DATA::_u::KeyNode, _CELL_DATA::_u::KeySecurity, PAGED_CODE, _CM_KEY_SECURITY::ReferenceCount, _CM_KEY_NODE::Security, and _CELL_DATA::u.

01471 : 01472 01473 Frees the security descriptor associated with a particular node. This 01474 can only happen when the node is actually being deleted from the 01475 registry. 01476 01477 NOTE: Caller is expected to have already marked relevent cells dirty. 01478 01479 Arguments: 01480 01481 Hive - Supplies thepointer to hive control structure for hive of interest 01482 01483 Cell - Supplies index for cell to free storage for (the target) 01484 01485 Return Value: 01486 01487 None. 01488 01489 --*/ 01490 01491 { 01492 PCELL_DATA Node; 01493 PCELL_DATA Security; 01494 HCELL_INDEX SecurityCell; 01495 01496 PAGED_CODE(); 01497 CMLOG(CML_FLOW, CMS_SEC) { 01498 KdPrint(("CmpFreeSecurityDescriptor for cell %ld\n",Cell)); 01499 } 01500 01501 // 01502 // Map in the cell whose security descriptor is being freed 01503 // 01504 Node = HvGetCell(Hive, Cell); 01505 ASSERT_NODE(&(Node->u.KeyNode)); 01506 01507 // 01508 // Map in the cell containing the security descriptor. 01509 // 01510 SecurityCell = Node->u.KeyNode.Security; 01511 Security = HvGetCell(Hive, SecurityCell); 01512 ASSERT_SECURITY(&(Security->u.KeySecurity)); 01513 01514 01515 if (Security->u.KeySecurity.ReferenceCount == 1) { 01516 01517 // 01518 // This is the only cell that references this security descriptor, 01519 // so it is ok to free it now. 01520 // 01521 CmpRemoveSecurityCellList(Hive, SecurityCell); 01522 HvFreeCell(Hive, SecurityCell); 01523 CMLOG(CML_FLOW, CMS_SEC) { 01524 KdPrint(("CmpFreeSecurityDescriptor: freeing security cell\n")); 01525 } 01526 } else { 01527 01528 // 01529 // More than one node references this security descriptor, so 01530 // just decrement the reference count. 01531 // 01532 Security->u.KeySecurity.ReferenceCount -= 1; 01533 CMLOG(CML_FLOW, CMS_SEC) { 01534 KdPrint(("CmpFreeSecurityDescriptor: decrementing reference count\n")); 01535 } 01536 } 01537 01538 // 01539 // Zero out the pointer to the security descriptdr in the main cell 01540 // 01541 Node->u.KeyNode.Security = HCELL_NIL; 01542 }

PCM_KEY_SECURITY CmpGetKeySecurity IN PHHIVE  Hive,
IN PCM_KEY_NODE  Key,
OUT PHCELL_INDEX SecurityCell  OPTIONAL
 

Definition at line 1165 of file cmse.c.

References ASSERT, ASSERT_NODE, ASSERT_SECURITY, CM_KEY_NODE_SIGNATURE, CML_FLOW, CMLOG, CMS_SEC, HCELL_INDEX, Hive, HvGetCell, Key, Name, and PAGED_CODE.

Referenced by CmpCheckNotifyAccess(), CmpFindMatchingDescriptorCell(), CmpGetObjectSecurity(), and CmpSetSecurityDescriptorInfo().

01173 : 01174 01175 This routine returns the security of a registry key. 01176 01177 Arguments: 01178 01179 Hive - Supplies the hive the object's cell is in. 01180 01181 Key - Supplies a pointer to the key node. 01182 01183 SecurityCell - Returns the index of the security cell 01184 01185 Return Value: 01186 01187 Returns a pointer to the security cell of the object 01188 01189 --*/ 01190 01191 { 01192 HCELL_INDEX CellIndex; 01193 PCM_KEY_SECURITY Security; 01194 01195 PAGED_CODE(); 01196 01197 ASSERT(Key->Signature == CM_KEY_NODE_SIGNATURE); 01198 ASSERT_NODE(Key); 01199 01200 CMLOG(CML_FLOW, CMS_SEC) { 01201 #if DBG 01202 UNICODE_STRING Name; 01203 01204 Name.MaximumLength = Name.Length = Key->NameLength; 01205 Name.Buffer = Key->Name; 01206 KdPrint(("CmpGetObjectSecurity for: ")); 01207 KdPrint(("%wZ\n", &Name)); 01208 #endif 01209 } 01210 01211 CellIndex = Key->Security; 01212 01213 // 01214 // Map in the security descriptor cell 01215 // 01216 Security = (PCM_KEY_SECURITY) HvGetCell(Hive, CellIndex); 01217 ASSERT_SECURITY(Security); 01218 01219 if (ARGUMENT_PRESENT(SecurityCell)) { 01220 *SecurityCell = CellIndex; 01221 } 01222 01223 return(Security); 01224 }

VOID CmpGetObjectSecurity IN HCELL_INDEX  Cell,
IN PHHIVE  Hive,
OUT PCM_KEY_SECURITY Security,
OUT PHCELL_INDEX SecurityCell  OPTIONAL
 

Definition at line 1109 of file cmse.c.

References Cell, CML_FLOW, CMLOG, CmpGetKeySecurity(), CMS_SEC, HCELL_INDEX, Hive, HvGetCell, _CM_KEY_NODE::Name, Name, _CM_KEY_NODE::NameLength, PAGED_CODE, and _CM_KEY_NODE::Security.

Referenced by EhGetKeySecurity().

01118 : 01119 01120 This routine maps in the security cell of a registry object. 01121 01122 Arguments: 01123 01124 Cell - Supplies the cell index of the object. 01125 01126 Hive - Supplies the hive the object's cell is in. 01127 01128 Security - Returns a pointer to the security cell of the object. 01129 01130 SecurityCell - Returns the index of the security cell 01131 01132 Return Value: 01133 01134 NONE. 01135 01136 --*/ 01137 01138 { 01139 HCELL_INDEX CellIndex; 01140 PCM_KEY_NODE Node; 01141 01142 PAGED_CODE(); 01143 // 01144 // Map the node we need to get the security descriptor for 01145 // 01146 Node = (PCM_KEY_NODE) HvGetCell(Hive, Cell); 01147 01148 CMLOG(CML_FLOW, CMS_SEC) { 01149 #if DBG 01150 UNICODE_STRING Name; 01151 01152 Name.MaximumLength = Name.Length = Node->NameLength; 01153 Name.Buffer = Node->Name; 01154 KdPrint(("CmpGetObjectSecurity for: ")); 01155 KdPrint(("%wZ\n", &Name)); 01156 #endif 01157 } 01158 01159 *Security = CmpGetKeySecurity(Hive,Node,SecurityCell); 01160 01161 return; 01162 }

PSECURITY_DESCRIPTOR CmpHiveRootSecurityDescriptor VOID   ) 
 

Definition at line 1227 of file cmse.c.

References ASSERT, CML_MAJOR, CMLOG, CMS_SEC, ExAllocatePool, ExFreePool(), FALSE, KeBugCheckEx(), NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, PagedPool, RtlAddAccessAllowedAce(), RtlCreateAcl(), RtlCreateSecurityDescriptor(), RtlGetAce(), RtlInitializeSid(), RtlLengthRequiredSid(), RtlSetDaclSecurityDescriptor(), RtlSubAuthoritySid(), RtlValidSid(), SeLengthSid, Status, TRUE, and WorldSid.

Referenced by CmInitSystem1(), CmpCreateRegistryRoot(), CmpInitializeHiveList(), CmpInitializeSystemHive(), and CmpSetVersionData().

01232 : 01233 01234 This routine allocates and initializes the default security descriptor 01235 for a system-created registry key. 01236 01237 The caller is responsible for freeing the allocated security descriptor 01238 when he is done with it. 01239 01240 Arguments: 01241 01242 None 01243 01244 Return Value: 01245 01246 Pointer to an initialized security descriptor if successful. 01247 01248 Bugcheck otherwise. 01249 01250 --*/ 01251 01252 { 01253 NTSTATUS Status; 01254 PSECURITY_DESCRIPTOR SecurityDescriptor=NULL; 01255 PACL Acl=NULL; 01256 PACL AclCopy; 01257 PSID WorldSid=NULL; 01258 PSID RestrictedSid=NULL; 01259 PSID SystemSid=NULL; 01260 PSID AdminSid=NULL; 01261 SID_IDENTIFIER_AUTHORITY WorldAuthority = SECURITY_WORLD_SID_AUTHORITY; 01262 SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; 01263 ULONG AceLength; 01264 ULONG AclLength; 01265 PACE_HEADER AceHeader; 01266 01267 PAGED_CODE(); 01268 01269 // 01270 // Allocate and initialize the SIDs we will need. 01271 // 01272 WorldSid = ExAllocatePool(PagedPool, RtlLengthRequiredSid(1)); 01273 RestrictedSid = ExAllocatePool(PagedPool, RtlLengthRequiredSid(1)); 01274 SystemSid = ExAllocatePool(PagedPool, RtlLengthRequiredSid(1)); 01275 AdminSid = ExAllocatePool(PagedPool, RtlLengthRequiredSid(2)); 01276 if ((WorldSid == NULL) || 01277 (RestrictedSid == NULL) || 01278 (SystemSid == NULL) || 01279 (AdminSid == NULL)) { 01280 01281 KeBugCheckEx(REGISTRY_ERROR, 10, 0, 0, 0); 01282 } 01283 01284 if ((!NT_SUCCESS(RtlInitializeSid(WorldSid, &WorldAuthority, 1))) || 01285 (!NT_SUCCESS(RtlInitializeSid(RestrictedSid, &NtAuthority, 1))) || 01286 (!NT_SUCCESS(RtlInitializeSid(SystemSid, &NtAuthority, 1))) || 01287 (!NT_SUCCESS(RtlInitializeSid(AdminSid, &NtAuthority, 2)))) { 01288 KeBugCheckEx(REGISTRY_ERROR, 10, 1, 0, 0); 01289 } 01290 01291 *(RtlSubAuthoritySid(WorldSid, 0)) = SECURITY_WORLD_RID; 01292 01293 *(RtlSubAuthoritySid(RestrictedSid, 0)) = SECURITY_RESTRICTED_CODE_RID; 01294 01295 *(RtlSubAuthoritySid(SystemSid, 0)) = SECURITY_LOCAL_SYSTEM_RID; 01296 01297 *(RtlSubAuthoritySid(AdminSid, 0)) = SECURITY_BUILTIN_DOMAIN_RID; 01298 *(RtlSubAuthoritySid(AdminSid, 1)) = DOMAIN_ALIAS_RID_ADMINS; 01299 01300 ASSERT(RtlValidSid(WorldSid)); 01301 ASSERT(RtlValidSid(RestrictedSid)); 01302 ASSERT(RtlValidSid(SystemSid)); 01303 ASSERT(RtlValidSid(AdminSid)); 01304 01305 // 01306 // Compute the size of the ACE list 01307 // 01308 01309 AceLength = (SeLengthSid(WorldSid) - 01310 sizeof(ULONG) + 01311 sizeof(ACCESS_ALLOWED_ACE)) 01312 + (SeLengthSid(RestrictedSid) - 01313 sizeof(ULONG) + 01314 sizeof(ACCESS_ALLOWED_ACE)) 01315 + (SeLengthSid(SystemSid) - 01316 sizeof(ULONG) + 01317 sizeof(ACCESS_ALLOWED_ACE)) 01318 + (SeLengthSid(AdminSid) - 01319 sizeof(ULONG) + 01320 sizeof(ACCESS_ALLOWED_ACE)); 01321 01322 // 01323 // Allocate and initialize the ACL 01324 // 01325 01326 AclLength = AceLength + sizeof(ACL); 01327 Acl = ExAllocatePool(PagedPool, AclLength); 01328 if (Acl == NULL) { 01329 CMLOG(CML_MAJOR, CMS_SEC) { 01330 KdPrint(("CmpHiveRootSecurityDescriptor: couldn't allocate ACL\n")); 01331 } 01332 01333 KeBugCheckEx(REGISTRY_ERROR, 10, 2, 0, 0); 01334 } 01335 01336 Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION); 01337 if (!NT_SUCCESS(Status)) { 01338 CMLOG(CML_MAJOR, CMS_SEC) { 01339 KdPrint(("CmpHiveRootSecurityDescriptor: couldn't initialize ACL\n")); 01340 } 01341 KeBugCheckEx(REGISTRY_ERROR, 10, 3, 0, 0); 01342 } 01343 01344 // 01345 // Now add the ACEs to the ACL 01346 // 01347 Status = RtlAddAccessAllowedAce(Acl, 01348 ACL_REVISION, 01349 KEY_ALL_ACCESS, 01350 SystemSid); 01351 if (NT_SUCCESS(Status)) { 01352 Status = RtlAddAccessAllowedAce(Acl, 01353 ACL_REVISION, 01354 KEY_ALL_ACCESS, 01355 AdminSid); 01356 } 01357 if (NT_SUCCESS(Status)) { 01358 Status = RtlAddAccessAllowedAce(Acl, 01359 ACL_REVISION, 01360 KEY_READ, 01361 WorldSid); 01362 } 01363 if (NT_SUCCESS(Status)) { 01364 Status = RtlAddAccessAllowedAce(Acl, 01365 ACL_REVISION, 01366 KEY_READ, 01367 RestrictedSid); 01368 } 01369 if (!NT_SUCCESS(Status)) { 01370 CMLOG(CML_MAJOR, CMS_SEC) { 01371 KdPrint(("CmpHiveRootSecurityDescriptor: RtlAddAce failed status %08lx\n", Status)); 01372 } 01373 01374 KeBugCheckEx(REGISTRY_ERROR, 10, 4, 0, 0); 01375 } 01376 01377 // 01378 // Make the ACEs inheritable 01379 // 01380 Status = RtlGetAce(Acl,0,&AceHeader); 01381 ASSERT(NT_SUCCESS(Status)); 01382 AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; 01383 01384 Status = RtlGetAce(Acl,1,&AceHeader); 01385 ASSERT(NT_SUCCESS(Status)); 01386 AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; 01387 01388 Status = RtlGetAce(Acl,2,&AceHeader); 01389 ASSERT(NT_SUCCESS(Status)); 01390 AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; 01391 01392 Status = RtlGetAce(Acl,3,&AceHeader); 01393 ASSERT(NT_SUCCESS(Status)); 01394 AceHeader->AceFlags |= CONTAINER_INHERIT_ACE; 01395 // 01396 // We are finally ready to allocate and initialize the security descriptor 01397 // Allocate enough space to hold both the security descriptor and the 01398 // ACL. This allows us to free the whole thing at once when we are 01399 // done with it. 01400 // 01401 01402 SecurityDescriptor = ExAllocatePool( 01403 PagedPool, 01404 sizeof(SECURITY_DESCRIPTOR) + AclLength 01405 ); 01406 01407 if (SecurityDescriptor == NULL) { 01408 CMLOG(CML_MAJOR, CMS_SEC) { 01409 KdPrint(("CmpHiveRootSecurityDescriptor: Couldn't allocate Sec. Desc.\n")); 01410 } 01411 KeBugCheckEx(REGISTRY_ERROR, 10, 5, 0, 0); 01412 } 01413 01414 AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor+1); 01415 RtlMoveMemory(AclCopy, Acl, AclLength); 01416 01417 Status = RtlCreateSecurityDescriptor( SecurityDescriptor, 01418 SECURITY_DESCRIPTOR_REVISION ); 01419 if (!NT_SUCCESS(Status)) { 01420 CMLOG(CML_MAJOR, CMS_SEC) { 01421 KdPrint(("CmpHiveRootSecurityDescriptor: CreateSecDesc failed %08lx\n",Status)); 01422 } 01423 ExFreePool(SecurityDescriptor); 01424 SecurityDescriptor=NULL; 01425 KeBugCheckEx(REGISTRY_ERROR, 10, 6, 0, 0); 01426 } 01427 01428 Status = RtlSetDaclSecurityDescriptor( SecurityDescriptor, 01429 TRUE, 01430 AclCopy, 01431 FALSE ); 01432 if (!NT_SUCCESS(Status)) { 01433 CMLOG(CML_MAJOR, CMS_SEC) { 01434 KdPrint(("CmpHiveRootSecurityDescriptor: SetDacl failed %08lx\n",Status)); 01435 } 01436 ExFreePool(SecurityDescriptor); 01437 SecurityDescriptor=NULL; 01438 KeBugCheckEx(REGISTRY_ERROR, 10, 7, 0, 0); 01439 } 01440 01441 // 01442 // free any allocations we made 01443 // 01444 if (WorldSid!=NULL) { 01445 ExFreePool(WorldSid); 01446 } 01447 if (RestrictedSid!=NULL) { 01448 ExFreePool(RestrictedSid); 01449 } 01450 if (SystemSid!=NULL) { 01451 ExFreePool(SystemSid); 01452 } 01453 if (AdminSid!=NULL) { 01454 ExFreePool(AdminSid); 01455 } 01456 if (Acl!=NULL) { 01457 ExFreePool(Acl); 01458 } 01459 01460 return(SecurityDescriptor); 01461 }

BOOLEAN CmpInsertSecurityCellList IN PHHIVE  Hive,
IN HCELL_INDEX  NodeCell,
IN HCELL_INDEX  SecurityCell
 

Definition at line 1704 of file cmse.c.

References ASSERT_NODE, ASSERT_SECURITY, _CM_KEY_SECURITY::Blink, Cell, CML_FLOW, CMLOG, CMS_SEC, FALSE, _CM_KEY_NODE::Flags, _CM_KEY_SECURITY::Flink, Hive, HvGetCell, HvGetCellType, HvMarkCellDirty(), KEY_HIVE_ENTRY, PAGED_CODE, _CM_KEY_NODE::Parent, _CM_KEY_NODE::Security, TRUE, and Volatile.

Referenced by CmpAssignSecurityDescriptor().

01711 : 01712 01713 Inserts a newly-created security cell into the per-hive linked list of 01714 security cells. 01715 01716 NOTE: Assumes that NodeCell and SecurityCell have already been 01717 marked dirty. 01718 01719 Arguments: 01720 01721 Hive - Supplies a pointer to the hive control structure. 01722 01723 NodeCell - Supplies the cell index of the node that owns the security cell 01724 01725 SecurityCell - Supplies the cell index of the security cell. 01726 01727 Return Value: 01728 01729 TRUE - it worked 01730 01731 FALSE - some failure - generally STATUS_NO_LOG_SPACE 01732 01733 --*/ 01734 01735 { 01736 PCM_KEY_SECURITY FlinkCell; 01737 PCM_KEY_SECURITY BlinkCell; 01738 PCM_KEY_SECURITY Cell; 01739 PCM_KEY_NODE Node; 01740 PCM_KEY_NODE ParentNode; 01741 01742 PAGED_CODE(); 01743 // 01744 // If the new cell's storage type is Volatile, simply make it the 01745 // anchor of it's own list. (Volatile security entries will disappear 01746 // at reboot, restore, etc, so we don't need the list to hunt them 01747 // down at those times.) 01748 // 01749 // Else, the storage type is Stable. 01750 // Map in the node that owns the new security cell. If it is a root 01751 // cell, then we are creating the hive for the first time, so this is 01752 // the only security cell in the list. If it is not a root cell, then 01753 // we simply find its parent's security cell and stick the new security 01754 // cell into the list immediately after it. 01755 // 01756 Cell = (PCM_KEY_SECURITY) HvGetCell(Hive, SecurityCell); 01757 ASSERT_SECURITY(Cell); 01758 01759 if (HvGetCellType(SecurityCell) == Volatile) { 01760 01761 Cell->Flink = Cell->Blink = SecurityCell; 01762 01763 } else { 01764 01765 Node = (PCM_KEY_NODE) HvGetCell(Hive, NodeCell); 01766 ASSERT_NODE(Node); 01767 01768 if (Node->Flags & KEY_HIVE_ENTRY) { 01769 // 01770 // This must be the hive creation, so this cell becomes the anchor 01771 // for the list. 01772 // 01773 CMLOG(CML_FLOW, CMS_SEC) { 01774 KdPrint(("CmpInsertSecurityCellList: hive creation\n")); 01775 } 01776 Cell->Flink = Cell->Blink = SecurityCell; 01777 01778 } else { 01779 CMLOG(CML_FLOW, CMS_SEC) { 01780 KdPrint(("CmpInsertSecurityCellList: insert at parent\n")); 01781 } 01782 // 01783 // Map in the node's parent's security cell, so we can hook into 01784 // the list there. 01785 // 01786 ParentNode = (PCM_KEY_NODE) HvGetCell(Hive, Node->Parent); 01787 ASSERT_NODE(ParentNode); 01788 BlinkCell = (PCM_KEY_SECURITY) HvGetCell( 01789 Hive, 01790 ParentNode->Security 01791 ); 01792 ASSERT_SECURITY(BlinkCell); 01793 01794 // 01795 // Map in the Flink of the parent's security cell. 01796 // 01797 FlinkCell = (PCM_KEY_SECURITY) HvGetCell( 01798 Hive, 01799 BlinkCell->Flink 01800 ); 01801 ASSERT_SECURITY(FlinkCell); 01802 01803 if (! (HvMarkCellDirty(Hive, ParentNode->Security) && 01804 HvMarkCellDirty(Hive, BlinkCell->Flink))) 01805 { 01806 return FALSE; 01807 } 01808 01809 // 01810 // Insert the new security cell in between the Flink and Blink cells 01811 // 01812 Cell->Flink = BlinkCell->Flink; 01813 Cell->Blink = FlinkCell->Blink; 01814 BlinkCell->Flink = SecurityCell; 01815 FlinkCell->Blink = SecurityCell; 01816 } 01817 } 01818 return TRUE; 01819 }

NTSTATUS CmpQuerySecurityDescriptorInfo IN PCM_KEY_CONTROL_BLOCK  kcb,
IN PSECURITY_INFORMATION  SecurityInformation,
OUT PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN OUT PULONG  Length,
IN OUT PSECURITY_DESCRIPTOR *  ObjectsSecurityDescriptor
 

Definition at line 847 of file cmse.c.

References CML_FLOW, CMLOG, CMS_SEC, _CM_KEY_SECURITY::Descriptor, HvGetCell, kcb(), NTSTATUS(), PAGED_CODE, SeQuerySecurityDescriptorInfo(), and Status.

Referenced by CmpSecurityMethod().

00857 : 00858 00859 This routine will extract the desired information from the 00860 passed security descriptor and return the information in 00861 the passed buffer as a security descriptor in absolute format. 00862 00863 Arguments: 00864 00865 Key - Supplies a pointer to the CM_KEY_REFERENCE for the node whose 00866 security descriptor will be deleted. 00867 00868 SecurityInformation - Specifies what information is being queried. 00869 00870 SecurityDescriptor - Supplies the buffer to output the requested 00871 information into. 00872 00873 This buffer has been probed only to the size indicated by 00874 the Length parameter. Since it still points into user space, 00875 it must always be accessed in a try clause. 00876 00877 Length - Supplies the address of a variable containing the length of 00878 the security descriptor buffer. Upon return this variable will 00879 contain the length needed to store the requested information. 00880 00881 ObjectsSecurityDescriptor - Supplies the address of a pointer to 00882 the objects security descriptor. The passed security descriptor 00883 must be in self-relative format. 00884 00885 00886 Return Value: 00887 00888 NTSTATUS - STATUS_SUCCESS if successful and an appropriate error value 00889 otherwise 00890 00891 --*/ 00892 00893 { 00894 NTSTATUS Status; 00895 PCM_KEY_SECURITY Security; 00896 PSECURITY_DESCRIPTOR CellSecurityDescriptor; 00897 00898 PAGED_CODE(); 00899 CMLOG(CML_FLOW, CMS_SEC) { 00900 KdPrint(("CmpQuerySecurityDescriptorInfo:\n")); 00901 } 00902 00903 Security = (PCM_KEY_SECURITY) HvGetCell(kcb->KeyHive, kcb->Security); 00904 00905 CellSecurityDescriptor = &Security->Descriptor; 00906 00907 Status = SeQuerySecurityDescriptorInfo( SecurityInformation, 00908 SecurityDescriptor, 00909 Length, 00910 &CellSecurityDescriptor ); 00911 00912 return(Status); 00913 }

VOID CmpRemoveSecurityCellList IN PHHIVE  Hive,
IN HCELL_INDEX  SecurityCell
 

Definition at line 1823 of file cmse.c.

References ASSERT, _CM_KEY_SECURITY::Blink, Cell, CML_FLOW, CMLOG, CMS_SEC, _CM_KEY_SECURITY::Flink, Hive, HvGetCell, and PAGED_CODE.

Referenced by CmpFreeSecurityDescriptor(), and CmpSetSecurityDescriptorInfo().

01829 : 01830 01831 Removes a security cell from the per-hive linked list of security cells. 01832 (This means the cell is going to be deleted!) 01833 01834 NOTE: Caller is expected to have already marked relevent cells dirty 01835 01836 Arguments: 01837 01838 Hive - Supplies a pointer to the hive control structure 01839 01840 SecurityCell - Supplies the cell index of the security cell to be 01841 removed 01842 01843 Return Value: 01844 01845 None. 01846 01847 --*/ 01848 01849 { 01850 PCM_KEY_SECURITY FlinkCell; 01851 PCM_KEY_SECURITY BlinkCell; 01852 PCM_KEY_SECURITY Cell; 01853 01854 PAGED_CODE(); 01855 CMLOG(CML_FLOW, CMS_SEC) { 01856 KdPrint(("CmpRemoveSecurityCellList: index %ld\n",SecurityCell)); 01857 } 01858 Cell = (PCM_KEY_SECURITY) HvGetCell(Hive, SecurityCell); 01859 FlinkCell = (PCM_KEY_SECURITY) HvGetCell(Hive, Cell->Flink); 01860 BlinkCell = (PCM_KEY_SECURITY) HvGetCell(Hive, Cell->Blink); 01861 01862 ASSERT(FlinkCell->Blink == SecurityCell); 01863 ASSERT(BlinkCell->Flink == SecurityCell); 01864 01865 FlinkCell->Blink = Cell->Blink; 01866 BlinkCell->Flink = Cell->Flink; 01867 }

ULONG CmpSecurityExceptionFilter IN PEXCEPTION_POINTERS  ExceptionPointers  ) 
 

Definition at line 117 of file cmse.c.

References DbgPrint, and EXCEPTION_EXECUTE_HANDLER.

Referenced by CmpSecurityMethod().

00123 : 00124 00125 Debug code to find registry security exceptions that are being swallowed 00126 00127 Return Value: 00128 00129 EXCEPTION_EXECUTE_HANDLER 00130 00131 --*/ 00132 00133 { 00134 DbgPrint("CM: Registry security exception %lx, ExceptionPointers = %p\n", 00135 ExceptionPointers->ExceptionRecord->ExceptionCode, 00136 ExceptionPointers); 00137 00138 // 00139 // This is a request from the base test team; no dbg should be hit on the free builds 00140 // at the client; after RC2 is shipped we should enable this on free builds too. 00141 // 00142 #if DBG 00143 try { 00144 DbgBreakPoint(); 00145 } except (EXCEPTION_EXECUTE_HANDLER) { 00146 00147 // 00148 // no debugger enabled, just keep going 00149 // 00150 00151 } 00152 #endif 00153 00154 return(EXCEPTION_EXECUTE_HANDLER); 00155 }

NTSTATUS CmpSecurityMethod IN PVOID  Object,
IN SECURITY_OPERATION_CODE  OperationCode,
IN PSECURITY_INFORMATION  SecurityInformation,
IN OUT PSECURITY_DESCRIPTOR  SecurityDescriptor,
IN OUT PULONG  CapturedLength,
IN OUT PSECURITY_DESCRIPTOR *  ObjectsSecurityDescriptor,
IN POOL_TYPE  PoolType,
IN PGENERIC_MAPPING  GenericMapping
 

Definition at line 158 of file cmse.c.

References ASSERT, ASSERT_CM_LOCK_OWNED_EXCLUSIVE, ASSERT_KEY_OBJECT, AssignSecurityDescriptor, CML_FLOW, CMLOG, CmpAssignSecurityDescriptor(), CmpLockRegistry(), CmpLockRegistryExclusive(), CmpQuerySecurityDescriptorInfo(), CmpReportNotify(), CmpSecurityExceptionFilter(), CmpSetSecurityDescriptorInfo(), CmpUnlockRegistry(), CMS_SEC, DeleteSecurityDescriptor, FALSE, kcb(), KeBugCheckEx(), Key, NonPagedPool, NT_SUCCESS, NTSTATUS(), NULL, ObAssignObjectSecurityDescriptor(), PAGED_CODE, PagedPool, QuerySecurityDescriptor, SetSecurityDescriptor, and Status.

Referenced by CmpCreateObjectTypes(), and CmpDoCreateChild().

00171 : 00172 00173 This is the security method for registry objects. It is responsible for 00174 retrieving, setting, and deleting the security descriptor of a registry 00175 object. It is not used to assign the original security descriptor to an 00176 object (use SeAssignSecurity for that purpose). 00177 00178 00179 IT IS ASSUMED THAT THE OBJECT MANAGER HAS ALREADY DONE THE ACCESS 00180 VALIDATIONS NECESSARY TO ALLOW THE REQUESTED OPERATIONS TO BE PERFORMED. 00181 00182 Arguments: 00183 00184 Object - Supplies a pointer to the object being used. 00185 00186 OperationCode - Indicates if the operation is for setting, querying, or 00187 deleting the object's security descriptor. 00188 00189 SecurityInformation - Indicates which security information is being 00190 queried or set. This argument is ignored for the delete operation. 00191 00192 SecurityDescriptor - The meaning of this parameter depends on the 00193 OperationCode: 00194 00195 QuerySecurityDescriptor - For the query operation this supplies the 00196 buffer to copy the descriptor into. The security descriptor is 00197 assumed to have been probed up to the size passed in in Length. 00198 Since it still points into user space, it must always be 00199 accessed in a try clause in case it should suddenly disappear. 00200 00201 SetSecurityDescriptor - For a set operation this supplies the 00202 security descriptor to copy into the object. The security 00203 descriptor must be captured before this routine is called. 00204 00205 DeleteSecurityDescriptor - It is ignored when deleting a security 00206 descriptor. 00207 00208 AssignSecurityDescriptor - For assign operations this is the 00209 security descriptor that will be assigned to the object. 00210 It is assumed to be in kernel space, and is therefore not 00211 probed or captured. 00212 00213 CapturedLength - For the query operation this specifies the length, in 00214 bytes, of the security descriptor buffer, and upon return contains 00215 the number of bytes needed to store the descriptor. If the length 00216 needed is greater than the length supplied the operation will fail. 00217 It is ignored in the set and delete operation. 00218 00219 This parameter is assumed to be captured and probed as appropriate. 00220 00221 ObjectsSecurityDescriptor - For the Set operation this supplies the address 00222 of a pointer to the object's current security descriptor. This routine 00223 will either modify the security descriptor in place or deallocate/ 00224 allocate a new security descriptor and use this variable to indicate 00225 its new location. For the query operation it simply supplies 00226 the security descriptor being queried. 00227 00228 PoolType - For the set operation this specifies the pool type to use if 00229 a new security descriptor needs to be allocated. It is ignored 00230 in the query and delete operation. 00231 00232 GenericMapping - Passed only for the set operation, this argument provides 00233 the mapping of generic to specific/standard access types for the object 00234 being accessed. This mapping structure is expected to be safe to 00235 access (i.e., captured if necessary) prior to be passed to this routine. 00236 00237 Return Value: 00238 00239 NTSTATUS - STATUS_SUCCESS if the operation is successful and an 00240 appropriate error status otherwise. 00241 00242 --*/ 00243 00244 { 00245 PCM_KEY_CONTROL_BLOCK kcb; 00246 NTSTATUS Status; 00247 CM_KEY_REFERENCE Key; 00248 00249 // 00250 // Make sure the common parts of our input are proper 00251 // 00252 00253 PAGED_CODE(); 00254 ASSERT_KEY_OBJECT(Object); 00255 00256 ASSERT( (OperationCode == SetSecurityDescriptor) || 00257 (OperationCode == QuerySecurityDescriptor) || 00258 (OperationCode == AssignSecurityDescriptor) || 00259 (OperationCode == DeleteSecurityDescriptor) ); 00260 00261 // 00262 // Lock hive for shared or exclusive, depending on what we need 00263 // to do. 00264 // 00265 if (OperationCode == QuerySecurityDescriptor) { 00266 CmpLockRegistry(); 00267 } else { 00268 CmpLockRegistryExclusive(); 00269 } 00270 00271 if (((PCM_KEY_BODY)Object)->KeyControlBlock->Delete) { 00272 // 00273 // Key has been deleted, performing security operations on 00274 // it is Not Allowed. 00275 // 00276 CmpUnlockRegistry(); 00277 return(STATUS_KEY_DELETED); 00278 } 00279 00280 kcb = ((PCM_KEY_BODY)Object)->KeyControlBlock; 00281 00282 try { 00283 // 00284 // This routine simply cases off of the operation code to decide 00285 // which support routine to call 00286 // 00287 00288 switch (OperationCode) { 00289 00290 case SetSecurityDescriptor: 00291 00292 // 00293 // check the rest of our input and call the set security 00294 // method 00295 // 00296 ASSERT( (PoolType == PagedPool) || (PoolType == NonPagedPool) ); 00297 00298 Status = CmpSetSecurityDescriptorInfo( kcb, 00299 SecurityInformation, 00300 SecurityDescriptor, 00301 ObjectsSecurityDescriptor, 00302 PoolType, 00303 GenericMapping ); 00304 00305 // 00306 // this is the one and only path on which a user could change 00307 // a security descriptor, therefore, report such changes for 00308 // notification here. 00309 // 00310 if (NT_SUCCESS(Status)) { 00311 CmpReportNotify(kcb, 00312 kcb->KeyHive, 00313 kcb->KeyCell, 00314 REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_SECURITY); 00315 00316 } 00317 00318 break; 00319 00320 case QuerySecurityDescriptor: 00321 00322 // 00323 // check the rest of our input and call the default query security 00324 // method 00325 // 00326 ASSERT( CapturedLength != NULL ); 00327 Status = CmpQuerySecurityDescriptorInfo( kcb, 00328 SecurityInformation, 00329 SecurityDescriptor, 00330 CapturedLength, 00331 ObjectsSecurityDescriptor ); 00332 break; 00333 00334 case DeleteSecurityDescriptor: 00335 00336 // 00337 // Nobody should ever call the delete method. When the key is 00338 // freed, the security descriptor associated with it is 00339 // explicitly freed (CmpFreeSecurityDescriptor) 00340 // 00341 ASSERT(FALSE); 00342 00343 break; 00344 00345 case AssignSecurityDescriptor: 00346 00347 // 00348 // Set the SecurityDescriptor field in the object's header to 00349 // NULL. This indicates that our security method needs to be 00350 // called for any security descriptor operations. 00351 // 00352 00353 Status = ObAssignObjectSecurityDescriptor(Object, NULL, PagedPool); 00354 00355 ASSERT( NT_SUCCESS( Status )); 00356 00357 // 00358 // Assign the actual descriptor. 00359 // 00360 Status = CmpAssignSecurityDescriptor( kcb->KeyHive, 00361 kcb->KeyCell, 00362 kcb->KeyNode, 00363 SecurityDescriptor ); 00364 // 00365 // Security has been changed, update the cache. 00366 // 00367 ASSERT_CM_LOCK_OWNED_EXCLUSIVE(); 00368 kcb->Security = kcb->KeyNode->Security; 00369 00370 break; 00371 00372 default: 00373 00374 // 00375 // Bugcheck on any other operation code, We won't get here if 00376 // the earlier asserts are still checked. 00377 // 00378 KeBugCheckEx( REGISTRY_ERROR,3,1,(ULONG_PTR)kcb,0); 00379 00380 } 00381 00382 } except (CmpSecurityExceptionFilter(GetExceptionInformation())) { 00383 CMLOG(CML_FLOW, CMS_SEC) { 00384 KdPrint(("!!CmpSecurityMethod: code:%08lx\n", GetExceptionCode())); 00385 } 00386 Status = GetExceptionCode(); 00387 } 00388 00389 00390 CmpUnlockRegistry(); 00391 return(Status); 00392 00393 }

NTSTATUS CmpSetSecurityDescriptorInfo IN PCM_KEY_CONTROL_BLOCK  kcb,
IN PSECURITY_INFORMATION  SecurityInformation,
IN PSECURITY_DESCRIPTOR  ModificationDescriptor,
IN OUT PSECURITY_DESCRIPTOR *  ObjectsSecurityDescriptor,
IN POOL_TYPE  PoolType,
IN PGENERIC_MAPPING  GenericMapping
 

Definition at line 397 of file cmse.c.

References ASSERT_CM_LOCK_OWNED_EXCLUSIVE, ASSERT_SECURITY, _CM_KEY_SECURITY::Blink, CM_KEY_SECURITY_SIGNATURE, CML_FLOW, CMLOG, CmpDumpSecurityDescriptor, CmpFindMatchingDescriptorCell(), CmpGetKeySecurity(), CmpRemoveSecurityCellList(), CMS_SEC, DCmCheckRegistry, _CM_KEY_SECURITY::Descriptor, _CM_KEY_SECURITY::DescriptorLength, ExFreePool(), _CM_KEY_SECURITY::Flink, HCELL_INDEX, HCELL_NIL, Hive, HvAllocateCell(), HvFreeCell(), HvGetCell, HvGetCellType, HvMarkCellDirty(), HvReallocateCell(), KeQuerySystemTime(), Key, _CM_KEY_NODE::LastWriteTime, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, _CM_KEY_SECURITY::ReferenceCount, RtlLengthSecurityDescriptor(), _CM_KEY_NODE::Security, SECURITY_CELL_LENGTH, SeSetSecurityDescriptorInfo(), _CM_KEY_SECURITY::Signature, and Status.

Referenced by CmpSecurityMethod().

00407 : 00408 00409 This routine will set a node's security descriptor. The input 00410 security descriptor must be previously captured. 00411 00412 Arguments: 00413 00414 Key - Supplies a pointer to the KEY_CONTROL_BLOCK for the node whose 00415 security descriptor will be set. 00416 00417 SecurityInformation - Indicates which security information is 00418 to be applied to the object. The value(s) to be assigned are 00419 passed in the SecurityDescriptor parameter. 00420 00421 ModificationDescriptor - Supplies the input security descriptor to be 00422 applied to the object. The caller of this routine is expected 00423 to probe and capture the passed security descriptor before calling 00424 and release it after calling. 00425 00426 ObjectsSecurityDescriptor - Supplies the address of a pointer to 00427 the objects security descriptor that is going to be altered by 00428 this procedure 00429 00430 PoolType - Specifies the type of pool to allocate for the objects 00431 security descriptor. 00432 00433 GenericMapping - This argument provides the mapping of generic to 00434 specific/standard access types for the object being accessed. 00435 This mapping structure is expected to be safe to access 00436 (i.e., captured if necessary) prior to be passed to this routine. 00437 00438 Return Value: 00439 00440 NTSTATUS - STATUS_SUCCESS if successful and an appropriate error 00441 value otherwise 00442 00443 --*/ 00444 00445 { 00446 NTSTATUS Status; 00447 HCELL_INDEX SecurityCell; 00448 HCELL_INDEX MatchSecurityCell; 00449 HCELL_INDEX NewCell; 00450 HCELL_INDEX OldCell; 00451 PCM_KEY_SECURITY Security; 00452 PCM_KEY_SECURITY NewSecurity; 00453 PCM_KEY_SECURITY FlinkSecurity; 00454 PCM_KEY_SECURITY BlinkSecurity; 00455 PCM_KEY_NODE Node; 00456 ULONG DescriptorLength; 00457 PSECURITY_DESCRIPTOR DescriptorCopy; 00458 PSECURITY_DESCRIPTOR OldDescriptorCopy; 00459 ULONG Type; 00460 LARGE_INTEGER SystemTime; 00461 PHHIVE Hive; 00462 00463 PAGED_CODE(); 00464 CMLOG(CML_FLOW, CMS_SEC) { 00465 KdPrint(("CmpSetSecurityDescriptorInfo:\n")); 00466 } 00467 00468 // 00469 // Map in the hive cell for the security descriptor before we make 00470 // the call to SeSetSecurityDescriptorInfo. This prevents us from 00471 // changing its security descriptor and then being unable to bring 00472 // the hive cell into memory for updating. 00473 // 00474 Security = CmpGetKeySecurity(Key->KeyHive, 00475 Key->KeyNode, 00476 &SecurityCell); 00477 00478 // 00479 // SeSetSecurityDescriptorInfo takes a pointer to the original 00480 // descriptor. This pointer is not freed, but a new pointer will 00481 // be returned. 00482 // 00483 DescriptorCopy = &Security->Descriptor; 00484 Status = SeSetSecurityDescriptorInfo( NULL, 00485 SecurityInformation, 00486 ModificationDescriptor, 00487 &DescriptorCopy, 00488 PoolType, 00489 GenericMapping ); 00490 00491 if (!NT_SUCCESS(Status)) { 00492 return(Status); 00493 } 00494 00495 // 00496 // Set Security operation succeeded, so we update the security 00497 // descriptor in the hive. 00498 // 00499 DescriptorLength = RtlLengthSecurityDescriptor(DescriptorCopy); 00500 Type = HvGetCellType(Key->KeyCell); 00501 Hive = Key->KeyHive; 00502 Node = Key->KeyNode; 00503 00504 if (! (HvMarkCellDirty(Hive, Key->KeyCell) && 00505 HvMarkCellDirty(Hive, SecurityCell))) 00506 { 00507 ExFreePool(DescriptorCopy); 00508 return STATUS_NO_LOG_SPACE; 00509 } 00510 00511 // 00512 // Try to find an existing security descriptor that we can share. 00513 // 00514 if (CmpFindMatchingDescriptorCell(Hive, Node, DescriptorCopy, Type, &MatchSecurityCell)) { 00515 // 00516 // A match was found. 00517 // 00518 if (!HvMarkCellDirty(Hive, MatchSecurityCell)) { 00519 ExFreePool(DescriptorCopy); 00520 return(STATUS_NO_LOG_SPACE); 00521 } 00522 if (Security->ReferenceCount == 1) { 00523 // 00524 // No more references to the old security cell, so we can free it now. 00525 // 00526 if (! (HvMarkCellDirty(Hive, Security->Flink) && 00527 HvMarkCellDirty(Hive, Security->Blink))) { 00528 ExFreePool(DescriptorCopy); 00529 return(STATUS_NO_LOG_SPACE); 00530 } 00531 CmpRemoveSecurityCellList(Hive, SecurityCell); 00532 HvFreeCell(Hive, SecurityCell); 00533 } else { 00534 00535 // 00536 // Just decrement the count on the old security cell 00537 // 00538 Security->ReferenceCount -= 1; 00539 } 00540 00541 // 00542 // Set the node to point at the matching security cell. 00543 // 00544 Security = (PCM_KEY_SECURITY)HvGetCell(Hive, MatchSecurityCell); 00545 Security->ReferenceCount += 1; 00546 Node->Security = MatchSecurityCell; 00547 } else { 00548 00549 // 00550 // No match was found, we need to create a new cell. 00551 // 00552 if (Security->ReferenceCount > 1) { 00553 00554 // 00555 // We can't change the existing security cell, since it is shared 00556 // by multiple keys. Allocate a new cell and decrement the existing 00557 // one's reference count. 00558 // 00559 NewCell = HvAllocateCell(Key->KeyHive, 00560 SECURITY_CELL_LENGTH(DescriptorCopy), 00561 Type); 00562 if (NewCell == HCELL_NIL) { 00563 ExFreePool(DescriptorCopy); 00564 return(STATUS_INSUFFICIENT_RESOURCES); 00565 } 00566 00567 if (! HvMarkCellDirty(Key->KeyHive, Security->Flink)) { 00568 ExFreePool(DescriptorCopy); 00569 return STATUS_NO_LOG_SPACE; 00570 } 00571 00572 Security->ReferenceCount -= 1; 00573 00574 // 00575 // Map in the new cell and insert it into the linked list. 00576 // 00577 NewSecurity = (PCM_KEY_SECURITY) HvGetCell(Key->KeyHive, NewCell); 00578 NewSecurity->Blink = SecurityCell; 00579 NewSecurity->Flink = Security->Flink; 00580 FlinkSecurity = (PCM_KEY_SECURITY) HvGetCell(Key->KeyHive, Security->Flink); 00581 Security->Flink = FlinkSecurity->Blink = NewCell; 00582 00583 // 00584 // initialize new cell 00585 // 00586 NewSecurity->Signature = CM_KEY_SECURITY_SIGNATURE; 00587 NewSecurity->ReferenceCount = 1; 00588 NewSecurity->DescriptorLength = DescriptorLength; 00589 Security=NewSecurity; 00590 00591 // 00592 // Update the pointer in the node cell. 00593 // 00594 Node->Security = NewCell; 00595 00596 } else if (DescriptorLength != Security->DescriptorLength) { 00597 00598 // 00599 // The security descriptor's size has changed, and it is not shared 00600 // by any other cells, so reallocate the cell. 00601 // 00602 if (! (HvMarkCellDirty(Key->KeyHive, Security->Flink) && 00603 HvMarkCellDirty(Key->KeyHive, Security->Blink))) { 00604 ExFreePool(DescriptorCopy); 00605 return(STATUS_INSUFFICIENT_RESOURCES); 00606 } 00607 00608 DCmCheckRegistry((PCMHIVE)(Key->KeyHive)); 00609 OldCell = SecurityCell; 00610 SecurityCell = HvReallocateCell( Key->KeyHive, 00611 SecurityCell, 00612 SECURITY_CELL_LENGTH(DescriptorCopy) ); 00613 if (SecurityCell == HCELL_NIL) { 00614 ExFreePool(DescriptorCopy); 00615 return(STATUS_INSUFFICIENT_RESOURCES); 00616 } 00617 00618 // 00619 // Update the Node's security data. 00620 // 00621 Node->Security = SecurityCell; 00622 00623 // 00624 // Update Security to point to where the new security object is 00625 // 00626 Security = (PCM_KEY_SECURITY) HvGetCell(Key->KeyHive, SecurityCell); 00627 ASSERT_SECURITY(Security); 00628 00629 // 00630 // Update other list references to the node 00631 // 00632 if (Security->Flink == OldCell) { 00633 Security->Flink = SecurityCell; // point to new self 00634 } else { 00635 FlinkSecurity = (PCM_KEY_SECURITY) HvGetCell( 00636 Key->KeyHive, 00637 Security->Flink 00638 ); 00639 FlinkSecurity->Blink = SecurityCell; 00640 } 00641 00642 if (Security->Blink == OldCell) { 00643 Security->Blink = SecurityCell; // point to new self 00644 } else { 00645 BlinkSecurity = (PCM_KEY_SECURITY) HvGetCell( 00646 Key->KeyHive, 00647 Security->Blink 00648 ); 00649 BlinkSecurity->Flink = SecurityCell; 00650 } 00651 00652 // 00653 // Finally, update the length field in the cell 00654 // 00655 Security->DescriptorLength = DescriptorLength; 00656 DCmCheckRegistry((PCMHIVE)(Key->KeyHive)); 00657 00658 } else { 00659 00660 // 00661 // Size hasn't changed, and it's not shared by any other cells, so 00662 // we can just write the new bits over the old bits. 00663 // 00664 NOTHING; 00665 } 00666 00667 RtlMoveMemory( &(Security->Descriptor), 00668 DescriptorCopy, 00669 DescriptorLength ); 00670 } 00671 00672 00673 CMLOG(CML_FLOW, CMS_SEC) { 00674 KdPrint(("\tObject's SD has been changed\n")); 00675 CmpDumpSecurityDescriptor(DescriptorCopy, "NEW DESCRIPTOR\n"); 00676 } 00677 00678 ExFreePool(DescriptorCopy); 00679 00680 // 00681 // Update the LastWriteTime of the key. 00682 // 00683 KeQuerySystemTime(&SystemTime); 00684 Node->LastWriteTime = SystemTime; 00685 00686 // 00687 // Security has changed, update the cache. 00688 // 00689 ASSERT_CM_LOCK_OWNED_EXCLUSIVE(); 00690 Key->Security = Node->Security; 00691 00692 return(STATUS_SUCCESS); 00693 }


Generated on Sat May 15 19:43:11 2004 for test by doxygen 1.3.7