service permissions across network

joshua7

Member
Joined
Dec 14, 2005
Messages
8
Programming Experience
1-3
first off, issues similar to mine have been raised in other threads (http://www.vbdotnetforums.com/showthread.php?t=4773) and in this post: http://www.vbdotnetforums.com/showthread.php?t=4524 the poster seems to have found a solution (impersonation), but does not explain how to go about implementing it, so i have decided to repost the issue.

i have a windows service that pulls some stuff from sql, formats it, dumps it to a dat file, and then copies that across the network. everything works fine as an application, but when the code is run as a service it bombs out at the "copy file across network" section due to an "access is denied" error.

it seems to me, services run under various accounts vs whatever the user account is for an applicaton. the default, being "local system" appears to not have suffecient privileges to map to, copy to, or access files over the network.

i have tried setting up my service, both through installation, and manually in services.msc, as administrator on my local box, which has permissions to access these resources. however access is still denied. when i try setting the service up as a user on the destination box, it will not even register, which does make sense.

currently i am at a bit of stand still. if, even under the administrator account (which reads as ./administrator in the snap in) i cannot access mapped files how can i indeed do it at all?

i do not know how to impersonate user accounts or if this process falls under the service installer or within the service code itself.

if any one knows any good links (i have been googling for a while now) related windows service permissions and network communication or impersonation please let us know. thanks.
 
Well...I'll tell you what I know, which should get you pretty far along, but I can't guarantee that it will fix your particular problem.

Firstly, services do indeed run as local system, which is a special account that all services run under by default. They have all possible privs on the local machine, and no priv anywhere else. This means that they may have security policies enabled, that even your administrator account does not have by default. Basically all policies that you see in the "Local security settings" page (Adminstrative Tools) are enabled implicitly for services. You will notice that many are not granted for Administrators--for example, "Act as part of the operating system". So from this you might gather that local system appears to not have permission to access a resource on another machine (nothing you can do about this), but when you run as Administrator, you lack some other policy that your service needs. Just a guess.

So what you can do is impersonate a particular user in your service. What this means, is that your service (not the installer) switches the identity of a particular thread, so that it is running with the permissions, logon, and policies of that particular user. So you want to run this code just before you get started doing your real work. There is a .Undo() call that reverts back to the original identity of the service (Local system).

So what you do is make an unmanaged call to LogonUser, then the impersonation code is all done with .NET calls, although you could just as easily make unmanaged calls to ImpersonateLoggedOnUser() and RevertToSelf(). It turns out that I just coded this for fun a few days ago. Here is the sample code:

VB.NET:
Imports System
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.Security.Principal
Public Class ADVAPI32
    ' LogonUser call
    Public 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 Integer
     Public Enum Logon
         Batch = 1
         Interactive = 2
         NetworkCleartext = 8
     End Enum
     Public Enum Provider
         [Default] = 0
         WindowsNT35 = 1
         WindowsNT40 = 2
         Windows2000 = 3
     End Enum
     Public Declare Auto Function CloseHandle Lib "kernel32.dll" _
     (ByVal hObject As IntPtr) As Integer 
End Class
Module ImpersonateUserExample
    Public Sub PrintCurrentUserInfo ()
        Dim wi As WindowsIdentity = WindowsIdentity.GetCurrent()
        Dim wp As New WindowsPrincipal(wi)
        
        System.Console.WriteLine("Current User info")
        System.Console.WriteLine("Name: " & wp.Identity.Name)
        System.Console.WriteLine("Authentication type: " & wp.Identity.AuthenticationType)
        System.Console.WriteLine("IsAuthenticated: " & wp.Identity.IsAuthenticated.ToString())
        System.Console.WriteLine("")
    End Sub
    Public Sub Main (ByVal args() As String)
 
        If args.Length <> 3 Then
            System.Console.WriteLine("Usage: prog.exe username domain password")
            System.Environment.Exit(1)
        End If
        Dim user As String = args(0)
        Dim domain As String = args(1)
        Dim pw As String = args(2)
        Dim context As WindowsImpersonationContext
        Dim hUser As IntPtr
        ' Print current identity info
        PrintCurrentUserInfo()
        If ADVAPI32.LogonUser(user,domain,pw,ADVAPI32.Logon.Interactive, ADVAPI32.Provider.Default, hUser) = 0 Then
            System.Console.WriteLine("Invalid credentials!")
            System.Environment.Exit(1)
        End If
        Try
            Dim ident As New WindowsIdentity(hUser)
            context = ident.Impersonate()
            ' Do some task
            PrintCurrentUserInfo()
        Finally
            ' Revert and close the user handle
            context.Undo()
            ADVAPI32.CloseHandle(hUser)
        End Try
    End Sub
End Module
 
thanks.

i will spend some time trying to wrap my head around this. it may point me in the right direction.

you wrote this for fun? what do you do when you are really bored?

;)

thanks again, no one else seems to have any replies for this question.
 
Very good

The solution from above solve my problem when I want to copy file from server to client over domain. The code help me login in to domain, if not access denied will come out, thk a lot :)
 
Back
Top