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 comments:
Post a Comment