mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
578 lines
13 KiB
578 lines
13 KiB
/*++
|
|
|
|
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)
|
|
#pragma alloc_text(PAGE, NtfsFsdQuerySecurityInfo)
|
|
#pragma alloc_text(PAGE, NtfsFsdSetSecurityInfo)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
NtfsFsdQuerySecurityInfo (
|
|
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine implements the FSD part of the Query Security Information API
|
|
calls.
|
|
|
|
Arguments:
|
|
|
|
VolumeDeviceObject - Supplies the device object to use.
|
|
|
|
Irp - Supplies the Irp being processed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The Fsd status for the Irp
|
|
|
|
--*/
|
|
|
|
{
|
|
TOP_LEVEL_CONTEXT TopLevelContext;
|
|
PTOP_LEVEL_CONTEXT ThreadTopLevelContext;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PIRP_CONTEXT IrpContext = NULL;
|
|
|
|
ASSERT_IRP( Irp );
|
|
|
|
UNREFERENCED_PARAMETER( VolumeDeviceObject );
|
|
|
|
PAGED_CODE();
|
|
|
|
DebugTrace( +1, Dbg, ("NtfsFsdQuerySecurityInfo\n") );
|
|
|
|
//
|
|
// Call the common query Information routine
|
|
//
|
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
ThreadTopLevelContext = NtfsSetTopLevelIrp( &TopLevelContext, FALSE, FALSE );
|
|
|
|
do {
|
|
|
|
try {
|
|
|
|
//
|
|
// We are either initiating this request or retrying it.
|
|
//
|
|
|
|
if (IrpContext == NULL) {
|
|
|
|
IrpContext = NtfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
|
|
NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );
|
|
|
|
} else if (Status == STATUS_LOG_FILE_FULL) {
|
|
|
|
NtfsCheckpointForLogFileFull( IrpContext );
|
|
}
|
|
|
|
Status = NtfsCommonQuerySecurityInfo( IrpContext, Irp );
|
|
break;
|
|
|
|
} except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {
|
|
|
|
//
|
|
// We had some trouble trying to perform the requested
|
|
// operation, so we'll abort the I/O request with
|
|
// the error status that we get back from the
|
|
// execption code
|
|
//
|
|
|
|
Status = NtfsProcessException( IrpContext, Irp, GetExceptionCode() );
|
|
}
|
|
|
|
} while (Status == STATUS_CANT_WAIT ||
|
|
Status == STATUS_LOG_FILE_FULL);
|
|
|
|
if (ThreadTopLevelContext == &TopLevelContext) {
|
|
NtfsRestoreTopLevelIrp( ThreadTopLevelContext );
|
|
}
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
//
|
|
// And return to our caller
|
|
//
|
|
|
|
DebugTrace( -1, Dbg, ("NtfsFsdQuerySecurityInfo -> %08lx\n", Status) );
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NtfsFsdSetSecurityInfo (
|
|
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine implements the FSD part of the Set Security Information API
|
|
calls.
|
|
|
|
Arguments:
|
|
|
|
VolumeDeviceObject - Supplies the device object to use.
|
|
|
|
Irp - Supplies the Irp being processed
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS - The Fsd status for the Irp
|
|
|
|
--*/
|
|
|
|
{
|
|
TOP_LEVEL_CONTEXT TopLevelContext;
|
|
PTOP_LEVEL_CONTEXT ThreadTopLevelContext;
|
|
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PIRP_CONTEXT IrpContext = NULL;
|
|
|
|
ASSERT_IRP( Irp );
|
|
|
|
UNREFERENCED_PARAMETER( VolumeDeviceObject );
|
|
|
|
PAGED_CODE();
|
|
|
|
DebugTrace( +1, Dbg, ("NtfsFsdSetSecurityInfo\n") );
|
|
|
|
//
|
|
// Call the common query Information routine
|
|
//
|
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
ThreadTopLevelContext = NtfsSetTopLevelIrp( &TopLevelContext, FALSE, FALSE );
|
|
|
|
do {
|
|
|
|
try {
|
|
|
|
//
|
|
// We are either initiating this request or retrying it.
|
|
//
|
|
|
|
if (IrpContext == NULL) {
|
|
|
|
IrpContext = NtfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
|
|
NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );
|
|
|
|
} else if (Status == STATUS_LOG_FILE_FULL) {
|
|
|
|
NtfsCheckpointForLogFileFull( IrpContext );
|
|
}
|
|
|
|
Status = NtfsCommonSetSecurityInfo( IrpContext, Irp );
|
|
break;
|
|
|
|
} except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {
|
|
|
|
//
|
|
// We had some trouble trying to perform the requested
|
|
// operation, so we'll abort the I/O request with
|
|
// the error status that we get back from the
|
|
// execption code
|
|
//
|
|
|
|
Status = NtfsProcessException( IrpContext, Irp, GetExceptionCode() );
|
|
}
|
|
|
|
} while (Status == STATUS_CANT_WAIT ||
|
|
Status == STATUS_LOG_FILE_FULL);
|
|
|
|
if (ThreadTopLevelContext == &TopLevelContext) {
|
|
NtfsRestoreTopLevelIrp( ThreadTopLevelContext );
|
|
}
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
//
|
|
// And return to our caller
|
|
//
|
|
|
|
DebugTrace( -1, Dbg, ("NtfsFsdSetSecurityInfo -> %08lx\n", Status) );
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
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 );
|
|
|
|
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)) {
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
//
|
|
// If the this handle does not open the entire file then refuse access.
|
|
//
|
|
|
|
} else if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {
|
|
|
|
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, FALSE );
|
|
|
|
try {
|
|
|
|
if (Fcb->SharedSecurity == NULL) {
|
|
|
|
NtfsReleaseFcb( IrpContext, Fcb );
|
|
AcquiredFcb = FALSE;
|
|
|
|
NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, FALSE, FALSE );
|
|
AcquiredFcb = TRUE;
|
|
}
|
|
|
|
Status = NtfsQuerySecurity( IrpContext,
|
|
Fcb,
|
|
&IrpSp->Parameters.QuerySecurity.SecurityInformation,
|
|
(PSECURITY_DESCRIPTOR)Irp->UserBuffer,
|
|
&IrpSp->Parameters.QuerySecurity.Length );
|
|
|
|
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;
|
|
|
|
#ifdef _CAIRO_
|
|
PQUOTA_CONTROL_BLOCK OldQuotaControl;
|
|
ULONG OldOwnerId;
|
|
ULONG LargeStdInfo;
|
|
#endif // _CAIRO_
|
|
|
|
TYPE_OF_OPEN TypeOfOpen;
|
|
PVCB Vcb;
|
|
PFCB Fcb;
|
|
PSCB Scb;
|
|
PCCB Ccb;
|
|
|
|
ASSERT_IRP_CONTEXT( IrpContext );
|
|
ASSERT_IRP( Irp );
|
|
|
|
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)) {
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
//
|
|
// If the this handle does not open the entire file then refuse access.
|
|
//
|
|
|
|
} else if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Our operation is to acquire the fcb, do the operation and then
|
|
// release the fcb
|
|
//
|
|
|
|
NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, FALSE, FALSE );
|
|
|
|
try {
|
|
|
|
#ifdef _CAIRO_
|
|
|
|
//
|
|
// 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;
|
|
|
|
#endif // _CAIRO_
|
|
|
|
Status = NtfsModifySecurity( IrpContext,
|
|
Fcb,
|
|
&IrpSp->Parameters.SetSecurity.SecurityInformation,
|
|
IrpSp->Parameters.SetSecurity.SecurityDescriptor );
|
|
|
|
if (NT_SUCCESS( Status )) {
|
|
|
|
#ifdef _CAIRO_
|
|
//
|
|
// Make sure the new security descriptor Id is written out.
|
|
//
|
|
|
|
NtfsUpdateStandardInformation( IrpContext, Fcb );
|
|
#endif
|
|
}
|
|
|
|
//
|
|
// Abort transaction on error by raising.
|
|
//
|
|
|
|
NtfsCleanupTransaction( IrpContext, Status, FALSE );
|
|
|
|
//
|
|
// Set the flag in the Ccb to indicate this change occurred.
|
|
//
|
|
|
|
SetFlag( Ccb->Flags,
|
|
CCB_FLAG_UPDATE_LAST_CHANGE | CCB_FLAG_SET_ARCHIVE );
|
|
|
|
} finally {
|
|
|
|
DebugUnwind( NtfsCommonSetSecurityInfo );
|
|
|
|
#ifdef _CAIRO_
|
|
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);
|
|
|
|
}
|
|
}
|
|
#endif // _CAIRO_
|
|
|
|
NtfsReleaseFcb( IrpContext, Fcb );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now complete the request and return to our caller
|
|
//
|
|
|
|
NtfsCompleteRequest( &IrpContext, &Irp, Status );
|
|
|
|
DebugTrace( -1, Dbg, ("NtfsCommonSetSecurityInfo -> %08lx", Status) );
|
|
|
|
return Status;
|
|
}
|
|
|