0

I have a WebApi app that needs to access a network share on a different machine and open Crystal Reports files.

I'm using LogonUser and WindowsIdentity.Impersonate to impersonate a user that has rights to the network share using this code (not complete):

SafeTokenHandle safeTokenHandle;

const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;

bool returnValue = LogonUser(userName, domainName, userPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);

if (returnValue == false)
{
    int ret = Marshal.GetLastWin32Error();
    throw new System.ComponentModel.Win32Exception(ret);
}

using (safeTokenHandle)
using (var newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle()))
using (var impersonatedUser = newId.Impersonate())
{ 
    actionToExecute();
}

This works fine when, for example, listing folders or deleting files using managed code (System.IO). However I need to open Crystal Reports files (I have the latest version), and when doing so, I get an exception:

Access denied

I am assuming that CR is trying to load the file within the context of the Application Pool user.

I would probably get this working if I change the Application Pool user to a domain user with enough rights on the network share. But I want to avoid this solution.

Would using the new WindowsIdentity.RunImpersonated for .NET4.6 help or will it have the same outcome. If yes, is there a way to get CR to run within the supplied user context instead of the Application Pool / AppDomain user?

UPDATE

I've had partial success by changing the LogonUser parameters to LOGON32_LOGON_NEW_CREDENTIALS and LOGON32_PROVIDER_WINNT50. Then I tested the following:

  1. Started the project locally from within VS2017 (so that the WebApi project runs within the local IIS Express context) and accessed the network resource using the client app on my machine. This test was a success.

  2. Published the WebApi project on IIS on a separate machine. Started the client (ClickOnce) project on my machine and accessed the same network resource. This test fails.

  3. Same as (2) but the client is published and installed on another machine, and accessing it using terminal server. This test fails.

Why does the first test succeeds but tests 2 and 3 fail? What should the correct logon parameters be if the supplied ones won't always work?

Ivan-Mark Debono
  • 15,500
  • 29
  • 132
  • 263
  • https://stackoverflow.com/q/125341/3110834 – Reza Aghaei Feb 09 '19 at 07:04
  • If you can work with remote files, then it sounds like impersonation works. But what do you mean by "open Crystal Reports files", is it different then open a file on a share? Maybe Crystal Reports just doesn't support this. – Simon Mourier Feb 09 '19 at 08:36
  • Have you tried to map shared folder as a drive? – Maciej Los Feb 11 '19 at 09:02
  • @SimonMourier I mean load the .rpt file into a document, set parameters and print the report. – Ivan-Mark Debono Feb 11 '19 at 11:38
  • How is it different than opening it from a share? – Simon Mourier Feb 11 '19 at 12:19
  • @SimonMourier If I knew the answer I wouldn't have the problem. Funny thing is that when I start local IIS Express (within VS2017) I don't have problems with impersonation and loading the report. I'm logged in as a local user on my dev machine. It's only when the webapi is deploying on a separate IIS machine. – Ivan-Mark Debono Feb 11 '19 at 12:37
  • Have you checked the user who's identity is used for running the application pool associated with the IIS site? – Simon Mourier Feb 11 '19 at 14:11
  • @SimonMourier It's the default user created by IIS. – Ivan-Mark Debono Feb 11 '19 at 14:53
  • This may also be a dependency issue, the local AppPool process may not have permissions to access all the DLL's required by crystal reports. Also are you sure all dependencies are available on the web server. – Bigtoe Feb 11 '19 at 17:14
  • @Bigtoe Permissions should not be a problem because the CR dll's are copied to the bin folder. Required DLL's are automatically copied on publishing. This might or might not be an issue. I'll look into it. – Ivan-Mark Debono Feb 12 '19 at 06:46
  • @Ivan-MarkDebono the problem seems to be opening the .rpt file that is in a different network location, not with the dll's. You need delegation, not impersonation, or maybe both – Daniel Brughera Feb 13 '19 at 13:35

2 Answers2

2

The problem is that ReportDocument doesn't have something like LoadImpersonate, so, it will always try to open the .rpt file using the app-pool permissions.

What you need is delegation, not impersonation, if you are using windows authentication and active directory you need to authorize your server and/or your app-pool account for delegation...

https://support.microsoft.com/en-us/help/810572/how-to-configure-an-asp-net-application-for-a-delegation-scenario

That way the app-pool account will use the user's privileges to access the resources

If that is not posible, as a workaround you can use impersonation to copy the .rpt file to an accessible location for your app-pool account and delete it after use it...

Daniel Brughera
  • 1,641
  • 1
  • 7
  • 14
0

Is it possible for you to use the built in impersonation in ASP.NET?. https://support.microsoft.com/en-ie/help/306158/how-to-implement-impersonation-in-an-asp-net-application

Bigtoe
  • 3,372
  • 1
  • 31
  • 47