What I am attempting to do seems very simple in principal. There is a directory which contains documents that I need to provide to my users however the account under which IIS is running does not have access. So what I am attempting to do is use impersonation to open the document in a .ashx with an account that does have access and write the document to the response stream.
Unfortunately unless I am hosting the website in an instance of Visual Studio which I am running as an administrator the code snippet below fails on using (Stream fileStream = new FileStream(@"c:\test3.pdf", FileMode.Open))
with System.UnauthorizedAccessException. This doesnt seem to make sense as impersonation seems to have taken affect as WindowsIdentity.GetCurrent().Name
returns the name of my test account and the test account does have access to open the document. It seems like I am missing something very simple here does anyone know what it is? I appreciate any help!!!!
<%@ WebHandler Language="C#" Class="PDFHandler" %>
using System;
using System.Web;
using System.IO;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Threading;
public class PDFHandler : IHttpHandler {
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
String lpszUsername,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool RevertToSelf();
public void ProcessRequest (HttpContext context) {
context.Response.Clear();
context.Response.ClearContent();
context.Response.ClearHeaders();
context.Response.ContentType = "application/pdf";
byte[] result = null;
IntPtr admin_token = default(IntPtr);
WindowsIdentity wid_current = WindowsIdentity.GetCurrent();
WindowsIdentity wid_admin = null;
WindowsImpersonationContext wic = null;
RevertToSelf();
if (LogonUser("test account", "Odysseus", "test", 2, 0, ref admin_token) == true)
{
wid_admin = new WindowsIdentity(admin_token);
wic = wid_admin.Impersonate();
using (Stream fileStream = new FileStream(@"c:\test3.pdf", FileMode.Open))
{
result = ReadFully(fileStream);
fileStream.Close();
}
}
else
{
//login failed
}
context.Response.BinaryWrite(result);
context.Response.Flush();
}
public static byte[] ReadFully(Stream input)
{
byte[] returnValue;
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
returnValue = ms.ToArray();
}
return returnValue;
}
public bool IsReusable {
get {
return false;
}
}
}