393 lines
9.8 KiB
C
393 lines
9.8 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;
|
||
}
|
||
|