NTSTATUS FspFsvolSetSecurityComplete( PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) { FSP_ENTER_IOC(PAGED_CODE()); if (!NT_SUCCESS(Response->IoStatus.Status)) { Irp->IoStatus.Information = 0; Result = Response->IoStatus.Status; FSP_RETURN(); } PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); /* if the security descriptor that we got back is valid */ if (0 < Response->Rsp.SetSecurity.SecurityDescriptor.Size && Response->Buffer + Response->Rsp.SetSecurity.SecurityDescriptor.Size <= (PUINT8)Response + Response->Size && RtlValidRelativeSecurityDescriptor((PVOID)Response->Buffer, Response->Rsp.SetSecurity.SecurityDescriptor.Size, 0)) { /* update the cached security */ FspFileNodeSetSecurity(FileNode, Response->Buffer, Response->Rsp.SetSecurity.SecurityDescriptor.Size); } else { /* invalidate the cached security */ FspFileNodeSetSecurity(FileNode, 0, 0); } FspIopRequestContext(Request, RequestFileNode) = 0; FspFileNodeReleaseOwner(FileNode, Full, Request); Irp->IoStatus.Information = 0; Result = STATUS_SUCCESS; FSP_LEAVE_IOC("FileObject=%p, SecurityInformation=%x", IrpSp->FileObject, IrpSp->Parameters.SetSecurity.SecurityInformation); }
/* Create a new key, if the key exists already, * open the existing key */ NTSTATUS SqliteCreateKeyInternal( IN OPTIONAL HANDLE handle, IN PREG_KEY_CONTEXT pParentKeyCtx, IN PWSTR pwszFullKeyName, // Full Key Path IN ACCESS_MASK AccessDesired, IN OPTIONAL PSECURITY_DESCRIPTOR_RELATIVE pSecDescRel, IN ULONG ulSecDescLength, OUT OPTIONAL PREG_KEY_HANDLE* ppKeyHandle, OUT OPTIONAL PDWORD pdwDisposition ) { NTSTATUS status = STATUS_SUCCESS; PREG_DB_KEY pRegEntry = NULL; PREG_KEY_HANDLE pKeyHandle = NULL; PREG_KEY_CONTEXT pKeyCtx = NULL; BOOLEAN bInLock = FALSE; PREG_SRV_API_STATE pServerState = (PREG_SRV_API_STATE)handle; PSECURITY_DESCRIPTOR_RELATIVE pSecDescRelToSet = NULL; ULONG ulSecDescLengthToSet = 0; DWORD dwDisposition = 0; // Full key path BAIL_ON_NT_INVALID_STRING(pwszFullKeyName); // when starting up lwregd pServerState is NULL and // creating root key can skip ACL check if (pServerState && !pServerState->pToken) { status = RegSrvCreateAccessToken(pServerState->peerUID, pServerState->peerGID, &pServerState->pToken); BAIL_ON_NT_STATUS(status); } LWREG_LOCK_MUTEX(bInLock, &gActiveKeyList.mutex); status = SqliteOpenKeyInternal_inlock( handle, pwszFullKeyName, // Full Key Path AccessDesired, &pKeyHandle); if (!status) { dwDisposition = REG_OPENED_EXISTING_KEY; goto done; } else if (STATUS_OBJECT_NAME_NOT_FOUND == status) { status = 0; } BAIL_ON_NT_STATUS(status); // Root Key has to be created with a given SD if (!pParentKeyCtx && !pSecDescRel) { status = STATUS_INTERNAL_ERROR; BAIL_ON_NT_STATUS(status); } // ACL check // Get key's security descriptor // Inherit from its direct parent or given by caller if (!pSecDescRel || !ulSecDescLength) { BAIL_ON_INVALID_KEY_CONTEXT(pParentKeyCtx); status = SqliteCacheKeySecurityDescriptor(pParentKeyCtx); BAIL_ON_NT_STATUS(status); pSecDescRelToSet = pParentKeyCtx->pSecurityDescriptor; ulSecDescLengthToSet = pParentKeyCtx->ulSecDescLength; } else { pSecDescRelToSet = pSecDescRel; ulSecDescLengthToSet = ulSecDescLength; } // Make sure SD has at least owner information if (!RtlValidRelativeSecurityDescriptor(pSecDescRelToSet, ulSecDescLengthToSet, OWNER_SECURITY_INFORMATION)) { status = STATUS_INVALID_SECURITY_DESCR; BAIL_ON_NT_STATUS(status); } // Create key with SD status = RegDbCreateKey(ghCacheConnection, pwszFullKeyName, pSecDescRelToSet, ulSecDescLengthToSet, &pRegEntry); BAIL_ON_NT_STATUS(status); if (pParentKeyCtx) { SqliteCacheResetParentKeySubKeyInfo_inlock(pParentKeyCtx->pwszKeyName); } status = SqliteCreateKeyContext(pRegEntry, &pKeyCtx); BAIL_ON_NT_STATUS(status); // Cache this new key in gActiveKeyList status = SqliteCacheInsertActiveKey_inlock(pKeyCtx); BAIL_ON_NT_STATUS(status); status = SqliteCreateKeyHandle(pServerState ? pServerState->pToken : NULL, AccessDesired, pKeyCtx, &pKeyHandle); BAIL_ON_NT_STATUS(status); pKeyCtx = NULL; dwDisposition = REG_CREATED_NEW_KEY; done: if (ppKeyHandle) { *ppKeyHandle = pKeyHandle; } else { SqliteSafeFreeKeyHandle_inlock(pKeyHandle); } if (pdwDisposition) { *pdwDisposition = dwDisposition; } cleanup: SqliteReleaseKeyContext_inlock(pKeyCtx); LWREG_UNLOCK_MUTEX(bInLock, &gActiveKeyList.mutex); RegDbSafeFreeEntryKey(&pRegEntry); return status; error: if (ppKeyHandle) { *ppKeyHandle = NULL; } SqliteSafeFreeKeyHandle_inlock(pKeyHandle); goto cleanup; }
NTSTATUS FspFsvolQuerySecurityComplete( PIRP Irp, const FSP_FSCTL_TRANSACT_RSP *Response) { FSP_ENTER_IOC(PAGED_CODE()); if (!NT_SUCCESS(Response->IoStatus.Status)) { Irp->IoStatus.Information = 0; Result = Response->IoStatus.Status; FSP_RETURN(); } PFILE_OBJECT FileObject = IrpSp->FileObject; FSP_FILE_NODE *FileNode = FileObject->FsContext; SECURITY_INFORMATION SecurityInformation = IrpSp->Parameters.QuerySecurity.SecurityInformation; PVOID Buffer = Irp->AssociatedIrp.SystemBuffer; ULONG Length = IrpSp->Parameters.QuerySecurity.Length; PVOID SecurityBuffer = 0; FSP_FSCTL_TRANSACT_REQ *Request = FspIrpRequest(Irp); BOOLEAN Success; if (0 != FspIopRequestContext(Request, RequestFileNode)) { /* check that the security descriptor we got back is valid */ if (Response->Buffer + Response->Rsp.QuerySecurity.SecurityDescriptor.Size > (PUINT8)Response + Response->Size || !RtlValidRelativeSecurityDescriptor((PVOID)Response->Buffer, Response->Rsp.QuerySecurity.SecurityDescriptor.Size, 0)) { Irp->IoStatus.Information = 0; Result = STATUS_INVALID_SECURITY_DESCR; FSP_RETURN(); } FspIopRequestContext(Request, RequestSecurityChangeNumber) = (PVOID)FileNode->SecurityChangeNumber; FspIopRequestContext(Request, RequestFileNode) = 0; FspFileNodeReleaseOwner(FileNode, Full, Request); } Success = DEBUGTEST(90) && FspFileNodeTryAcquireExclusive(FileNode, Main); if (!Success) { FspIopRetryCompleteIrp(Irp, Response, &Result); FSP_RETURN(); } Success = !FspFileNodeTrySetSecurity(FileNode, Response->Buffer, Response->Rsp.QuerySecurity.SecurityDescriptor.Size, (ULONG)(UINT_PTR)FspIopRequestContext(Request, RequestSecurityChangeNumber)); Success = Success && FspFileNodeReferenceSecurity(FileNode, &SecurityBuffer, 0); FspFileNodeRelease(FileNode, Main); if (Success) { Result = FspQuerySecurityDescriptorInfo(SecurityInformation, Buffer, &Length, SecurityBuffer); FspFileNodeDereferenceSecurity(SecurityBuffer); } else { SecurityBuffer = (PVOID)Response->Buffer; Result = FspQuerySecurityDescriptorInfo(SecurityInformation, Buffer, &Length, SecurityBuffer); } Irp->IoStatus.Information = Length; FSP_LEAVE_IOC("FileObject=%p, SecurityInformation=%x", IrpSp->FileObject, IrpSp->Parameters.QuerySecurity.SecurityInformation); }