• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 333
  • Last Modified:

Create New File in share using alternate user credentials

I am writing an applicaion which will create a text file in a networked share which the currently logged in user may not have proper permissions.  I've written a console app to model the process.
My thought was to first programmatically open the share using the alternate credentials and then create the file.  
Using the model code below, I receive an "The parameter is incorrect" error at p.start()
Research indicates that I may be stuck without shelling out to a "Net Use" statement.  Reasons:
1.  Specifying User requires: UseShellExecute = False
2. UseShellExecute = False requires:  an EXE file be defined as the FileName

The share does exist and the code works if I don't specify the domain, user and password parameters but....

I would prefer to think that there's another way which I'm missing.   Any thoughts?

Thank you.

The model code reads:
        ' Define Path and name for Text File
        Dim TextFilePath As String = "\\ServerName\ShareName"
        Dim TextFileName As String = "LogFile.Txt"

        ' Define Password SecureString
        Dim s As String = "PaSsWoRd"
        Dim ss As New System.Security.SecureString
        Dim c As Char() = s.ToCharArray
        For i As Integer = 0 To s.Length - 1
            ss.AppendChar(c(i))
        Next

        ' Attempt to Open Path (Network share) using alternate credentials
        Dim p As Process = New Process
        With p.StartInfo
            .Domain = "DomainName"
            .UserName = "UserName"
            .Password = ss
            .FileName = TextFilePath
            .UseShellExecute = False
        End With
       
        Try
            p.Start()
            Console.WriteLine("Path is OK")
            ' Path is open. Now Create and Write to File.
            Try
                Dim oWrite As System.IO.StreamWriter
                oWrite = IO.File.CreateText(TextFilePath & "\" & TextFileName)
                Console.WriteLine("Can open File")
                Try
                    oWrite.WriteLine("Success")
                    oWrite.Flush()
                    oWrite.Close()
                    oWrite.Dispose()
                    Console.WriteLine("Can write to File")
                Catch ex As Exception
                    ' Unable to Write to File
                    Console.WriteLine(ex.Message)
                End Try
            Catch ex As Exception
                ' Unable to Create File
                Console.WriteLine(ex.Message)
            End Try
        Catch ex As Exception
            ' Unable to Open Share
            Console.WriteLine(ex.Message)
        End Try
0
RichardKline
Asked:
RichardKline
  • 4
  • 3
1 Solution
 
Bob LearnedCommented:
What version of .NET do you have?  With 2005, it might be possible to query the user rights on the folder without using Process or writing a file.

Bob
0
 
RichardKlineAuthor Commented:
Thank you.
VB.NET 2005 (2.0 .Net Framework).  
The desired end result is to write content to a file in the share regardless of the logged in user's assigned permissions.

0
 
Bob LearnedCommented:
Can you use impersonation for the entire process?

Bob
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
RichardKlineAuthor Commented:
If that is what needs to be done.   By these questions, do you believe that there isn't an application only solution?

0
 
Bob LearnedCommented:
No, I don't because while you are opening the share with the alternate credentials, you are writing the file with the current credentials.

Bob
0
 
RichardKlineAuthor Commented:
OK,
Is it then possible to programmatically open and write to a text file on the network share using alternate credentials?  
The code above was my attempt to get that end result.  I would like to obtain that end result using some code but not necessarily the lines above.

Thank you
0
 
Bob LearnedCommented:
Yes, you can use impersonation:

' Source:
'  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemSecurityPrincipalWindowsIdentityClassImpersonateTopic1.asp

Imports System.Runtime.InteropServices
Imports System.Security.Principal
Imports System.Security.Permissions

Public Class WindowsImpersonator

  Private Declare Auto Function LogonUser Lib "advapi32.dll" (ByVal lpszUsername As [String], _
   ByVal lpszDomain As [String], ByVal lpszPassword As [String], _
   ByVal dwLogonType As Integer, ByVal dwLogonProvider As Integer, _
   ByRef phToken As IntPtr) As Boolean

  <DllImport("kernel32.dll")> _
  Public Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef lpSource As IntPtr, _
   ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByRef lpBuffer As [String], _
   ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer
  End Function

  Public Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean

  Public Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _
    ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
    ByRef DuplicateTokenHandle As IntPtr) As Boolean

  Private m_impersonatedUser As WindowsImpersonationContext

  ' GetErrorMessage formats and returns an error message
  ' corresponding to the input errorCode.
  Private Function GetErrorMessage(ByVal errorCode As Integer) As String
    Dim FORMAT_MESSAGE_ALLOCATE_BUFFER As Integer = &H100
    Dim FORMAT_MESSAGE_IGNORE_INSERTS As Integer = &H200
    Dim FORMAT_MESSAGE_FROM_SYSTEM As Integer = &H1000

    Dim messageSize As Integer = 255
    Dim lpMsgBuf As String = ""
    Dim dwFlags As Integer = FORMAT_MESSAGE_ALLOCATE_BUFFER Or FORMAT_MESSAGE_FROM_SYSTEM Or FORMAT_MESSAGE_IGNORE_INSERTS

    Dim ptrlpSource As IntPtr = IntPtr.Zero
    Dim prtArguments As IntPtr = IntPtr.Zero

    Dim retVal As Integer = FormatMessage(dwFlags, ptrlpSource, errorCode, 0, lpMsgBuf, _
     messageSize, prtArguments)
    If 0 = retVal Then
      Throw New Exception("Failed to format message for error code " + errorCode.ToString() + ". ")
    End If

    Return lpMsgBuf
  End Function

  Public Sub Impersonate(ByVal domainName As String, ByVal userName As String, ByVal password As String)

    Const LOGON32_PROVIDER_DEFAULT As Integer = 0
    'This parameter causes LogonUser to create a primary token.
    Const LOGON32_LOGON_INTERACTIVE As Integer = 2
    Const SecurityImpersonation As Integer = 2

    Dim tokenHandle As New IntPtr(0)
    Dim dupeTokenHandle As New IntPtr(0)

    tokenHandle = IntPtr.Zero
    dupeTokenHandle = IntPtr.Zero

    ' Call LogonUser to obtain a handle to an access token.
    Dim returnValue As Boolean = LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)

    If Not returnValue Then
      Dim ret As Integer = Marshal.GetLastWin32Error()
      Throw New Exception(String.Format("Error: [{0}] {1}", ret, GetErrorMessage(ret)))
    End If

    Dim retVal As Boolean = DuplicateToken(tokenHandle, SecurityImpersonation, dupeTokenHandle)
    If Not retVal Then
      CloseHandle(tokenHandle)
      Throw New Exception("Exception thrown in trying to duplicate token.")
    End If

    ' TThe token that is passed to the following constructor must
    ' be a primary token in order to use it for impersonation.
    Dim newId As New WindowsIdentity(dupeTokenHandle)
    m_impersonatedUser = newId.Impersonate()

    ' Free the tokens.
    If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero) Then
      CloseHandle(tokenHandle)
    End If

    If Not System.IntPtr.op_Equality(dupeTokenHandle, IntPtr.Zero) Then
      CloseHandle(dupeTokenHandle)
    End If

  End Sub

  Public Sub Undo()
    m_impersonatedUser.Undo()
  End Sub

  Public ReadOnly Property CurrentName() As String
    Get
      Return WindowsIdentity.GetCurrent.Name
    End Get
  End Property

End Class

Bob
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now