Hi,
yes I was able to do so (I just tried this, and it was my first time - I am
a newbee).
I disabled anonymous access in my webapp folder in the IIS. I also granted
my user the right "Replace a process level token" and activated the
impersonation in my web.config.
My sample Code (based on the one supplied by Willy Denoyette)
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
namespace ImpProcess
{
/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
internal static extern bool CreateProcessWithLogonW(String lpszUsername,
String lpszDomain, String lpszPassword,
int dwLogonFlags, string applicationName, StringBuilder commandLine,
int creationFlags, IntPtr environment,
string currentDirectory,
ref STARTUPINFO sui,
out PROCESS_INFORMATION processInfo);
[StructLayout(LayoutKind.Sequential)]
internal struct STARTUPINFO
{
internal int cb;
[MarshalAs(UnmanagedType.LPTStr)]
internal string lpReserved;
[MarshalAs(UnmanagedType.LPTStr)]
internal string lpDesktop;
[MarshalAs(UnmanagedType.LPTStr)]
internal string lpTitle;
internal int dwX;
internal int dwY;
internal int dwXSize;
internal int dwYSize;
internal int dwXCountChars;
internal int dwYCountChars;
internal int dwFillAttribute;
internal int dwFlags;
internal short wShowWindow;
internal short cbReserved2;
internal IntPtr lpReserved2;
internal IntPtr hStdInput;
internal IntPtr hStdOutput;
internal IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PROCESS_INFORMATION
{
internal IntPtr hProcess;
internal IntPtr hThread;
internal int dwProcessId;
internal int dwThreadId;
}
//dwLogonFlags Specifies the logon option
const int LOGON_WITH_PROFILE = 1;
const int LOGON_NETCREDENTIALS_ONLY = 2;
//dwCreationFlags - Specifies how the process is created
const int CREATE_SUSPENDED = 0x00000004;
const int CREATE_NEW_CONSOLE = 0x00000010;
const int CREATE_NEW_PROCESS_GROUP = 0x00000200;
const int CREATE_SEPARATE_WOW_VDM = 0x00000800;
const int CREATE_UNICODE_ENVIRONMENT = 0x00000400;
const int CREATE_DEFAULT_ERROR_MODE = 0x04000000;
//dwCreationFlags parameter controls the new process's priority class
const int NORMAL_PRIORITY_CLASS = 0x00000020;
const int IDLE_PRIORITY_CLASS = 0x00000040;
const int HIGH_PRIORITY_CLASS = 0x00000080;
const int REALTIME_PRIORITY_CLASS = 0x00000100;
const int BELOW_NORMAL_PRIORITY_CLASS = 0x00004000;
const int ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000;
//dwFlags
// This is a bit field that determines whether certain STARTUPINFO
// members are used when the process creates a window.
// Any combination of the following values can be specified:
const int STARTF_USESHOWWINDOW = 0x0000000;
const int STARTF_USESIZE = 0x00000002;
const int STARTF_USEPOSITION = 0x00000004;
const int STARTF_USECOUNTCHARS = 0x00000008;
const int STARTF_USEFILLATTRIBUTE = 0x00000010;
const int STARTF_FORCEONFEEDBACK = 0x00000040;
const int STARTF_FORCEOFFFEEDBACK = 0x00000080;
const int STARTF_USESTDHANDLES = 0x00000100;
const int STARTF_USEHOTKEY = 0x00000200;
protected System.Web.UI.WebControls.Button Button1;
private void Page_Load(object sender, System.EventArgs e)
{
// Put user code to initialize the page here
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.Button1.Click += new System.EventHandler(this.Button1_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
private void Button1_Click(object sender, System.EventArgs e)
{
// I inserted this to check that my ASP.NET Web App is corectly
impersonated.
string temp = System.Web.HttpContext.Current.User.Identity.Name;
// Account to run as
string _logonName = "myuser"; // some user
string _domain = "."; // local machine account
string _password = "myPassword";
StringBuilder sb = new StringBuilder();
// command to execute
sb.Append(@"notepad.exe");
PROCESS_INFORMATION processInfo;
STARTUPINFO startInfo = new STARTUPINFO();
startInfo.cb = Marshal.SizeOf(startInfo);
startInfo.lpTitle = "This is a NotePad console";
startInfo.dwFlags = STARTF_USECOUNTCHARS;
startInfo.dwYCountChars = 50;
// create process similar as "runas" using the logon users profile
bool ret = CreateProcessWithLogonW(_logonName, _domain, _password,
LOGON_WITH_PROFILE, null, sb,
NORMAL_PRIORITY_CLASS | CREATE_UNICODE_ENVIRONMENT,
IntPtr.Zero, "c:\\",
ref startInfo, out processInfo);
Console.WriteLine("CreateProcessWithLogonW called");
if(!ret)
{ // If failure ...
Response.Write(Marshal.GetLastWin32Error());
}
else
{
Response.Write(processInfo.dwProcessId);
}
}
}
}
I inserted a breakpoint after CreateProcessWithLogonW and watched the
taskpad for my new notepad. And it runs as my user.
My Config:
Windows XP with SP1
Framework 1.1
Hope this helps
Bjoern Wolfgardt