SharePoint Network Share Access Denied - c#

I'm building a web part for our SharePoint that needs to read file and folder names from a network share. However, I get an access denied error when I try to use
Directory.GetDirectories(path);
I've done some research on how to fix this, the general consensus is to either use RunWithElevatedPrivileges or impersonate the current logged in user. Unfortunately everything I've tried has failed. I have tried all of the following to no avail:
Impersonating the user and here
Setting the ASP.NET app pool to classic mode (Breaks all of sharepoint)
Changing the trust level for SharePoint to full (Doesn't seem to affect anything)
Giving the Network Service permission to the network share
Making a symbolic link on the SharePoint machine that points to the network share
Any suggestions on what to do? I'm at the end of my rope.

Related

How to allow a .NET Core web app access to network drives?

I am implementing a .NET Core (3.1) web api that reads files from a network drive, does string manipulations in them, and writes them out in a different folder (within the same network drive).
The goal is to trigger that process through an HTTP request.
To achieve that, I created my web api project, deployed to IIS 10 (win10), and the web application runs perfectly.
However, I always run into permissions issues when trying to access the network drive:
System.UnauthorizedAccessException: Access to the path '\\my\network\drive' is denied.
at System.IO.FileSystem.CreateDirectory(String fullPath, Byte[] securityDescriptor)
at System.IO.Directory.CreateDirectory(String path)
...
I have tried using all different identities under Application Pool -> Advances Settings -> Identity, and nothing worked.
What I hear from my company's infrastructure team, authorization to this network drive are granted at the user level, so it would not be possible to just give permissions to my web server's machine account to access the drive (apologies if I am not using proper terminology here - not a networking guy).
I have been trying to sort this out for a couple of days now, without any luck. Any help would be very appreciated.
TL;DR:
I have a .NET Core web app that receives an HTTP request, and when it does, it is supposed to read and write files that exist in a network drive. However, System.UnauthorizedAccessException is thrown, preventing my application from accessing the network drive and its contents.
UPDATE:
Not sure if this makes sense, but what I am thinking is, I cannot allow access to my network drive to group IIS_IUSRS (the group for application pool users), because it is a local group in the machine that hosts my application. That being the case, maybe what I need is to configure that application pool to run as a specific domain user that has read/write permissions in my network drive. Is this even possible? If so, how can I accomplish this?
This is because your drive has set access permissions and the application cannot access it.
Right click on your drive directory, then click "Properties":
Click "Edit":
I recommend giving all "Group or user names" full control permissions:

Impersonate user to access file on remote server - Access denied

I have an MVC web application that is supposed to allow users to download files that are stored as UNC paths in a database. These files can be in any number of locations on remote servers/shares.
E.g. Server 1 hosts the web application that is used to download a file stored on Server 2
I do not want to give permissions to these folders to the hosting service account, as the security should be dependent on what the user has access to. Therefore, I'm attempting to use Impersonation to retrieve the file.
When I debug on my local machine, everything works great. It impersonates my user and downloads the file.
When I deploy to my test server, I'm getting the following error:
Access to the path '\\Server2\SharedFolder\somefile.txt' is denied
I've tried various pieces from this Microsoft link, but am not having much luck.
Scenarios I've tried:
Just giving the permission to the service account of the AppPool works fine, but as I said, isn't ideal
Implementing the Impersonate a Specific User in Code from the above article, which works perfectly with a hard-coded user and password. This situation is also not ideal.
Implementing the Impersonate the Authenticating User in Code from the above article. This seems to be exactly what I need, but this is what generates the Access Denied error.
The Code that I want to work:
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext =
((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
//Code to read all bytes from the file path
impersonationContext.Undo();
I have logging, and System.Security.Principal.WindowsIdentity.GetCurrent().Name after the impersonation does return the intended user (my account instead of the service account), so it does appear to be working.
I thought maybe it was a double-hop thing, so I have also added SPNs for the server and the service account, making sure their Delegation in AD was set to allow for any service. That hasn't helped either.
This question seems to have the exact same problem as me, but there's no follow-up on what the final solution was. I did try the Process Monitor part, but it didn't help at all.
I'm at a loss to why Impersonation seems to be working, but I'm denied access to a file on a second server.
Update 1
I've played around more with my IIS settings and trying to get Kerberos properly set up. The only thing enabled in my IIS Authentication is "Windows Authentication".
When I spit out details after my Impersonate() call, I'm finding that ImpersonationLevel = Impersonation
Is that how it should be, or should that be returning Delegation ?
It would seem the issue was mostly due to my setup with Kerberos and SPNs. I undid all my settings and re-registered my service account, and the Impersonation ended up working properly.
The issue now is that it only seems to work with Internet Explorer. Chrome and MobileIron are doing something different that prevents the ImpersonationLevel of Delegation. That's a whole other question...

Service running as network service/local system: failed to add entries to ActiveDirectoryContainer (DirectoryOperationException:No Permissions)

I have two Windows services (one runs as network service and the other runs as local system). And the system in which these services are running are part of domain. These services uses active directory as central store and the idea is to be able to add/remove/read entries from this store.
We are simply using System.DirectoryServices.Protocols.LdapConnection.BeginSendRequest(DirectoryRequest request .... http://msdn.microsoft.com/en-us/library/system.directoryservices.protocols.ldapconnection.beginsendrequest(v=vs.110).aspx ) and passing AddReuest as input to add entries to the Active Directory.
However, the operation is failing with System.DirectoryServices.Protocols.DirectoryOperationException with message The user has insufficient access rights (same error for both network service as well as computer/local system account). But I did add the computer account to the store in Active Directory and granted full permissions on the store. I am not sure what I am missing?
Is it not possible to add/remove entries on active directory even though computer account has granted full permissions? (I thought local system/network service simply pass the computer credentials over network - I have taken quick peek at the following links for reference The difference between the 'Local System' account and the 'Network Service' account? or http://technet.microsoft.com/en-us/library/bb680595.aspx)
Incidentally, please note that as long as I run the service with one of the domain user accounts the operations are passing. And search (read operations) are passing for all the accounts.
You might be mistaking an authentication problem with an authorization problem. Granted, when nothing works, its hard to tell them apart.
The rights you set in AD are probably ok, but you never get there. In the security event log of the computer that hosts the Active Directory, there is probably a access denied for a network logon of \\server_a. On the Active Directory server, give the computer account (SERVER_A) the privilege "Access this computer from the network".
It will solve the authentication part, letting the process acquire an access token that will be used by Active Directory to perform authorization.
If you are in a low volume lab, you can also try to enable Active Directory Diagnostic Logging, with the Security Events registry entry.
I'm going to put this as an answer instead of a comment though I'm not yet sure if it will help.
When approaching permissions issues like this, I tend to think in terms of sets. I'd start by looking at the set of membership provided to your two different test cases, the machine account and service account with something like a powershell script described here: https://stackoverflow.com/a/20410668/44656.
It's possible that your service account has a permission granted via indirect membership that your machine account does not.
If that doesn't shed light on it, you can try enabling auditing on the ActiveDirectory server and looking for the failed access attempts. Usually a failed permission check does a decent job of highlighting why something is being denied. Auditing can be configured via global auditing policy and setting SACLs on specific object(s) you are interested in.

Why can't I open a file using impersonation on a remote machine?

I have a WCF service written in C# being hosted on a remote machine, running as the local administrator account. From my machine logged in as an active directory user, I am sending a command that simply tells it to open a file on the network. I have access to the file, but the administrator account on the host machine does not. I'm using the [OperationBehavior(Impersonation=ImpersonationOption.Required)] meta tag on the method that requires impersonation, and I have the credential type and security modes set correctly. I can verify that account is indeed trying to be impersonated by comparing Windows Identities, but I still get an access denied exception. I'm thinking it has something to do with active directory not authenticating the impersonated user. Is there something I'm missing?
You are entering the domain of Kerberos security and two hops-authentication.
You have two options:
Take the red pill: try to get the two hops-authentication to work. Make sure you have at least a Windows Server 2003 domain, time properly synchronized between all machines and setup proper delegation for the spefic users/computer accounts. If you're really "lucky" you'll have to configure SPNs with SetSPN.
Take the blue pill: forget two hops-authentication, impersonate the WCF service under an account that has just enough rights, and check authorization in an earlier step.
Forgive my frustration, but I do think that my brief experience with this topic has cost me at least 10 years of my life. I hate to see that happend to anyone else. Anyways, this post should give you enough Google keywords if you're feeling brave.
Eventlog and network monitor are useful for debugging...
You also probably need to set up delegation from the web server to the file server. This will allow the file server to trust credentials that the web server has validated. See this MSDN article on how to set up delegation for your application, particularly the section on configuring AD.

write a file from webservices

I have a web service using .net c# and I want to write to a text file on the server, but I cannot get this to work. I believe it's a permission problem.
Specifically, I think the problem is I am using System.IO.Directory.GetCurrentDirectory().
Is there a better alternative?
Try granting the ASP.NET user (or whatever account IIS is running as) permission to write to the folder you are trying to write to.
If this is a network share, try to run IIS as a domain user that can write to the share.
Remember the principle of granting minimal permission (dont use Admin level access).
If you don't specify a destination folder I assume your web service wants to write to "C:\Windows\System32\" or something of that kind. That's why a UnauthorizedAccessException will be thrown on the server. In order to write to the "home"-directory of the web service you have to find out where that is first.
The following works for me but you also find other suggestions here.
Add the reference System.Web, and get the current directory by calling:
strFileDestination = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath + strFileName;
Remember to give your service write permission in IIS.
If you're running on Windows 2003 and haven't turned on ASP.NET impersonation, and are running the app in the DefaultAppPool or an application pool that is configured to run under the identity of "Network Service", then you'll need to give the "Network Service" account write permission to the destination folder. If you're running the site in an app pool that is using an identity other than "Network Service" then that account may require write permissions to the destination folder.
If you're running windows 2000 then the '<MACHINENAME>\ASPNET' account will need write permissions to the destination folder.
If you've got impersonation turned on then you'll need to give the site's anonymous user account write permissions to the destination folder instead.
To check if impersonation is turned on, open (assuming ASP.NET 2.0) then check your machine.config file (C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG) to see if you have the following setting:
<identity impersonate="true"/>
This may also be overridden in your application's web.config.
Additionally if you're running in a partial trust environment then you'll likely only be able to write to the website's application folder because the default FileIOPermission is usually set to $AppDir$, i.e. you can't modify files anywhere else, even with the correct NTFS permissions.
If you're writing to a network share then StingyJack has the answer for you, but the partial trust environment considerations still apply.
But check your NTFS perms first, that's probably the best bet.
Hope this helps
Kev
Stuart, instead of using System.IO.Directory.GetCurrentDirectory(), you may want to use Server.MapPath. You can give Server.MapPath the directory relative to the location of your web service where you want to save the file, otherwise you probably need to pass a full file path "C:\Files\file.txt". As far as the permissions issue, I am usually able to resolve this by adding write access to the folder I'm writing the file to for IIS_WPG and ASPNET users (These usernames may be different on your server).
You should be able to write files from web services. This is most likely a permissions or trust issue. If you are in a limited trust (i.e., Medium trust) ensure that you are writing to a patch in or below your web root. If you are already doing that, or are in a full trust environment check to make sure that the directory has permissions for the IIS worker process to write to it.

Categories