Impersonation and FileSystemWatcher (threading?)
-
Hi all, I am not sure if this is the right place to post this...sorry in advance if it should be elsewhere: I need a little help...here's the problem: I am writing a windows service that runs under the localsystem account. In it's startup code it impersonates a domain user in order to gain access to files on another machine in the domain. All that works fine. Trouble is: I try to create a set of FileSystemWatcher objects to monitor the directories on the remote machine and they fail, saying that the path is invalid. When I run the service under a domain account (not localsystem) the FileSystemWatchers work fine. So I suspect (maybe) that the FileSystemWatchers are living in a seperate thread(s) that are running under the same login as the process started under, not the impersonated one. Does this sound (un)reasonable to anyone? Anyone know how to get the FileSystemWatcher object to run under an impersonated identity? Thanks in advance Bill
-
Hi all, I am not sure if this is the right place to post this...sorry in advance if it should be elsewhere: I need a little help...here's the problem: I am writing a windows service that runs under the localsystem account. In it's startup code it impersonates a domain user in order to gain access to files on another machine in the domain. All that works fine. Trouble is: I try to create a set of FileSystemWatcher objects to monitor the directories on the remote machine and they fail, saying that the path is invalid. When I run the service under a domain account (not localsystem) the FileSystemWatchers work fine. So I suspect (maybe) that the FileSystemWatchers are living in a seperate thread(s) that are running under the same login as the process started under, not the impersonated one. Does this sound (un)reasonable to anyone? Anyone know how to get the FileSystemWatcher object to run under an impersonated identity? Thanks in advance Bill
Maybe a different way of asking the question is in order. If you were to successfully implement the impersonation, how would you (or your client) specify the user name and password for the user to impersonate? Likely, the answer would involve adding to or createing a configurtion UI and encrypting passwords to store in files or registry keys, etc. Since that would only get you to the same place that you already reached by specifying a proper login for the service itself -- are there any reasons you should not require that the service run under a domain account? John
"You said a whole sentence with no words in it, and I understood you!" -- my wife as she cries about slowly becoming a geek. -
Maybe a different way of asking the question is in order. If you were to successfully implement the impersonation, how would you (or your client) specify the user name and password for the user to impersonate? Likely, the answer would involve adding to or createing a configurtion UI and encrypting passwords to store in files or registry keys, etc. Since that would only get you to the same place that you already reached by specifying a proper login for the service itself -- are there any reasons you should not require that the service run under a domain account? John
"You said a whole sentence with no words in it, and I understood you!" -- my wife as she cries about slowly becoming a geek.Hi John, Thanks for the advice. Actually, I have been considering that option too. As I understand it, I need to grant whatever domain user I select the "act as part of the operating system" privilege on the machine running the service, yes? I need to discuss with our network admins. if they have a domain level policy preventing this...don't know yet. Definitely a good option...but I am not sure it's going to fly in the present setting. Besides, at this point, I'd REALLY like to know how to make it work the way I am trying it... :) Thanks again, Bill
-
Hi all, I am not sure if this is the right place to post this...sorry in advance if it should be elsewhere: I need a little help...here's the problem: I am writing a windows service that runs under the localsystem account. In it's startup code it impersonates a domain user in order to gain access to files on another machine in the domain. All that works fine. Trouble is: I try to create a set of FileSystemWatcher objects to monitor the directories on the remote machine and they fail, saying that the path is invalid. When I run the service under a domain account (not localsystem) the FileSystemWatchers work fine. So I suspect (maybe) that the FileSystemWatchers are living in a seperate thread(s) that are running under the same login as the process started under, not the impersonated one. Does this sound (un)reasonable to anyone? Anyone know how to get the FileSystemWatcher object to run under an impersonated identity? Thanks in advance Bill
The
FileSystemWatcher
runs in another thread, yes. How do you think you can setEnabled
totrue
and continue your code? Before you do setEnabled
, you should get the impersonatedIIdentity
, wrap that in anIPrincipal
implementation (such asWindowsPrincipal
) and pass that toAppDomain.SetThreadPrincipal
in order to set the principal for new threads created in thisAppDomain
. Another idea to solve this problem is to - if possible - create an account in your domain specifically for this service, much like many database admins do for SQL Server. Then you can grant this user permission to whatever directories you need watched and exclude it from those that don't (just be sure to handle exceptions properly when access is denied).Microsoft MVP, Visual C# My Articles
-
The
FileSystemWatcher
runs in another thread, yes. How do you think you can setEnabled
totrue
and continue your code? Before you do setEnabled
, you should get the impersonatedIIdentity
, wrap that in anIPrincipal
implementation (such asWindowsPrincipal
) and pass that toAppDomain.SetThreadPrincipal
in order to set the principal for new threads created in thisAppDomain
. Another idea to solve this problem is to - if possible - create an account in your domain specifically for this service, much like many database admins do for SQL Server. Then you can grant this user permission to whatever directories you need watched and exclude it from those that don't (just be sure to handle exceptions properly when access is denied).Microsoft MVP, Visual C# My Articles
Thank you Heath! Duh! Of course they run in a seperate thread...Sorry my ignorance here runs deep aparently. I tried to implement what you suggested...the code is below.
System.Security.Principal.WindowsPrincipal p; p=new WindowsPrincipal(System.Security.Principal.WindowsIdentity.GetCurrent()); AppDomain.CurrentDomain.SetThreadPrincipal (p);
I've verified that WindowsIdentity.GetCurrent() is, in fact, the identity I want to use...but it still gives me the same error (at the creation of the FileSystemWatchers...not when I enable them, btw). What did I mess up? Do I need to create a new AppDomain? I may follow your other advice and run the service under a special domain user but I'd really like to know how to do it this way too. Thanks again. Bill -
Thank you Heath! Duh! Of course they run in a seperate thread...Sorry my ignorance here runs deep aparently. I tried to implement what you suggested...the code is below.
System.Security.Principal.WindowsPrincipal p; p=new WindowsPrincipal(System.Security.Principal.WindowsIdentity.GetCurrent()); AppDomain.CurrentDomain.SetThreadPrincipal (p);
I've verified that WindowsIdentity.GetCurrent() is, in fact, the identity I want to use...but it still gives me the same error (at the creation of the FileSystemWatchers...not when I enable them, btw). What did I mess up? Do I need to create a new AppDomain? I may follow your other advice and run the service under a special domain user but I'd really like to know how to do it this way too. Thanks again. BillDid you use
WindowsIdentity.GetCurrent
in the handler for any of theFileSystemWatcher
events, or just after your service was started?Microsoft MVP, Visual C# My Articles
-
Did you use
WindowsIdentity.GetCurrent
in the handler for any of theFileSystemWatcher
events, or just after your service was started?Microsoft MVP, Visual C# My Articles
Heath, All the Impersonation, WindowsIdentity.GetCurrent, etc. occur in the code of the service itself. It's all part the the OnStart event handler which, subsequently, also creates the FileSystemWatchers. I do not reference WindowsIdentity.GetCurrent in the FileSystemWatcher event handlers...but I don't think it would matter, since the error occurs when the FileSystemWatcher constructor is called. Bill
-
Did you use
WindowsIdentity.GetCurrent
in the handler for any of theFileSystemWatcher
events, or just after your service was started?Microsoft MVP, Visual C# My Articles
OK... I could not get the
AppDomain.SetThreadPrincipal
to work, so I took another tact.I created a class
ImpersonatingLurker
that derives from the System.IO.FileSystemWatcher. The only difference is that the first thing it does in it's constructor is the impersonation. This seems the get the principal set correctly for the thread then handles the FileSystemWatcher. The full class definition is:
public class ImpersonateingLurker :System.IO.FileSystemWatcher { public ImpersonateingLurker(string strPath,string strFilter, System.Security.Principal.WindowsPrincipal p) { Debug.WriteLine ("Lurker Constructor:"+p.Identity.Name ); WindowsIdentity i = (WindowsIdentity) p.Identity; i.Impersonate (); this.Path = strPath; this.Filter = strFilter; } }
Then in the OnStart event handler for the windows service we do:
int iToken; LogonUser("user","domain","password",3,0,out iToken); IntPtr token2 = new IntPtr(iToken); WindowsIdentity wi = new WindowsIdentity(token2); WindowsPrincipal wp = new WindowsPrincipal (wi); ... ImpersonateingLurker IL = new ImpersonateingLurker (PathOfInterest,Filter,wp);
And it all seems to work out...Thanks to Heath and John for their advice! Bill