Anonymous access + Windows Authentication

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hello,

I have a web app that uploads files to a file server (different box than the
web server). The application uses NT integrated authentication, but no users
should have permissions to the file server.

How can I use a fixed domain account to upload the files to the file server
while still preserving the users' Windows integrated authentication on the
web server?

Thank you,

Eric
 
Eric said:
Hello,

I have a web app that uploads files to a file server (different box
than the web server). The application uses NT integrated
authentication, but no users should have permissions to the file
server.

How can I use a fixed domain account to upload the files to the file
server while still preserving the users' Windows integrated
authentication on the web server?

Use P/Invoke and code-level impersonation. Search the KB for "asp.net
impersonation".

--
Jim Cheshire
JIMCO Software
http://www.jimcosoftware.com

FrontPage add-ins for FrontPage 2000 - 2003
 
Here's how impersonate the webapp user

try
{
// Get current Identity
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
// Output Current Principal
output.Write("--- CurrentPrincipal ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Try impersonating the App Pool user
RevertToSelf();
// The next 3 steps are the important steps
WindowsIdentity wi = WindowsIdentity.GetCurrent();
Thread.CurrentPrincipal = new WindowsPrincipal(wi);
WindowsImpersonationContext wic = wi.Impersonate();
// Output WindowsIdentity
output.Write("--- RevertToSelf() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Impersonate back to original identity
wic.Undo();
Thread.CurrentPrincipal = new WindowsPrincipal(currentIdentity);
currentIdentity.Impersonate();
// Output WindowsIdentity
output.Write("--- Impersonate() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
}
catch (Exception ex)
{
// display diagnostic error information if exception occurs
output.Write("<div>");
output.Write("<b>Exception Type</b>: " + ex.GetType().ToString() + "<br>");
output.Write("<b>Exception Message</b>: " + ex.Message + "<br>" );
output.Write("<b>Stack Trace</b>:<br>" + ex.StackTrace.Replace("\n", "<br>"));
output.Write("</div>");
}

You can also use the LogonUser()

[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
/// <summary>
/// This will impersonate a user using the LogonUser() and return a handle
/// to the WindowsImpersonationContext
/// </summary>
/// <param name="login"></param>
/// <param name="password"></param>
/// <param name="domain"></param>
public WindowsImpersonationContext ImpersonateUser(string login, string
password, string domain)
{
// constants used by LogonUser() method
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
// handle returned from the LogonUser() method
IntPtr handle = new IntPtr(0);
handle = IntPtr.Zero;
// try to login to the domain
bool logonUser = LogonUser(login, domain, password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref handle);
// login unsuccessful
if(!logonUser)
{
// get the error
int lastWin32Error = Marshal.GetLastWin32Error();
throw new Exception("ImpersonateUser failed<br>Win32Error: " +
lastWin32Error);
}
// create a new WindowsIdentity, set the CurrentPrincipal and Impersonate
the user
WindowsIdentity wi
= new WindowsIdentity(handle, "NTLM", WindowsAccountType.Normal, true);
Thread.CurrentPrincipal = new WindowsPrincipal(wi);
WindowsImpersonationContext wic = wi.Impersonate();
// close the handle
CloseHandle(handle);
// return the WindowsImpersonationContext
return wic;
}
/// <summary>
/// Render this Web Part to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void RenderWebPart(HtmlTextWriter output)
{
// start of try block
try
{
// Get current Identity
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
// Output Current Principal
output.Write("--- CurrentPrincipal ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Impersonate a user
WindowsImpersonationContext wic
= ImpersonateUser("username", "password", "domain");
// Output WindowsIdentity
output.Write("--- ImpersonateUser() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Undo the impersonation and set the CurrentPrincipal back
wic.Undo();
Thread.CurrentPrincipal = new WindowsPrincipal(currentIdentity);
// Impersonate back to original identity
currentIdentity.Impersonate();
output.Write("--- Impersonate() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
}
catch (Exception ex)
{
// display diagnostic error information if exception occurs
output.Write("<div>");
output.Write("<b>Exception Type</b>: " + ex.GetType().ToString() + "<br>");
output.Write("<b>Exception Message</b>: " + ex.Message + "<br>" );
output.Write("<b>Stack Trace</b>:<br>" + ex.StackTrace.Replace("\n", "<br>"));
output.Write("</div>");
}
}
 
Thank you for the reply, Kevin. LogonUser looks like what I'm looking for
(supplying my own username/password for the impersonation), but do you know
of a managed equivalent?

Thanks,

Eric


Kevin Schlegelmilch said:
Here's how impersonate the webapp user

try
{
// Get current Identity
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
// Output Current Principal
output.Write("--- CurrentPrincipal ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Try impersonating the App Pool user
RevertToSelf();
// The next 3 steps are the important steps
WindowsIdentity wi = WindowsIdentity.GetCurrent();
Thread.CurrentPrincipal = new WindowsPrincipal(wi);
WindowsImpersonationContext wic = wi.Impersonate();
// Output WindowsIdentity
output.Write("--- RevertToSelf() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Impersonate back to original identity
wic.Undo();
Thread.CurrentPrincipal = new WindowsPrincipal(currentIdentity);
currentIdentity.Impersonate();
// Output WindowsIdentity
output.Write("--- Impersonate() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
}
catch (Exception ex)
{
// display diagnostic error information if exception occurs
output.Write("<div>");
output.Write("<b>Exception Type</b>: " + ex.GetType().ToString() + "<br>");
output.Write("<b>Exception Message</b>: " + ex.Message + "<br>" );
output.Write("<b>Stack Trace</b>:<br>" + ex.StackTrace.Replace("\n", "<br>"));
output.Write("</div>");
}

You can also use the LogonUser()

[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
/// <summary>
/// This will impersonate a user using the LogonUser() and return a handle
/// to the WindowsImpersonationContext
/// </summary>
/// <param name="login"></param>
/// <param name="password"></param>
/// <param name="domain"></param>
public WindowsImpersonationContext ImpersonateUser(string login, string
password, string domain)
{
// constants used by LogonUser() method
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
// handle returned from the LogonUser() method
IntPtr handle = new IntPtr(0);
handle = IntPtr.Zero;
// try to login to the domain
bool logonUser = LogonUser(login, domain, password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref handle);
// login unsuccessful
if(!logonUser)
{
// get the error
int lastWin32Error = Marshal.GetLastWin32Error();
throw new Exception("ImpersonateUser failed<br>Win32Error: " +
lastWin32Error);
}
// create a new WindowsIdentity, set the CurrentPrincipal and Impersonate
the user
WindowsIdentity wi
= new WindowsIdentity(handle, "NTLM", WindowsAccountType.Normal, true);
Thread.CurrentPrincipal = new WindowsPrincipal(wi);
WindowsImpersonationContext wic = wi.Impersonate();
// close the handle
CloseHandle(handle);
// return the WindowsImpersonationContext
return wic;
}
/// <summary>
/// Render this Web Part to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
protected override void RenderWebPart(HtmlTextWriter output)
{
// start of try block
try
{
// Get current Identity
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
// Output Current Principal
output.Write("--- CurrentPrincipal ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Impersonate a user
WindowsImpersonationContext wic
= ImpersonateUser("username", "password", "domain");
// Output WindowsIdentity
output.Write("--- ImpersonateUser() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Undo the impersonation and set the CurrentPrincipal back
wic.Undo();
Thread.CurrentPrincipal = new WindowsPrincipal(currentIdentity);
// Impersonate back to original identity
currentIdentity.Impersonate();
output.Write("--- Impersonate() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
}
catch (Exception ex)
{
// display diagnostic error information if exception occurs
output.Write("<div>");
output.Write("<b>Exception Type</b>: " + ex.GetType().ToString() + "<br>");
output.Write("<b>Exception Message</b>: " + ex.Message + "<br>" );
output.Write("<b>Stack Trace</b>:<br>" + ex.StackTrace.Replace("\n", "<br>"));
output.Write("</div>");
}
}

Eric said:
Hello,

I have a web app that uploads files to a file server (different box than the
web server). The application uses NT integrated authentication, but no users
should have permissions to the file server.

How can I use a fixed domain account to upload the files to the file server
while still preserving the users' Windows integrated authentication on the
web server?

Thank you,

Eric
 
Eric,

Sorry ... not sure what you mean... I just tried this and it worked fine for
me:

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.Xml;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Threading;
using System.Security.Permissions;

namespace ScreenScrape
{

/// <summary>
/// Summary description for WebForm1.
/// </summary>
public class WebForm1 : System.Web.UI.Page
{

protected System.Web.UI.WebControls.Literal myPage;

private void Page_Load(object sender, System.EventArgs e)
{
RenderHtml(Response);
}

[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);

/// <summary>
/// This will impersonate a user using the LogonUser() and return a handle
/// to the WindowsImpersonationContext
/// </summary>
/// <param name="login"></param>
/// <param name="password"></param>
/// <param name="domain"></param>
public WindowsImpersonationContext ImpersonateUser(string login, string
password, string domain)
{
// constants used by LogonUser() method
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
// handle returned from the LogonUser() method
IntPtr handle = new IntPtr(0);
handle = IntPtr.Zero;
// try to login to the domain
bool logonUser = LogonUser(login, domain, password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref handle);
// login unsuccessful
if(!logonUser)
{
// get the error
int lastWin32Error = Marshal.GetLastWin32Error();
throw new Exception("ImpersonateUser failed<br>Win32Error: " +
lastWin32Error);
}
// create a new WindowsIdentity, set the CurrentPrincipal and Impersonate
the user
WindowsIdentity wi
= new WindowsIdentity(handle, "NTLM", WindowsAccountType.Normal, true);
Thread.CurrentPrincipal = new WindowsPrincipal(wi);
WindowsImpersonationContext wic = wi.Impersonate();
// close the handle
CloseHandle(handle);
// return the WindowsImpersonationContext
return wic;
}
/// <summary>
/// Render this Web Part to the output parameter specified.
/// </summary>
/// <param name="output"> The HTML writer to write out to </param>
public void RenderHtml(HttpResponse output)
{
// start of try block
try
{
// Get current Identity
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
// Output Current Principal
output.Write("--- CurrentPrincipal ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Impersonate a user
WindowsImpersonationContext wic
= ImpersonateUser("username", "password", "domain");
// Output WindowsIdentity
output.Write("--- ImpersonateUser() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
// Undo the impersonation and set the CurrentPrincipal back
wic.Undo();
Thread.CurrentPrincipal = new WindowsPrincipal(currentIdentity);
// Impersonate back to original identity
currentIdentity.Impersonate();
output.Write("--- Impersonate() ---<br>");
output.Write("WindowsIdentity.GetCurrent().Name: "
+ WindowsIdentity.GetCurrent().Name + "<br>");
output.Write("Thread.CurrentPrincipal.Identity.Name : "
+ Thread.CurrentPrincipal.Identity.Name + "<br>");
}
catch (Exception ex)
{
// display diagnostic error information if exception occurs
output.Write("<div>");
output.Write("<b>Exception Type</b>: " + ex.GetType().ToString() +
"<br>");
output.Write("<b>Exception Message</b>: " + ex.Message + "<br>" );
output.Write("<b>Stack Trace</b>:<br>" + ex.StackTrace.Replace("\n",
"<br>"));
output.Write("</div>");
}
}


#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.Load += new System.EventHandler(this.Page_Load);

}
#endregion

}

}
 
Eric said:
Thank you for the reply, Kevin. LogonUser looks like what I'm
looking for (supplying my own username/password for the
impersonation), but do you know of a managed equivalent?

A managed equivalent is just going to call LogonUser just like you are. If
you really need a managed equivalent, build a managed wrapper class around
the LogonUser API and you'll have one. ;)

--
Jim Cheshire
JIMCO Software
http://www.jimcosoftware.com

FrontPage add-ins for FrontPage 2000 - 2003
 
Ah hah...point taken, Jim. Thank you both for your responses. You've helped
greatly! I tested the code, and it works perfectly for what I need.

Take care,

Eric
 
Eric said:
Ah hah...point taken, Jim. Thank you both for your responses.
You've helped greatly! I tested the code, and it works perfectly for
what I need.

I meant that to be funny, not as a sarcastic remark. :)

--
Jim Cheshire
JIMCO Software
http://www.jimcosoftware.com

FrontPage add-ins for FrontPage 2000 - 2003
 
I meant that to be funny, not as a sarcastic remark. :)

No worries, that's exactly how I took it.

Eric
 
Yeah, it was just some code I put into a Page for a paper I wrote on
SharePoint Services WebPart development describing what you would need to
impersonate another domain user ... never wrote a wrapper class around it,
which is easily done by just moving it into a class with 2 methods.
Basically just need an Impersonate() method and an Undo() method.
 
Is this what you need?

using System;
using System.Security.Principal;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Threading;

namespace Impersonate
{
/// <summary>
/// Summary description for ImpersonateUser.
/// </summary>
public class ImpersonateUser
{

[DllImport("advapi32.dll", SetLastError=true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);

private WindowsImpersonationContext wic = null;
private WindowsIdentity currentIdentity = null;

public ImpersonateUser()
{
// Get current Identity
currentIdentity = WindowsIdentity.GetCurrent();
}

/// <summary>
/// This will impersonate a user using the LogonUser() and return a handle
/// to the WindowsImpersonationContext
/// </summary>
/// <param name="login"></param>
/// <param name="password"></param>
/// <param name="domain"></param>
public WindowsImpersonationContext Impersonate(string login, string
password, string domain)
{
// constants used by LogonUser() method
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
// handle returned from the LogonUser() method
IntPtr handle = new IntPtr(0);
handle = IntPtr.Zero;
// try to login to the domain
bool logonUser = LogonUser(login, domain, password,
LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref handle);
// login unsuccessful
if(!logonUser)
{
// get the error
int lastWin32Error = Marshal.GetLastWin32Error();
throw new Exception("ImpersonateUser failed<br>Win32Error: " +
lastWin32Error);
}
// create a new WindowsIdentity, set the CurrentPrincipal and Impersonate
the user
WindowsIdentity wi
= new WindowsIdentity(handle, "NTLM", WindowsAccountType.Normal, true);
Thread.CurrentPrincipal = new WindowsPrincipal(wi);
wic = wi.Impersonate();
// close the handle
CloseHandle(handle);
// return the WindowsImpersonationContext
return wic;
}

public void Undo()
{
// Impersonate back to original identity
Thread.CurrentPrincipal = new WindowsPrincipal(currentIdentity);
currentIdentity.Impersonate();
}

}

}
 
Hi Kevin,
Could you please help with this. I implemented as what you gave for
impersonation. Its working very well but what i need is cross domain
impersonation. If i use LogonUser im unable to impersonate . Im getting this
error regardless of any parameter i change for LogonUser() method

Error :

LogonUser() failed with error code: 1326

code snippet :

int bImpersonated = LogonUser(sUsername, sDomain, sPassword,
LOGON32_LOGON_NEW_CREDENTIALS, LOGON32_PROVIDER_WINNT50,
out pExistingTokenHandle);


Logonuser is only working for those user which are in same domain . How i
can implment to work with cross domain user impersonation.
 
Back
Top