I know I can use the WNetAddConnection2 and similar variants to connect to remote shares using custom credentials. I would like to do the same for mapped drives (ex:\\MyShare\MyFolder mapped to Y:) and my local disks (eg: C:,D:,E:, etc...)
If I point WNetAddConnection to something not \\ it fails...
Is there a function specific for this scenario???
At work we use a WindowsImpersonationContext to handle this situation. Originally we used it in a VB.NET ASP.NET application, but it is readily modified.
Microsoft Support has a great article on how to do it. (We originally used it for Network Drives, but it can be expanded to local disks as well.)
You can basically impersonate a valid user account, which will grant you permissions that account would have in the situation. I had to use it to get access to a network drive at work, on a computer that was not a part of the domain. (As such, we had to provide a Username, Domain, and Password for this user account that was not on our domain network and this topic served us well.)
Related
I am using Linq to sql from c# to connect to sql server in a WCF service. I am using windows authentication to connect to database. I want to use other user windows authentication to connect to sql server from Linq to sql. Is their a way to do that.
From the comments I assume you want to connect to a production database during development for a short period, until your development account gets access to the database.
First of all, don't do this. It's a bad idea for several reasons. Working against a production database is bad.So is writing code that will be removed once you get proper access.
If you only want to test your service, just use the Windows account credentials you already have as the service account.
As a last resort, you can impersonate a specific account using WindowsIdentity.Impersonate. The function's sample shows how to authenticate the user using P/Invoke and the LogonUser Win32 API. You'll have to take care to call Undo once you are finished impersonating otherwise your code will keep running with the old identity.
If Kerberos is properly implemented in the domain and your account has permission to impersonate the other account, you can use the WindowsIdentity constructor that only needs a user principal name. That's far safer than storing a username and password in a config file, even it you encrypt them.
A better idea is to clone the data you need (all or just a sample) to a local database and use this during development. This way you will be free to experiment without affecting the production environment (or get blamed for anything untoward).
The Entity data Model wizard says :
This connection string appears to contain sensitive data (for example, a password) that is required to
connect to the database. Storing sensitive data in the connection string can be a security risk. Do you want
to include this sensitive data in the connection string?
I have included the db password in many live projects, How risky is it?
It is all about minimizing your risk. Lets say a attacker found a way of getting a copy of the code from the server but not a way to execute code on the server:
If you stored the username and password in the code the attacker now has direct access to your database with the same privileges as your code.
If you used integrated authentication the attacker still does not have any way to get data from your database as he can not impersonate the user to perform integrated authentication.
If you use proper IIS encrption you must be able to execute code on the server itself (the encryption key is tied to the server not the code) to be able to get the username and password. So the attacker still would not have access to the database.
Risk is something only you can evaluate. Is it a test server in your bedroom that is not connected to the internet? Not much risk. Is it an internal company server for a small company without any real sensitive information? Maybe not much risk.
Is it connected to the internet? It's risky. It's always risky if you're connected to the internet. Why? Because the internet is not a safe place. It doesn't matter how big or small you are, you're a target. There are automated bots that roam the net looking for vulnerable systems and automatically taking them over. Then, they infect the systems with Malware to spread to your users. Or they sell your credentials to other hackers so they can use your servers for command and control centers for spam networks. Or any number of other situations.
If you're on the internet, you are at risk. Period. So always take security seriously.
It comes down to how secure is your domain and IIS on your web server? IIS and web.config is at the root of your web application. If you have problems with domain security and people being able to access your inetpub or wwwroot directories and their children, then your website is always at risk. If you are using a third party provider such as go daddy or 1 and 1, they are relatively secure.
If you are hosting it yourself, you want to limit access, especially directory listing privileges. You want to mitigate permissions as much as possible. Also with your SQL Account you use for your web applications, limit database privileges and mitigate access as much as possible. Also do not use generic accounts for access, and have each web app with their own account. In a domain, you want to make sure you take the necessary precautions in your DMZ to help secure that web server if it sits on the edge of your network.
Internal threats are more prevalent than external threats. Those already on your domain with elevated privileges may already have access to your root of your web application without you even knowing it! Keep an eye on your delegate accounts, too that IIS uses for web apps and web services.
You should encrypt the connection string using aspnet_regiis Take a look at this link too (How To Encrypt web.config), for some useful information.
With regards to other aspects of the web application, you need to make sure you are setting the least privileges possible, making sure you research all web application vulnerabilities and how to protect against these.
Replace user name and password with Integrated Security in the Connection string.
Ensure that the process using the connection executes with a user that has been registered on the SQL server with (just enough) privilegies to perform its tasks. This should minimize the risk of your system being compromised.
In my ASP.NET application, I need to be able to authenticate/authorise against local Windows users/groups (ie. not Active Directory) on a different machine, as well as be able to change the passwords of said remote local Windows accounts.
Yes, I know Active Directory is built for this sort of thing, but unfortunately the higher ups have decreed it needs to be done this way (so authentication against users in a database is out as well).
I've tried using DirectoryEntry and WinNT like so:
DirectoryEntry user = new DirectoryEntry(String.Format("WinNT://{0}/{1},User",
serverName, username), username, password, AuthenticationTypes.Secure)
but this results in an exception when you try to log in more than one user:
Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed. Disconnect all previous connections to the server or shared resource and try again.
I've tried making sure my DirectoryEntries are used inside a using block, so they're disposed properly, but this doesn't seem to fix the issue. Plus, even if that did work it is possible that two users could hit that line of code concurrently and therefore try to create multiple connections, so it would be fragile anyway.
Is there a better way to authenticate against local Windows accounts on a remote machine, authorise against their groups, and change their passwords?
Thanks for your help in advance.
In my opinion you cannot do this from your ASP.Net script. Because from the server you need to know what all client machines will access your page and provide sufficient rights to the server to access the client to do this extra user authentication and password change. Also this is cumbersome. One solution is to use an activex control and write this logic (user authentication and password change) in that activex control and provide the activex control sufficient rights in the clients. It is a bit ugly but this is the only possible solution without ADS.
How can a C# program running as LocalSystem impersonate the login identity of another user temporarily? Roughly speaking I have a Windows Service that I'd like to run as LocalSystem but at times impersonate user XYZ (when connecting to a db using windows integrated security).
Most important of all: Is there a way to do this without knowing the other user's password?
Note: if a password is mandatory is there a recommended strategy for storing a password securely (c# and/or vbscript).
It's possible, although it requires you to do a lot of code. See NtCreateToken and CreateToken. You need SeCreateTokenPrivilege, although that won't be a problem since you're running under NT AUTHORITY\SYSTEM. You can then use the created token to impersonate inside a thread.
Short answer: you can't without the user password or the user calling your service through COM.
To impersonate another user in your process, you have to call ImpersonateLoggedOnUser. ImpersonateLoggedOnUser requires a token handle. There are several ways you can obtain token handle:
by logging on as the user with LogonUser. This however requires you to know the user password.
by duplicating an existing token with CreateRestrictedToken, DuplicateToken, or DuplicateTokenEx.
by opening the token from another process or thread, that already is loggen on as the user, with OpenProcessToken or OpenThreadToken
For the password storing part, you may want to have a look at this question asked recently.
This was my answer:
You could/should use the DPAPI, the Data Protection API that provides storage encryption.
It's there just for this type of problem.
Encryption of the storage is based on either:
the user account, so only the logged-in user can access the data. This makes the data transferable to another PC with the exact same user credentials.
the machine, making the data only accessible on that particular machine setup and not transferable to another PC.
There is a dnrTV show with Karl Franklin showing exactly what's needed to implement this, and other encryption functions.
The source code from the show is also available on the page.
There are, of course, lots of other articles on that subject.
I have a web application that needs to read (and possibly write) files from a network share. I was wondering what the best way to do this would be?
I can't give the network service or aspnet accounts access to the network share. I could possibly use impersonation.
The network share and the web application are both hosted on the same domain and I can create a new user on the domain specifically for this purpose however I'm not quite sure how to join the dots between creating the filestream and specifying the credentials to use in the web application.
Unfortunately the drive isn't mapped as a network drive on the machine, it's only available to me as a network share so unfortunately I can't make a transparent call.
There is one problem I can think of with impersonation... I can only impersonate one user per application domain I think but I'm happy to be corrected. I may need to write this file to several different shares which means I may have to impersonate several users.
I like the idea of creating a token... if I can do that I'll be able to ask the use up front for their credentials and then dynamically apply the security and give them meaningful error messages if access is denied... I'm off to play but I'll be back with an update.
Given everyone already has domain accounts. Try IIS integrated authentication. You will get an ugly logon box off network but your creds should pass down to the file share.
#lomaxx
Are you saying that only you have perms to the share or that you manually mapped it to a drive letter. If the later you can use ucn \host\share the same way you would use a c:\shared_folder.
Random
Would it be a burden to mirror the share to a local folder on the host? I hear ROBOCOPY is pretty handy.
Another Idea. Run IIS on your target share you can read via http and if you need to write investigate webdav.
I've had no problems connecting to network shares transparently as if they were local drives. The only issue you may have is what you mentioned: having the aspnet account gain access to the share. Impersonation is probably the best way to do this.
You should be able to use any filestream objects to access the network share as long as it has a drive letter on the server machine.
Impersonation worked well for me in this scenario. We had a wizard that uploaded a zip file through the website, but we load balanced the site. Therefore needed to setup a way to save the file on all the machines.
There are many different ways to do it. We decided to make all requests to run under the user we setup and just added the web.config entry and setup the security permissions on the folders for the user. This kb article explains the setup very well.
You do have some options and one of of those is impersonation as you mentioned. However, another one I like to use and have used in the past is a trusted service call. Let's assume for a moment that it's always much safer to limit access through IIS to ensure there are as few holes as possible. With that let's go down this road.
Build a WCF service that has a couple of entry points and the interface might look like this.
public interface IDocumentService
{
public string BuildTrustedRelationship(string privateKey);
public byte[] ReadFile(string token, string fileName);
public void WriteFile(string token, string fileName, byte[] file);
}
Now, you can host this service via a Windows service very easily and so now all you need to do is on Application_start build the relationship with the service to get your token and you're off to the races. The other nice thing here is that this service is internal, trusted, and I've even hosted it on the file server before and so it's much easier to grant permissions to this operation.
If you can create a new AD user, I think the simplest solution is to have the Application Pool run under that AD account's authority, which would mean your application is now running as the AD user. You would need to add the AD user to the IIS Worker Process Group on the machine running your application. Then as long as your AD user has write permissions on the network share, you should be able to use the UNC path in your file operations.