Wrox Programmer Forums
|
Classic ASP Basics For beginner programmers starting with "classic" ASP 3, pre-".NET." NOT for ASP.NET 1.0, 1.1, or 2.0
Welcome to the p2p.wrox.com Forums.

You are currently viewing the Classic ASP Basics section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old November 12th, 2009, 11:50 AM
Wrox Author
 
Join Date: Oct 2005
Posts: 4,104
Thanks: 1
Thanked 64 Times in 64 Posts
Send a message via AIM to dparsons
Default Solution: Impersonation with Classic ASP

Hello All,
Some time ago (over two years ago) a forum reader asked how to use impersonation in ASP; my response to the reader was a link out to the MSDN where Microsoft had provided a solution, albeit in VB6. Reference thread: Identity impersonate in asp

As most of you know ASP executes under the guise, typically, of the IUSR_ account in IIS (IIS_IUSRS group for IIS 7) which has a very few permissions to do anything on the system (in most cases anyway). In .NET we can easily impersonate a user by placing some values into the web.config and viola. This, however, is not the case with ASP. Like most things in ASP the solution here is to create a COM component that can do some P/Invoke-ing to get a handle on some Win32 API's. I figured I could simply take the provided VB6 code, interepet it into C#, register the assembly for Interop and be done with it. Easy right?

While I could go on a rant about how Microsoft needs to contiually update their code references, ill spare you. The long and the short of it is to make impersonation a reality you need to hook 3 methods from advapi32 and 1 method from kernel32 which is simple enough, however, if you port the VB6 code to C# exactly as its wrote you will wind up with an Access Violation exception everytime you call LogonUser. After banging my head off the wall for sometime I consulted www.pinvoke.net and realized that the signature that Microsoft had provided for the LogonUser method was incorrect. The provided signature was string, string, string, long, long, long but needed to be string, string, string, int, int, out IntPtr! The return types that Microsoft had provided were also incorrect (mostly the return type was long when it should of been bool).

Once I corrected the signature and re-registered the assembly I was able to impersonate a domain account and write a file to a protected share via ASP! Below I have provided a (mostly) complete soultion so as to save the next poor soul that has to do this a few grey hairs! (I say mostly complete only because the code could be refactored a small bit. Otherwise the code is fully functional and I have pointed out pitfalls and "gotchas" that I discovered)

C# Code
I used Visual Studio 2008 to create my assembly but, I assume, you could also use Visual C# 2008 Express. Create a new class library and give it a name. I called mine Impersonate. Rename the default Class1.cs to a more meaningful namel; I used UserLogon.cs.

Using Statements
csharp Code:
using System;
using System.Runtime.InteropServices;

Class Definition
csharp Code:
namespace Impersonate
{[INDENT]public class UserLogon
{[INDENT][DllImport("advapi32.dll", SetLastError=true)]
public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
 
[DllImport("advapi32.dll")]
public static extern int ImpersonateLoggedOnUser(IntPtr hToken);
 
[DllImport("advapi32.dll")]
public static extern bool RevertToSelf();
 
[DllImport("kernel32.dll")]
public static extern bool CloseHandle(IntPtr hObject);
 
private const int LOGON32_LOGON_INTERACTIVE = 2;
private const int LOGON32_PROVIDER_DEFAULT = 0;
public void Logon(string strAdminUser, string strAdminPassword, string strAdminDomain)
{
     IntPtr hToken;
 
     RevertToSelf();
 
     LogonUser(strAdminUser, strAdminDomain, strAdminPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out hToken);
 
     ImpersonateLoggedOnUser(hToken);
 
     CloseHandle(hToken);
}
public void Logoff()
{
    RevertToSelf();
}
[/INDENT]}
[/INDENT]}

In the Solution Explorer locate the AssemblyInfo.cs file underneath the Properties folder of your project (you may need to click the 'Show all Files' button at the top of the solution explorer) and open it. Add the following line to the file:

csharp Code:
[assembly: ComVisible(true)]

Hit Ctrl + Shift + B (Build) to create your assembly.

Start* up a Visual Studio Command Prompt which can, typically, be found in Start -- > Programs --> Visual Studio 2008 --> Visual Studio Tools and navigate to the directory where your assembly is (something like: projectDirectory\bin\debug\) and issue the following command: regasm Impersonate.dll /tlb

*if you are running Vista or Win7 run this prompt with Admin rights

In your ASP editor (I used Notepad) use the following code to test your assembly:
asp Code:
[SIZE=2]<%
    Option Explicit
 
     Dim objLogon, oFs, oTextFile
 

     Set objLogon = Server.CreateObject("Impersonate.UserLogon")
     objLogon.Logon "username", "password", "domainname"
 

     Response.Write("Impersonating")
 
     set oFs = server.createobject("Scripting.FileSystemObject")
     set oTextFile = oFs.OpenTextFile("C:\foo.txt", 2, True)
 
     oTextFile.Write "This is some data wrote as a domain user"
     oTextFile.Close
 
     set oTextFile = nothing
     set oFS = nothing
 
     objLogon.Logoff
 
      Set objLogon = Nothing
      Response.Write("Done Impersonating")
%>
[/SIZE]

Most of this is very basic but there are some things to point out here:
  • Make sure that the call to CreateObject for objLogon has the name of your assembly. The format for the name will be Namespace.Class. If you have followed along using my code then the correct name is Impersonate.UserLogon.
  • Provide a valid username, password, and domain. I have not tried to impersonate a Local User but, I assume, you could simply provide the PC name as the domain and have this work.
  • Make sure that you call LogOff so that the thread reverts back to running as the IUSR account.
Provided that you execute this ASP script under the guise of IUSR, under normal circumstances, the call to create a text file in the root of the C drive should fail with an Access Denied error so that is a good case to test out our impersonation assembly. As you can see above, a user is impersonated, a file is wrote, and the user is logged off. If all went according to plan you should now see a text file in the root of your C drive! Obviously I am making the assumption that the domain user you are impersonating has the right to create files in the root of the C drive so adjust this test case accordingly.

Pitfalls and Gotchas
  • If you are running IIS 7 on a x64 platform you may get a cryptic "Active X is unable to Create Object". Before you google the problem first start up inetmgr, and locate the Application Pool that your ASP script is running from, right click on it and select 'Advanced Settings' from the context menu. The second option under the General section is 'Enable 32-Bit Applications'; change the value from False to True. If you still get the error, then Google it ;]
  • For testing purposes, I suggest moving your dll out of your debug directory and into another one and then register the dll from there. The reason for this is if you have to make any changes to the dll you will not be able to rebuild your project since the OS will have a lock on the dll in your bin directory.
  • If you need to make changes to your assembly after you have already registered it issue the following command from a Visual Studio command prompt inside the directory your assembly is registered from: regasm /u Impersonate.dll tlb:Impersonate.tlb Make your changes and then re-register the assembly using the regasm from the main tutorial. If, after you have unregistered the dll you are unable to replace the file (Access is denied because the file is in use by another process) start taskmgr and kill the w3wp.exe process (you will need to tick off the 'Show porcesses from all users' checkbox). You should now be able to replace the file.
That should do it! You should now have a fully operational component that allows for impersonation in Classic ASP!

As always, questions, comments, and criticisim are welcomed!

-Doug
__________________
===============================================
Doug Parsons
Wrox online library: Wrox Books 24 x 7
Did someone here help you? Click on their post!
"Easy is the path to wisdom for those not blinded by themselves."
===============================================
 
Old January 18th, 2011, 06:10 AM
Registered User
 
Join Date: Jan 2011
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

Hi dparsons ,

Thanks for such a nice article. I've been trying it since a while.
After following everything you mentioned, when I run the ASP file, I get an error as

Server object error 'ASP 0177 : 80070002'

Server.CreateObject Failed

I'm unable to find out the reason. Any help would be greatly appreciated.
 
Old January 18th, 2011, 06:18 AM
Registered User
 
Join Date: Jan 2011
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Default

I tried registering it as

regasm dllfile /codebase

Now, the previous error is gone and I get a new one as

Microsoft VBScript runtime error '800a0046'

Permission denied


Please help.





Similar Threads
Thread Thread Starter Forum Replies Last Post
How to Change ASP.NET into Classic ASP? GailCG Classic ASP Basics 2 April 22nd, 2009 06:04 PM
impersonation for asp app xile Classic ASP Basics 1 November 11th, 2008 08:56 AM
Converting Classic Asp to Asp.Net 2.0 vikaspatyal ASP.NET 2.0 Professional 2 October 7th, 2007 06:33 PM
asp.net vs classic asp "URGENT" naeem_ul_hussan Classic ASP Professional 1 August 1st, 2007 03:14 PM
classic asp with asp.net on same iis bostonrose .NET Framework 2.0 6 January 10th, 2007 12:38 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.