IIS ADSI virtual dir creation problem from web application

G

Gabriel R

I am trying to create a virtual directory using ADSI, with the following
C# code:

string Server = <srv>;
string ApplicationName = <app>;
DirectoryEntry root = new DirectoryEntry("IIS://" + Server +
"/W3SVC/1/Root", adminusername, adminuserpass);
// look up the virtual dir
DirectoryEntry app = null;
foreach (DirectoryEntry e in root.Children)
{
if (e.SchemaClassName == "IISWebVirtualDir" && e.Name.ToUpper() ==
ApplicationName.ToUpper())
{
app = e; break;
}
}
if (app == null)
{
// create the virtual dir
app = root.Children.Add(ApplicationName, "IISWebVirtualDir");
}
// create the application attached to it
app.Invoke("AppCreate", false);
// set the properties of the virtual dir
app.Properties["Path"][0] = "D:\\Web";
app.Properties["DefaultDoc"][0] = "default.aspx";
app.Properties["AppFriendlyName"][0] = ApplicationName;
app.CommitChanges();

The code works fine if I run it from a Windows Forms application,
however if it's run from a web application I get a COMException: Access
denied.
The web application runs under the credentials of the admin user (I used
<identity impersonate=true ...> in web.config).

How could I solve this problem?

Gabriel
 
J

Joe Kaplan \(MVP - ADSI\)

One thing to know about the IIS provider is that it doesn't respect the
username and password properties. It always uses the security context of
the current thread. Therefore, you need to make sure you change that
instead. I'm not sure why this isn't welll documented or doesn't throw an
exception, but that's the way it is.

Joe K.
 
J

Joe Kaplan \(MVP - ADSI\)

I'd suggest using the sample code that MS publishes for programmatic
impersonation:

http://msdn.microsoft.com/library/d...ImpersonationContextClassTopic.asp?frame=true

It has the benefit of some nicer error handling which might help explain
what didn't work on 2000 or 2003. Essentially, they should both work fine.
However, you do need "Act as part of the operating system" privilege to call
LogonUser under Windows 2000 which might be a deal breaker.

The other option is putting the code in a COM+ component and running that
under the identity you need to manage the server(s).

Another option might be to look at the WMI provider for IIS instead of ADSI.
It might give you more flexibility (although I don't know anything about
it).

HTH,

Joe K.

Gabriel R via DotNetMonster.com said:
I have tried to run the code impersonated (first calling
impersonateValidUser then, after everything's done, undoImpersonation). I
have used:

#region setup impersonation via interop
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
static System.Security.Principal.WindowsImpersonationContext
impersonationContext;

[DllImport("advapi32.dll", CharSet=CharSet.Auto)]public static extern int
LogonUser(String lpszUserName, String lpszDomain,String lpszPassword,int
dwLogonType, int dwLogonProvider,ref IntPtr phToken);
[DllImport("advapi32.dll",
CharSet=System.Runtime.InteropServices.CharSet.Auto,
SetLastError=true)]public extern static int DuplicateToken(IntPtr hToken,
int impersonationLevel, ref IntPtr hNewToken);
#endregion

#region impersonation methods
private static bool impersonateValidUser(String userName, String domain,
String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;

// try raw impersonation (username, pass)
if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) == 0)
return false;

// duplicate the token and use it for impersonation
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null) return true;
else return false;
}
else return false;
}

private static void undoImpersonation()
{
impersonationContext.Undo();
}
#endregion

What's interesting is that it works fine on IIS 5.1 (WinXP), but it
wouldn't work on IIS 5 (Win2k) or IIS 6 (Win2003). However, if run from a
Windows Forms application, it works on all machines.

Is there another way to impersonate the current thread (apart from the
functions I used from advapi32.dll)?

Thanks,
Gabriel
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top