Thursday, April 14, 2016

Remote Administration of IIS7 with Microsoft.Web.Administration & Impersonation

Leave a Comment

I am trying to administer IIS7 using Microsoft.Web.Administration from a c# winforms application.

In particular obtain the app pool status (started/stopped).

The catch is that I am doing so from outside the domain and I need to use impersonation.

I have the following code:

        try         {             ImpersonatedUser iU = new ImpersonatedUser(Globals.Domain, Globals.AdminUsername, Globals.AdminPassword);              ServerManager server = ServerManager.OpenRemote(ServerName);             ApplicationPool appPool = server.ApplicationPools[AppPoolName];              ApplicationPoolCollection applicationPools = server.ApplicationPools;              string state = appPool.State.ToString();             iU.Dispose();             return state;         }         catch (Exception ex)         {             System.Windows.Forms.MessageBox.Show(ex.ToString());              return "error";         } 

I'm then have the following impersonation class:

using System; using System.ComponentModel; using System.Runtime.InteropServices; using System.Security.Principal;   public class ImpersonatedUser : IDisposable { IntPtr userHandle; WindowsImpersonationContext impersonationContext;    public ImpersonatedUser(string domain, string user, string password) {       IntPtr userHandle = IntPtr.Zero;     bool valid = LogonUser(user,                 domain,                 password,                 (int)LogonType.NewCredentials,                 (int)LogonProvider.WinNT50,                 ref userHandle);      if (!valid)         throw new Win32Exception(Marshal.GetLastWin32Error());      // Begin impersonating the user     impersonationContext = WindowsIdentity.Impersonate(userHandle);      int retCode = CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, RpcAuthnLevel.PktPrivacy, RpcImpLevel.Impersonate, IntPtr.Zero, EoAuthnCap.DynamicCloaking, IntPtr.Zero);     }    public void Dispose() {     if (userHandle != IntPtr.Zero)     {         CloseHandle(userHandle);         userHandle = IntPtr.Zero;         impersonationContext.Undo();     } }  [DllImport("ole32.dll")] public static extern int CoInitializeSecurity(IntPtr pVoid, int     cAuthSvc, IntPtr asAuthSvc, IntPtr pReserved1, RpcAuthnLevel level,     RpcImpLevel impers, IntPtr pAuthList, EoAuthnCap dwCapabilities, IntPtr     pReserved3);   [DllImport("advapi32.dll", SetLastError = true)] public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);  [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr token);  enum LogonType {     Interactive = 2,     Network = 3,     Batch = 4,     Service = 5,     Unlock = 7,     NetworkClearText = 8,     NewCredentials = 9 }  enum LogonProvider {     Default = 0,     WinNT35 = 1,     WinNT40 = 2,     WinNT50 = 3 }  public enum RpcAuthnLevel {     Default = 0,     None = 1,     Connect = 2,     Call = 3,     Pkt = 4,     PktIntegrity = 5,     PktPrivacy = 6 }  public enum RpcImpLevel {     Default = 0,     Anonymous = 1,     Identify = 2,     Impersonate = 3,     Delegate = 4 }  public enum EoAuthnCap {     None = 0x00,     MutualAuth = 0x01,     StaticCloaking = 0x20,     DynamicCloaking = 0x40,     AnyAuthority = 0x80,     MakeFullSIC = 0x100,     Default = 0x800,     SecureRefs = 0x02,     AccessControl = 0x04,     AppID = 0x08,     Dynamic = 0x10,     RequireFullSIC = 0x200,     AutoImpersonate = 0x400,     NoCustomMarshal = 0x2000,     DisableAAA = 0x1000 }   } 

I have also gone into my project properties debug and unchecked "Enable the visual studio hosting process" (as I understand that interferes with impersonation).

When I run my application though I get the following error:

System.UnauthorizedAccessException: Retrieving the COM class factory for remote component with CLSID {2B72133B-3F5B-4602-8952-803546CE3344} from machine my-server failed due to the following error: 80070005 my-server. 

Checking the event viewer on the server I see the following in the security log:

An account failed to log on.  Subject: Security ID:        NULL SID Account Name:       - Account Domain:     - Logon ID:       0x0  Logon Type:         3  Account For Which Logon Failed: Security ID:        NULL SID Account Name:       brad Account Domain:     MyComputer  Failure Information: Failure Reason:     Unknown user name or bad password. Status:         0xc000006d Sub Status:     0xc0000064  Process Information: Caller Process ID:  0x0 Caller Process Name:    -  Network Information: Workstation Name:   MyComputer Source Network Address: 10.1.10.105 Source Port:        60631  Detailed Authentication Information: Logon Process:      NtLmSsp  Authentication Package: NTLM Transited Services: - Package Name (NTLM only):   - Key Length:     0 

So it seems my impersonation isn't working - instead its trying to use my local account. If I replace the app pool code with a simple request to create a file:

File.WriteAllBytes(@"\\myserver\c$\temp\test.txt", new byte[] { }); 

I see a file created which I wouldn't be able to do if impersonation wasn't working. So it seems particular to impersonation with ServerManager.OpenRemote.

I found this (http://forums.iis.net/t/1162205.aspx) forum with someone in a similar issue but I think I'm essentially using the same code and mine isn't working. Can anyone help?

Thanks Brad

0 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment