393 lines
9.4 KiB
C
393 lines
9.4 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
SeInfo.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements the Security Info routines for NTFS called by the
|
|||
|
dispatch driver.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Gary Kimura [GaryKi] 26-Dec-1991
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "NtfsProc.h"
|
|||
|
|
|||
|
//
|
|||
|
// The debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_SEINFO)
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, NtfsCommonQuerySecurityInfo)
|
|||
|
#pragma alloc_text(PAGE, NtfsCommonSetSecurityInfo)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NtfsCommonQuerySecurityInfo (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the common routine for querying security information called by
|
|||
|
both the fsd and fsp threads.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irp - Supplies the Irp to process
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - the return status for the operation
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PIO_STACK_LOCATION IrpSp;
|
|||
|
PFILE_OBJECT FileObject;
|
|||
|
|
|||
|
TYPE_OF_OPEN TypeOfOpen;
|
|||
|
PVCB Vcb;
|
|||
|
PFCB Fcb;
|
|||
|
PSCB Scb;
|
|||
|
PCCB Ccb;
|
|||
|
|
|||
|
BOOLEAN AcquiredFcb = TRUE;
|
|||
|
|
|||
|
ASSERT_IRP_CONTEXT( IrpContext );
|
|||
|
ASSERT_IRP( Irp );
|
|||
|
ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Get the current Irp stack location
|
|||
|
//
|
|||
|
|
|||
|
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|||
|
|
|||
|
DebugTrace( +1, Dbg, ("NtfsCommonQuerySecurityInfo") );
|
|||
|
DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
|
|||
|
DebugTrace( 0, Dbg, ("Irp = %08lx\n", Irp) );
|
|||
|
|
|||
|
//
|
|||
|
// Extract and decode the file object
|
|||
|
//
|
|||
|
|
|||
|
FileObject = IrpSp->FileObject;
|
|||
|
TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );
|
|||
|
|
|||
|
//
|
|||
|
// The only type of opens we accept are user file and directory opens
|
|||
|
//
|
|||
|
|
|||
|
if ((TypeOfOpen != UserFileOpen)
|
|||
|
&& (TypeOfOpen != UserDirectoryOpen)
|
|||
|
&& (TypeOfOpen != UserViewIndexOpen)) {
|
|||
|
|
|||
|
Status = STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Our operation is to acquire the fcb, do the operation and then
|
|||
|
// release the fcb. If the security descriptor for this file is
|
|||
|
// not already loaded we will release the Fcb and then acquire both
|
|||
|
// the Vcb and Fcb. We must have the Vcb to examine our parent's
|
|||
|
// security descriptor.
|
|||
|
//
|
|||
|
|
|||
|
NtfsAcquireSharedFcb( IrpContext, Fcb, NULL, 0 );
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
if (Fcb->SharedSecurity == NULL) {
|
|||
|
|
|||
|
NtfsReleaseFcb( IrpContext, Fcb );
|
|||
|
AcquiredFcb = FALSE;
|
|||
|
|
|||
|
NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, 0 );
|
|||
|
AcquiredFcb = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make sure the volume is still mounted.
|
|||
|
//
|
|||
|
|
|||
|
if (FlagOn( Scb->ScbState, SCB_STATE_VOLUME_DISMOUNTED )) {
|
|||
|
|
|||
|
Status = STATUS_VOLUME_DISMOUNTED;
|
|||
|
leave;
|
|||
|
}
|
|||
|
|
|||
|
Status = NtfsQuerySecurity( IrpContext,
|
|||
|
Fcb,
|
|||
|
&IrpSp->Parameters.QuerySecurity.SecurityInformation,
|
|||
|
(PSECURITY_DESCRIPTOR)Irp->UserBuffer,
|
|||
|
&IrpSp->Parameters.QuerySecurity.Length );
|
|||
|
|
|||
|
if (NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
Irp->IoStatus.Information = IrpSp->Parameters.QuerySecurity.Length;
|
|||
|
|
|||
|
} else if (Status == STATUS_BUFFER_TOO_SMALL) {
|
|||
|
|
|||
|
Irp->IoStatus.Information = IrpSp->Parameters.QuerySecurity.Length;
|
|||
|
|
|||
|
Status = STATUS_BUFFER_OVERFLOW;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Abort transaction on error by raising.
|
|||
|
//
|
|||
|
|
|||
|
NtfsCleanupTransaction( IrpContext, Status, FALSE );
|
|||
|
|
|||
|
} finally {
|
|||
|
|
|||
|
DebugUnwind( NtfsCommonQuerySecurityInfo );
|
|||
|
|
|||
|
if (AcquiredFcb) {
|
|||
|
|
|||
|
NtfsReleaseFcb( IrpContext, Fcb );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now complete the request and return to our caller
|
|||
|
//
|
|||
|
|
|||
|
NtfsCompleteRequest( IrpContext, Irp, Status );
|
|||
|
|
|||
|
DebugTrace( -1, Dbg, ("NtfsCommonQuerySecurityInfo -> %08lx", Status) );
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
NtfsCommonSetSecurityInfo (
|
|||
|
IN PIRP_CONTEXT IrpContext,
|
|||
|
IN PIRP Irp
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is the common routine for Setting security information called by
|
|||
|
both the fsd and fsp threads.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Irp - Supplies the Irp to process
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - the return status for the operation
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
PIO_STACK_LOCATION IrpSp;
|
|||
|
PFILE_OBJECT FileObject;
|
|||
|
PQUOTA_CONTROL_BLOCK OldQuotaControl = NULL;
|
|||
|
ULONG OldOwnerId;
|
|||
|
ULONG LargeStdInfo;
|
|||
|
|
|||
|
TYPE_OF_OPEN TypeOfOpen;
|
|||
|
PVCB Vcb;
|
|||
|
PFCB Fcb;
|
|||
|
PSCB Scb;
|
|||
|
PCCB Ccb;
|
|||
|
|
|||
|
ASSERT_IRP_CONTEXT( IrpContext );
|
|||
|
ASSERT_IRP( Irp );
|
|||
|
ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Get the current Irp stack location
|
|||
|
//
|
|||
|
|
|||
|
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|||
|
|
|||
|
DebugTrace( +1, Dbg, ("NtfsCommonSetSecurityInfo") );
|
|||
|
DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
|
|||
|
DebugTrace( 0, Dbg, ("Irp = %08lx\n", Irp) );
|
|||
|
|
|||
|
//
|
|||
|
// Extract and decode the file object
|
|||
|
//
|
|||
|
|
|||
|
FileObject = IrpSp->FileObject;
|
|||
|
TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );
|
|||
|
|
|||
|
//
|
|||
|
// The only type of opens we accept are user file and directory opens
|
|||
|
//
|
|||
|
|
|||
|
if ((TypeOfOpen != UserFileOpen)
|
|||
|
&& (TypeOfOpen != UserDirectoryOpen)
|
|||
|
&& (TypeOfOpen != UserViewIndexOpen)) {
|
|||
|
|
|||
|
Status = STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
} else if (NtfsIsVolumeReadOnly( Vcb )) {
|
|||
|
|
|||
|
Status = STATUS_MEDIA_WRITE_PROTECTED;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Capture the source information.
|
|||
|
//
|
|||
|
|
|||
|
IrpContext->SourceInfo = Ccb->UsnSourceInfo;
|
|||
|
|
|||
|
//
|
|||
|
// Our operation is to acquire the fcb, do the operation and then
|
|||
|
// release the fcb
|
|||
|
//
|
|||
|
|
|||
|
NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, 0 );
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// Make sure the volume is still mounted.
|
|||
|
//
|
|||
|
|
|||
|
if (FlagOn( Scb->ScbState, SCB_STATE_VOLUME_DISMOUNTED )) {
|
|||
|
|
|||
|
Status = STATUS_VOLUME_DISMOUNTED;
|
|||
|
leave;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Post the change to the Usn Journal.
|
|||
|
//
|
|||
|
|
|||
|
NtfsPostUsnChange( IrpContext, Scb, USN_REASON_SECURITY_CHANGE );
|
|||
|
|
|||
|
//
|
|||
|
// Capture the current OwnerId, Qutoa Control Block and
|
|||
|
// size of standard information.
|
|||
|
//
|
|||
|
|
|||
|
OldQuotaControl = Fcb->QuotaControl;
|
|||
|
OldOwnerId = Fcb->OwnerId;
|
|||
|
LargeStdInfo = Fcb->FcbState & FCB_STATE_LARGE_STD_INFO;
|
|||
|
|
|||
|
Status = NtfsModifySecurity( IrpContext,
|
|||
|
Fcb,
|
|||
|
&IrpSp->Parameters.SetSecurity.SecurityInformation,
|
|||
|
IrpSp->Parameters.SetSecurity.SecurityDescriptor );
|
|||
|
|
|||
|
if (NT_SUCCESS( Status )) {
|
|||
|
|
|||
|
//
|
|||
|
// Make sure the new security descriptor Id is written out.
|
|||
|
//
|
|||
|
|
|||
|
NtfsUpdateStandardInformation( IrpContext, Fcb );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Abort transaction on error by raising.
|
|||
|
//
|
|||
|
|
|||
|
NtfsCleanupTransaction( IrpContext, Status, FALSE );
|
|||
|
|
|||
|
//
|
|||
|
// Set the flag in the Ccb to indicate this change occurred.
|
|||
|
//
|
|||
|
|
|||
|
if (!IsDirectory( &Fcb->Info )) {
|
|||
|
SetFlag( Ccb->Flags, CCB_FLAG_UPDATE_LAST_CHANGE | CCB_FLAG_SET_ARCHIVE );
|
|||
|
}
|
|||
|
|
|||
|
} finally {
|
|||
|
|
|||
|
DebugUnwind( NtfsCommonSetSecurityInfo );
|
|||
|
|
|||
|
if (AbnormalTermination()) {
|
|||
|
|
|||
|
//
|
|||
|
// The request failed. Restore the owner and
|
|||
|
// QuotaControl are restored.
|
|||
|
//
|
|||
|
|
|||
|
if ((Fcb->QuotaControl != OldQuotaControl) &&
|
|||
|
(Fcb->QuotaControl != NULL)) {
|
|||
|
|
|||
|
//
|
|||
|
// A new quota control block was assigned.
|
|||
|
// Dereference it.
|
|||
|
//
|
|||
|
|
|||
|
NtfsDereferenceQuotaControlBlock( Fcb->Vcb,
|
|||
|
&Fcb->QuotaControl );
|
|||
|
}
|
|||
|
|
|||
|
Fcb->QuotaControl = OldQuotaControl;
|
|||
|
Fcb->OwnerId = OldOwnerId;
|
|||
|
|
|||
|
if (LargeStdInfo == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// The standard information has be returned to
|
|||
|
// its orginal size.
|
|||
|
//
|
|||
|
|
|||
|
ClearFlag( Fcb->FcbState, FCB_STATE_LARGE_STD_INFO );
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// The request succeed. If the quota control block was
|
|||
|
// changed then derefence the old block.
|
|||
|
//
|
|||
|
|
|||
|
if ((Fcb->QuotaControl != OldQuotaControl) &&
|
|||
|
(OldQuotaControl != NULL)) {
|
|||
|
|
|||
|
NtfsDereferenceQuotaControlBlock( Fcb->Vcb,
|
|||
|
&OldQuotaControl);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now complete the request and return to our caller
|
|||
|
//
|
|||
|
|
|||
|
NtfsCompleteRequest( IrpContext, Irp, Status );
|
|||
|
|
|||
|
DebugTrace( -1, Dbg, ("NtfsCommonSetSecurityInfo -> %08lx", Status) );
|
|||
|
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|