I am trying to call an old VB6 dll (no source code available) from an ASP.NET project. The dll connects to a server using windows authentication, so I need to call functions as a specific user, not NETWORKSERVICE as it is now.
This would preferably be determined at call time, not load time because I am impersonating the remote user and would like for this to be the user calling the functions, not the application user and not NETWORKSERVICE as it is now.
So, theres the browser running as USER, connecting to the application impersonating USER, calling the dll as USER, but the dll is trying to connect to a remote server as NETWORKSERVICE, not USER.
Is it possible to make this dll connect to the remote server as USER? Or, if nothing else, connect as the application user?
Edit:
Impersonation is done in code by calling Impersonate() on the remote user's WindowsIdentity. The company I work for has a custom SecurityPrincipal and SecurityIdentity so it's kind of weird how I have to go about getting the WindowsIdentity (it's a little more in depth than User.Identity), but I have used this method before successfully and have verified that System.Security.Principal.WindowsIdentity.GetCurrent().Name
is the correct user during the impersonation.
I would first try to find out how the DLL is connecting as a different user (Process Explorer can help with this). Is it possible that the DLL is communicating with a service (or some other process) which is running on the box which is logged in as NETWORKSERVICE? If so, you can change that service to run as a different user. Just grasping at straws, hope you figure it out!
I did eventually find the problem (which just lead to other problems, but anyway) it turned out to be I was missing an AspCompat="true" on my page. Actually the problem was that I was using a "Handler" and not a "Page". Handlers do not have the STA abilities that Pages have. What was happening was every time I tried to access the COM component, there would be a thread switch (impersonation lost) since the application is running in an MTA and the COM component must run in an STA.
Related
We have as SAAS application that runs for multiple customers at the same time. All customers use the same application, and by checking the URL used to access the application, users are redirected to the correct data for the organization.
Underwater, every organization has their own database. To make sure that users don't accidentally end up in the wrong database, we want to impersonate the request being executed to a user that only has access to the correct database. We used to do this and this worked beautifully on IIS in classic mode.
However, in integrated pipeline mode, we run into a threading issue. We use an HTTP module to impersonate the request to the correct user in the "PreRequestHandlerExecute" event. The problem that (apparently) there is no guarantee that this method is executed in the same thread as the handler that actually processes the request. This causes the impersonation to sometimes not work because the thread processing the request is not impersonated.
I've created a test project in GitHub (https://github.com/PaulVrugt/ImpersonationExample/tree/master/ImpersonationTest) demonstrating the issue (apologies for the vb.net, but you'll get the idea). When you run the example connected to an IIS using integrated pipeline mode, you'll see that sometimes the impersonated user is not used, and each time it is not used, the managedthreadid of the thread processing the request is different from the thread used in the httpmodule.
Now that I understand why it "sometimes" doesn't work, I begin to suspect I'm going about this all wrong. Is there a way to achieve what I am trying to do?
We've already tried to impersonate in the prerequesthandler in the global.asax, but that results in the same issue.
I'm new to this old stuff... I've set up my COM+ application (Classic ASP) on Windows Server 2012, but could only get it to run by unchecking "Enforce access checks for this application" in the application properties. It now runs okay, but any time the application tries to hit the database in any way, I get nothing. I've checked access to the necessary folders (as far as I know) and the user (local user, in the identity tab) has read/write access. Any ideas? And is more information needed?
As you probably already know, Windows Server releases are an ever-changing minefield of permission issues (aka user identity issues). What worked under 2008 may no longer under 2012.
The components in a classic ASP solution pretty much all have the potential to be running as different identities in the context of Windows.
Typical examples of unexpected identities are System, Network Service, and IUSR.
Where these options bite are, for example:
In IIS your web site has an assigned app pool in which it runs. The app pool has a user identity assignment;
In IIS, your virtual folders map to physical folders under Windows and there is access security there;
With COM you get a further identity option to set - this is the 'run-as' identity, which is the effective user that executes the COM components for you.
With a database such as MS SQL Server, you get the concept of user connection security which can be set to use Windows user authentication (trust the windows user) or userid/pwd required. So if you use, for example ADODB, in your code you must supply a connection string that you have to match to the connection settings the DB expects and will allow.
From your description I assume that you have the IIS site up and running, and your issue is confined to DB access from the COM components. You need to establish how the COM components connect to the DB and check that the DB will accept the credentials in use. If you are using Windows Authentication for the DB then you need to confirm for sure the run-as identity that is in use. In my setup we create a dedicated Windows user that we set aside specifically to use for COM so that we can be absolutely sure of the identity, and in our most verbose logging from the COM components we capture the run-as identity just to confirm it is all wired up correctly.
We do the same with dedicated Windows users for the IIS app pool user too. In general you are better off being sure which identity is in use by assigning it yourself rather than taking the default. Additionally, the defaults such as Network Service seem to have a diminishing amount of privs in Windows overall.
Word of caution - on the other hand do not give your dedicated users more access than they need, for example making them members of the Administrator group when you are frustrated or feeling your way through permission issues. Sure, assign these on a very temporary basis to confirm that access privs are the issue, but be sure to remove such assignments as soon as you possible can.
EDIT: I had this half written when your comment came in. You say that there was a missing component - I had not considered that potential as you seemed to be saying that the config worked but COM did not. Well done for solving your issue. I will leave this answer in place as some of what I have written could be useful for future folks walking the same or similar path.
Ive created a app in asp.net using c# that needs to create folders on a number of network shares. Ive configured the app pool account to use a domain account and given that domain account the correct permissions to the network share folder. When i run my code im getting the following exception. Any ideas?
Exception: System.ComponentModel.Win32Exception
Message: Logon failure: unknown user name or bad password
You should create an account on the network that has the relevant access to that share and then set your application pool to use that identity.
This way, all requests from your application will appear to be that user.
Take care with this approach, however, as if anyone changes the password to that account, you will need to update it within your IIS
OK seems I've been a bit of a chump. Seems there was some code I wrote (cant remember doing it) that impersonated the account I had set for the custom app pool but with the old password. Simply commented out the code and it now works as expected. Note to self!!!!!! Must read stack trace more carefully in future.
Apologies for wasting your time
I'm having some trouble calling a web service from within a web application and I was hoping someone here might be able to help. From what I can tell, this seems to have something to do with the Kerberos double-hop issue. However, if it is, I'm not sure what to do to actually fix the problem. To make things harder, I don't have the proper permissions to make changes to Active Directory accounts, so I need to know what to ask for when requesting changes. In my situation, I need to pass the credentials (Integrated Windows Authentication) from a web application onto a backend web service so that the web service runs under the proper user context.
Here's my exact issue:
This works
This doesn't work
The only difference between the working scenario and the non-working scenario is that the working scenario is running the application on localhost (whether a developer's PC or on the server in question) and the non-working example is running on another machine. The code between both scenarios is exactly the same.
What I've tried
Adding an SPN to the domain account that runs the app pool for each server setspn -a http/server1 DOMAIN\account
Different methods of impersonation
Removing the impersonation code using(...) and executing the web service call as the app pool account. This works as expected.
Does anyone have any idea on what I might be able to do in order to fix this problem?
The intermediate server must be trusted for delegation. Otherwise no credential will be delegated and the intermediate server cannot impersonate the original client.
More often than not the reason is that Server 1 does not pass a delegation token to Server 2. So when Server 2 tries to use that authentication ticket to go somewhere else (probably a SQL server) it fails.
You should set the impersonation level for the WCF call
ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Delegation
http://msdn.microsoft.com/en-us/library/system.servicemodel.security.windowsclientcredential.allowedimpersonationlevel.aspx
I have written a web service that reads from a message queue.
This works fine under Cassini.
Now that I have deployed the service under IIS, I receive an error message when the service tries to access the queue:
The queue does not exist or you do not have sufficient permissions to perform the operation.
I have set the anonymous access user on the IIS virtual directory to be my own domain account, which is a member of the administrators group on the local machine. I have granted this same user full permissions on the queue, as well as NETWORK SERVICE and ASPNET.
I still get the same error message.
I have also tried disabling anonymous access on the virtual directory and connecting to the service using my own login details - to no avail.
Any help with this problem will be greatly appreciated!
I have also tried various combinations of:
and
With testUsr having full permissions on the queue. I have added permissions for the user and ASPNET on the MSMQ store folders on C:\
My understanding of the problem is that the process trying to execute the code is running as a different account under IIS than it does under Cassini.
The problem was that regardless of which user I impersonated - I always got the same error message - even when the user was a member of the local and domain administrator groups, and this user had full permissions on the queue. i.e. It is barely possible to assign more rights to a user.
It turns out, that using a FormatName for the queue, rather than a path name (myMachine\queueName) has solved the problem...
FormatName:DIRECT=OS:myMachine\myQueue
I am uncertain as to exactly why this is the case. Reading up has showed that when a path name is used, there is a necessity for an AD lookup, and although I think that the users that I have been testing with should have rights to do this, perhaps there is something missing.
However the immediate problem is solved and that's good enough for me.