ASP.NET Remote File Access with Impersonation - asp.net

I have an ASP.NET web application that is trying to read a remote share with the impersonated user. Specifically, I am trying to use the following code to read the directories on the remote share..
DirectoryInfo rootDir = new DirectoryInfo(strPath);
foreach (DirectoryInfo dir in rootDir.EnumerateDirectories())
{
TreeNode folderNode = new TreeNode(dir.Name, dir.FullName);
folderNode.PopulateOnDemand = true;
folderNode.ImageUrl = "~/img/Folder.png";
nodeList.Add(folderNode);
}
When the webpage runs this code, I get the following error message...
Access to the path '\remoteserver\remoteshare\' is denied.
Here is my web.config...
<authentication mode="Windows"/>
<identity impersonate="true" />
<authorization>
<deny users="?"/>
</authorization>
When I log onto the website, I know that impersonation is working because I can do an HttpContext.Current.User.Identity.Name and see my username. I am running this application on a domain under IIS 7.5. I also know that this can't be a Kerberos "double-hop" issue because I can connect to a remote SQL server (from the web server) and pass the Windows Authenticated credentials through just fine and return results from a query.
I am using Process Monitor on the web server to figure out which credentials are being passed over to the remote share. When I look at the capture where the ACCESS DENIED is showing, it gives me this description...
Desired Access: Read Data/List Directory, Synchronize, Disposition: Open, Options: Directory, Synchronous IO Non-Alert, Open For Backup, Attributes: n/a, ShareMode: Read, Write, Delete, AllocationSize: n/a, Impersonating: DOMAIN\username
Where DOMAIN\username is my impersonated username from the web server.
Process Monitor is also showing that NT AUTHORITY\NETWORK SERVICE is the user on the web server that is making the request, which makes me think that the web server is NOT, in fact, passing over the impersonated user to read the remote file share. It's almost like there is a "double hop" issue for remote file share access specifically.
I have also configured the web server to "Trust this computer for delegation to any service (Kerberos only)". Again, this can't be a double-hop issue if I can access a remote SQL server from the web server, or can it? Any help or pointers would be greatly appreciated, I have spent 2 days looking at possible solutions and nothing works.

Related

Cant add bindings to IIS programmatically - redirection.config permissions (with a video!)

Here is a video summary of my problem http://screencast.com/t/v6th4BuRLhV
I am trying to add bindings programmatically to IIS with this code:
public void AddBindings(string sitename, string hostname)
{
ServerManager serverMgr = new ServerManager();
Site mySite = serverMgr.Sites[sitename];
mySite.Bindings.Add("*:80:" + hostname, "http");
mySite.ServerAutoStart = true;
serverMgr.CommitChanges();
}
And I get this error:
Filename: redirection.config
Error: Cannot read configuration file due to insufficient permissions
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.UnauthorizedAccessException: Filename: redirection.config
Error: Cannot read configuration file due to insufficient permissions
ASP.NET is not authorized to access the requested resource. Consider granting access rights to the resource to the ASP.NET request identity. ASP.NET has a base process identity (typically {MACHINE}\ASPNET on IIS 5 or Network Service on IIS 6 and IIS 7, and the configured application pool identity on IIS 7.5) that is used if the application is not impersonating. If the application is impersonating via <identity impersonate="true"/>, the identity will be the anonymous user (typically IUSR_MACHINENAME) or the authenticated request user.
I have addressed the permissions on redirection.config (both IUSR and IIS_IUSRS have permissions)
As well as the errors on web.config as suggested here http://www.codeproject.com/Questions/348972/Error-Cannot-read-configuration-file-due-to-insuff
But it still doesn't work.
ANSWER
Websites don't run under the IIS group. Whoever owns the app pool is the user and this is the user that needs permission. Or put that user in the IIS_IUSRS group.
Figure out what account your application pool is running as. Then you need to give that account access to the entire %SystemRoot%\System32\inetsrv\config folder. It wasn't enough for me to give access to just %SystemRoot%\System32\inetsrv\config\redirection.config
in my case "run as administrator" solved the problem

How to use session management with Load Balancer in Asp.Net

I have four different server and a load balancer. I want to use captcha control. I did something with it this way:
I created a handler.ashx to create the captcha image. This handler is used in the Main page. I keep the captcha control password in session while creating the captcha control. Then I compared password typed by the user with the password in the session. It works very well, but only on one server.
It doesn't run correctly with four servers. Although the user enters the correct password every time, it sometimes matches with the session password and sometimes doesn't match. I think the problem reason is this:
For Example :
A,B,C and D are the four servers. The load balancer routes the first request to A server. Which opens the main page from A server and creates password '123456'. This is stored in session on A server. Then user typed in the password and clicked button. Now the load balancer routes this request to the B server. Because session in B Sever is null, the passwords don't match.
My web.config has this,
<sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424"/>
But It still doesnt work.
What should I do ?
So first thing (just to make sure) - I believe that this connection string is just an example because 127.0.0.1 is localhost and it wouldn't have chance to work ;).
Now I will assume that you have chosen server A for you state server. Please check following things:
"ASP.NET State Service" is up and running on the server A (it's disabled by default, you can check that in Administrative Tools --> Services)
the stateConnectionString in servers B, C and D is "tcpip=[Server A IP Address or Network Name]:42424" (it can be 127.0.0.1 only on server A)
servers can communicate between each other using TCP/IP via port 42424 (firewalls etc.)
Please remember that if you have changed configuration of "ASP.NET State Service" on server A to not use default port (42424), you must reflect that in your connection strings.
Sometimes it's easier to configure "SQL Server Mode" instead of "State Server Mode" so you might want to consider that. You can find more details here.
You need to use StateServer or SqlServer for managing the session state and they should be out of your firewall network that is used to balance the load.
http://www.hanselman.com/blog/LoadBalancingAndASPNET.aspx
When using Session State Server, there are few things which need to setup.
Setup ASP.Net State Service on the machine which you want as a StateServer.
net start aspstate
Change Session Mode in Web.Config File for all web applications and point to a StateServer
<system.web>
<!-- ... -->
<sessionState
mode="StateServer"
stateConnectionString="tcpip=your_server_ip:42424"
cookieless="false"
timeout="20" />
<!-- ... -->
</system.web>
3 . All Web Server the use same <machinekey> configuration
<machineKey
validationKey="1234567890123456789012345678901234567890AAAAAAAAAA"
decryptionKey="123456789012345678901234567890123456789012345678"
validation="SHA1"
decryption="Auto"
/>
(Note:To maintain session state across different Web servers in the Web farm, the application path of the Web site (for example, \LM\W3SVC\2) in the Microsoft Internet Information Services (IIS) metabase must be the same for all of the Web servers in the Web farm. The case also needs to be the same because the application path is case-sensitive.
[http://support.microsoft.com/kb/325056])

Failed to generate a user instance of SQL Server due to failure in retrieving the user's local ap

This is my first time to deploy an asp.net web site. Everything is working fine on my local computer but when i published the web site on a remote computer i get the error "Failed to generate a user instance of SQL Server due to failure in retrieving the user's local application data path. Please make sure the user has a local user profile on the computer. The connection will be closed"
(only in pages that try to access the database)
Help pleaseee
In IIS under Vista/Windows 7/Server 2008 OS,
Select the application pool and then "advanced settings." Under "process model" find "Load User Profile" and set it to true.
SQL should now load under the default app pool account.
Try the following:
Start IIS
Open Application Pools by clicking on it
Right click on DefaultAppPool and select “Select Application Pool
Defaults”
Change “Identity” property to “NetworkService”
Save and exit IIS
You have to adjust your connection string according to your hosting server.
Modify the below section of web.config according to SQL server user name and password
<connectionStrings>
<add name="DBName" providerName="System.Data.SqlClient"
connectionString="uid=; pwd=; database=; server=;"/>
</connectionStrings>

WMI access denied error when query remote computer from ASP.NET

I have an ASP.NET application that executes a WMI call to a remote system. The application Web.config contains <identity impersonate="true"> and <authentication mode="Windows"> options which, as I understand, should force the application code to be executed on behalf of the application user.
The problem is that I get "Access is denied" error, despite the fact I can successfully execute the my WMI request from PowerShell console on the same host under the same user to the remote server in question.
// this doesn't work
ManagementScope scope = new ManagementScope();
scope.Path.NamespacePath = "root\\virtualization";
scope.Path.Server = "vs01";
scope.Connect(); // <-- here comes exception
# this works just fine
Get-WmiObject -Namespace 'root\virtualization' -Class Msvm_ComputerSystem -ComputerName vs01
Dumping HttpContext.Current.User.Identity.Name, System.Security.Principal.WindowsIdentity.GetCurrent().Name, System.Threading.Thread.CurrentPrincipal.Identity.Name properties suggest that impersonation works as expected.
Ideas? Could the issue be some kind of .NET or IIS security?
You need to have a domain administrator enable Delegation for your web server machine. This is a security feature of Kerberos. By default an intermediate server (in this case your web server) is not allowed to pass the impersonation context of a client to the remote server unless it has been given Delegation permission. If you don't do this the remote target server will see the request coming in as Anonymous User... which if its properly secured will be denied access.
Note its a common policy to only allow an intermediate server to delegate to specific target servers (called constrained delegation), so if your web app needs to be able to call WMI on any server in your network you may have problem. Talk to your domain admin.

asp.net windows authentication to sql server

I can not seem to get sql server to recognize my credentials.
Asp.net recognizes me when I login but when I execute a sql command I get a login failed message.
The IIS server and SQL server are on different machines.
There are other applications the IIS server which are able to authenticate to the sql server. I believe the Active Directory settings are correct. I am investigating what I am doing differently.
I must be missing something.
I check the IIS settings
The web config is set to impersonate.
Below is the relevant information. If anyone has any idea as to what I missed or am doing wrong I would appreciate some help.
IIS Settings:
'Integrated Windows authentication' is checked
'Enable anonymous access" is not checked
Web Config
<authentication mode="Windows"/>
<identity impersonate="true"/>
<authorization>
<deny users="?" />
</authorization>
Page_Load Code:
Dim winId As IIdentity = HttpContext.Current.User.Identity
TextBoxMessage.Text = winId.Name + Environment.NewLine
Dim cnn As SqlClient.SqlConnection
Try
Dim sql As String = "*****"
cnn = New SqlClient.SqlConnection("Data Source=*****;Initial Catalog=****;Integrated Security=True")
cnn.Open()
Dim cmd As New SqlClient.SqlCommand(sql, cnn)
cmd.ExecuteNonQuery()
cnn.Close()
Catch ex As Exception
TextBoxMessage.Text += ex.Message
cnn.Close()
End Try
Output:
Domain\UserName
Login failed for user 'NT AUTHORITY\ANONYMOUS LOGON'.
This is key = The IIS server and SQL server are on different machines. You're facing the classic double hop issue. Think of it in this way:
You access the web application under your credentials
IIS in this case has to present who you say you are to the SQL Server
IIS says, "Why hello SQL Server, I'm passing on Tony's kerberos creds, they are legit"
SQL Server says, "Hmmm, IIS I'm not sure I trust you, I need proof that you are trusted to present these credentials to me".
Thus once you enable delegation as mentioned by Remus, your SQL Server will trust the credentials your IIS server is presenting on your behalf.
In terms of security, under delegation, it would be wise to choose:
Trust this computer for delegation for specified services only | Use Kerberos only | and then underneath the "Services to which this account can present delegated credentials" make sure you explicitly set only the server/port you need.
You also need to enable constrained delegation:
Enabling Constrained Delegation
How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0
Windows Server 2003 Constrained Delegation (IIS 6.0)
Are your ISS server and SQL Server running on the same machine?
If not, Active Directory has to be configured to allow your IIS server to impersonate your accout towards the SQL Server. See How To: Use Protocol Transition and Constrained Delegation in ASP.NET 2.0.
Long story short: IIS server should have "trusted for delegation" checkbox checked in Active Directory.
You need to set you credentials in Application Pool.
- Open IIS
- Select Application Pools
- Enter the name, select .Net framework version and click OK
- Select the new added application pool and click on Advanced Settings..
- In the Process Model section click on Identity - choose custom account and enter the AD username, password, confirm password and click OK
- Select your application and in the Basic settings choose your application pool just created.
Hope this helps

Resources