GetNamedSecurityInfo - Read Owner pt II

  • Thread starter Thread starter Dave Coate
  • Start date Start date
D

Dave Coate

Hello again,

I am going to re-post a question. I got some excellent suggestions from
Rob and Mattias on this but their ideas did not solve the problem. Here is
the original post:

*****************************************************
I am looking for a way to 'override' file security and read the Owner of
a file to which I have no access. I am a system administrator, as such I
have administrative rights to all the computers in the company. Some of my
user base has full control rights to their files and have elected to remove
my access to some files. It is possible for an administrator to regain
access, but it is a messy process and can be time consuming. I have had more
than one long night copying data to a larger partition having to wach the
job for files that will not copy and go back to clean it up.

I have written a vb.net program that uses Windows API functions to
automate this. It takes ownership of problem files, grants administrative
access, copies the file or folder plus the security information and then
sets everything back the way it was. There is only one hitch. I have been
unsuccessful reading the owner of a file using Win APIs such as
GetNamedSecurityInfo when I do not have access to the file. I can WRITE a
new owner to such a file, but not read it. I need to be able to do this so I
can subsequently restore the original owner after I copy the file.

My current work around is to make a command shell call to fileacl.exe.
This utility will read a file's owner regardless of permissions if you use
the /force switch. This works, but I am not very happy with it and I would
like to do the whole job with Win APIs. For one thing it makes the program
more portable because I do not need to remember to have the fileacl.exe
utility on every server/computer from which I run this program.

Since the fileacl utility does read the file owner without permissions,
it must be possible. Can anyone give me a hint on how this might be
accomplished?

*****************************************************

I tried placing myself in the backup operators group and that did not help.
I have tried adjusting my token with the SeRestorePrivilege and
SeBackupPrivilege and that did not help either. (I am not certain I am doing
the latter properly, but the code I wrote does not return any errors,
including dll errors.) Does anyone have any other suggestions? Keep in
mind, I am an administrator on all boxes for which I have tried this.

Dave Coate
 
Take a look at Knowledge Base article Q240184:
INFO: Reading/Modifying DACL of a File or Folder with Backup and Restore
Privilege
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/enu_kbwin32sdk/en-us/win32sdk/Q240184.htm

To use the privileges, check out:
ms-help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/enu_kbwin32sdk/en-us/win32sdk/Q240184.htm

If you need addtional Win32 security APIs in VB.NET, check out
http://www.DataMarvel.com
It has samples on enabling privileges through a higher level wraper, which
is much simplier than the raw PInvoke Win32 APIs.
 
jzhu,

Thanks for the pointer. This appears to be what I am looking for.
However, I can not quite get it to work. The Security Descriptor pointer
returned by GetKernelObjectSecurity appears to be invalid. At least that is
what 'IsValidSecurityDescriptor' returns. When I try to use it in
'GetSecurityDescriptorOwner' it blows up with 'Object reference not set to
an instance of an object'. Any idea what I am doing wrong?

Dave

My Code:
*****************************************
'Structures and Functions
<StructLayout(LayoutKind.Sequential, Pack:=1)> _
Public Structure LUID
Public LowPart As Integer
Public HighPart As Integer
End Structure

<StructLayout(LayoutKind.Sequential, Pack:=1)> _
Public Structure LUID_AND_ATTRIBUTES
Public pLuid As LUID
Public Attributes As Integer
End Structure

<StructLayout(LayoutKind.Sequential, Pack:=1)> _
Public Structure TOKEN_PRIVILEGES
Public PrivilegeCount As Integer
Public Privileges As LUID_AND_ATTRIBUTES
End Structure

Private Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20
Private Const TOKEN_QUERY As Integer = &H8
Private Const SE_PRIVILEGE_ENABLED As Integer = &H2
Private Const FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000
Private Const EWX_FORCE As Integer = 4


Private Declare Ansi Function OpenProcessToken Lib "advapi32" ( _
ByVal ProcessHandle As IntPtr, _
ByVal DesiredAccess As Integer, _
ByRef TokenHandle As IntPtr) As Integer

Private Declare Ansi Function LookupPrivilegeValue Lib "advapi32" _
Alias "LookupPrivilegeValueA" ( _
ByVal lpSystemName As String, _
ByVal lpName As String, _
ByRef lpLuid As LUID) As Integer

Private Declare Ansi Function AdjustTokenPrivileges Lib "advapi32" ( _
ByVal TokenHandle As IntPtr, _
ByVal DisableAllPrivileges As Integer, _
ByRef NewState As TOKEN_PRIVILEGES, _
ByVal BufferLength As Integer, _
ByRef PreviousState As TOKEN_PRIVILEGES, _
ByRef ReturnLength As Integer) As Integer

Private Declare Function CreateFile Lib "kernel32.dll" _
Alias "CreateFileA" ( _
ByVal sFileName As String, _
ByVal iDesiredAccess As Integer, _
ByVal iSharedMode As Integer, _
ByVal iSecurityAttributes As Integer, _
ByVal iCreationDisposition As Integer, _
ByVal iFlagsAndAttributes As Integer, _
ByVal hTemplateFile As Integer) As IntPtr

Private Declare Function GetKernelObjectSecurity Lib "advapi32.dll" ( _
ByVal hFileHandle As IntPtr, _
ByVal SecurityInformation As SECURITY_INFORMATION, _
ByRef pSD As IntPtr, _
ByVal iLength As Integer, _
ByRef iLengthRequired As Integer) As Integer

Private Declare Function GetSecurityDescriptorOwner Lib "advapi32.dll"
( _
ByVal pSD As IntPtr, _
ByRef pOwner As IntPtr, _
ByRef pOwnerDefaulted As Boolean) As Integer

Private Declare Function IsValidSecurityDescriptor Lib "advapi32.dll"
( _
ByVal pSD As IntPtr) As Integer

*****************************************
Calling Code

Dim tokenHandle As IntPtr
Dim privilegeLUID As LUID
Dim newPrivileges As TOKEN_PRIVILEGES
Dim tokenPrivileges As TOKEN_PRIVILEGES
Dim bSuccess As Integer

If OpenProcessToken(Process.GetCurrentProcess.Handle, _
TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, tokenHandle) = 0 Then
MsgBox(Err.LastDllError)
End If

If LookupPrivilegeValue("", privilege, privilegeLUID) = 0 Then
MsgBox(Err.LastDllError)
End If

tokenPrivileges.PrivilegeCount = 1
tokenPrivileges.Privileges.Attributes = SE_PRIVILEGE_ENABLED
tokenPrivileges.Privileges.pLuid = privilegeLUID
bSuccess = AdjustTokenPrivileges(tokenHandle, 0, tokenPrivileges, _
4 + (12 * tokenPrivileges.PrivilegeCount), _
newPrivileges, 4 + (12 * newPrivileges.PrivilegeCount))
If bSuccess = 0 Then
MsgBox(Err.LastDllError)
End If

Dim hFileHandle As IntPtr

hFileHandle = CreateFile(sPath, READ_CONTROL, _
FILE_SHARE_READ, Nothing, OPEN_EXISTING, _
FILE_FLAG_BACKUP_SEMANTICS, Nothing)
If hFileHandle.ToString = INVALID_HANDLE_VALUE Then
MsgBox("CreateFile Failed")
Else
MsgBox("CreateFile Succeeded")
End If

Dim pSD As IntPtr
Dim iLen As Integer
Dim iLenReq As Integer

bSuccess = GetKernelObjectSecurity(hFileHandle, _
SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION, pSD, iLen,
iLenReq)

bSuccess = GetKernelObjectSecurity(hFileHandle, _
SECURITY_INFORMATION.OWNER_SECURITY_INFORMATION, pSD, iLenReq,
0)

If bSuccess = 0 Then
MsgBox("GetKernelErr " & Err.LastDllError)
Else
MsgBox("GetKernelObjSec Suceeded")
End If

MsgBox(IsValidSecurityDescriptor(pSD))

Dim pOwner As IntPtr
Dim dft As Boolean

bSuccess = GetSecurityDescriptorOwner(pSD, pOwner, dft)
*****************************************
 
Back
Top