test: cmse.c File Reference

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 }