I need to impersonate the my code to run with a different windows user id, right now i am using some code which i got from web which is calling some native libraries.
the purpose of the code is to change the permissions on a file server user directories permissions.
I can change my folder permissions, but i have the credentials of the other user to go and change the permissions on his folder. But i am running the code on my machine by impersonating him.
But, i am getting un authorized exception.
the code i am using is:
[DllImport("advapi32.dll", SetLastError = true)]
private static extern int LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
I am not sure this is working in Windows 7 or not. Is there any one who faced any issue like this..?
Exception i am getting:
Messagee:"{"Attempted to perform an unauthorized operation."}"
stack trace:
at System.Security.AccessControl.Win32.SetSecurityInfo(ResourceType type, String name, SafeHandle handle, SecurityInfos securityInformation, SecurityIdentifier owner, SecurityIdentifier group, GenericAcl sacl, GenericAcl dacl)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, SafeHandle handle, AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, AccessControlSections includeSections)
at System.Security.AccessControl.FileSystemSecurity.Persist(String fullPath)
at System.IO.Directory.SetAccessControl(String path, DirectorySecurity directorySecurity)
at FolderAccessManager.Program.Main(String[] args) in
Could you please share some solutions..?
Have a look at WindowsIdentity.Impersonate. There you'll see an example of how to go about.
Are you using a domain joined machine with ASP.NET?
I got the exact same message tring this code in a asp.net application when running with the default apppool identity. Changing the apppool user to a domain user with 'domain admin' permissions solved this problem (also Windows 7).
Related
I'm developing a windows form application that has different features, one of these features is that the user has the ability to generate a receipt file in a pdf format.
The Problem I'm facing now is that when I run the application from visual studio this feature works perfectly, but when I publish and run the application in my pc and in other pcs the following error pops-up:
System.IO.DirectoryNotFoundException: C:\Users\USERNAME\AppData\Local\Apps\2.0\B8GVHPQK.4RG\XND3YQM7.9AB\hsar..tion_5a44077fdab68dde_0002.0000_e0623e33977d687d\TempReceipts
at System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType resourceType, Boolean isContainer, String name, SafeHandle handle, AccessControlSections includeSections, Boolean createByName, ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext)
at System.Security.AccessControl.FileSystemSecurity..ctor(Boolean isContainer, String name, AccessControlSections includeSections, Boolean isDirectory)
at System.Security.AccessControl.DirectorySecurity..ctor(String name, AccessControlSections includeSections)
at System.IO.DirectoryInfo.GetAccessControl()
The error tells that the directory, where the receipts are stored, is can't be found, while in visual studio the there is no such error.
I've read a little about and some said that this is occurred because of permissions restrictions, I've tried to use the following code to grant the WRITE permissions in the targeted directory, but still facing the same error:
AddDirectorySecurity("TempReceipts", #"Resources\\TempReceipts", FileSystemRights.WriteData, AccessControlType.Allow);
Here is the method:
public static void AddDirectorySecurity(string FileName, string Account, FileSystemRights Rights, AccessControlType ControlType)
{
// Create a new DirectoryInfo object.
DirectoryInfo dInfo = new DirectoryInfo(FileName);
// Get a DirectorySecurity object that represents the
// current security settings.
DirectorySecurity dSecurity = dInfo.GetAccessControl();
// Add the FileSystemAccessRule to the security settings.
dSecurity.AddAccessRule(new FileSystemAccessRule(Environment.UserName, Rights, ControlType));
// Set the new access settings.
dInfo.SetAccessControl(dSecurity);
}
so could anyone please suggest a solution for this problem?
The code has been taken from here This code example works fine my side its just add a service own local system) But I prepare Setup program I must think StartMode and User Account Type method because of customers system.
so How can I set Account Type and StartType method when I gonna add windows service.
there is every appearance that ServiceBootFlag enum provide StartType but Account Type still a problem. Or I'm open different idiom for set mentioned method for adding a windows service programmatically
And I read this question all post and comments I didn't see anything for set Startmode and User Account Type method When add a windows service.
[DllImport("advapi32.dll", EntryPoint = "CreateServiceA")]
private static extern IntPtr CreateService(IntPtr hSCManager, string
lpServiceName, string lpDisplayName, ServiceRights dwDesiredAccess, int
dwServiceType, ServiceBootFlag dwStartType, ServiceError dwErrorControl,
string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string
lpDependencies, string lp, string lpPassword);
After reading tons of similar posts I decided to came up with this one. Well, basically this problem is similar to many others, but somehow I can't make it work.
Here's the scenario, I have load balancing over 2 servers (servA and servB) and I need to force the app to create just on 1 of them. So I want to put the UNC path when I save files. I, obviously, have a problem creating files on the directory over the net.
If I run it with Cassini it's all good, I can access to the path cause it's logged with my account. As soon as I migrate the app on the development server it doesn't work anymore.
I know IIS uses the user associated with the app pool, so I checked that account (which is network_service) and added write privileges write on that folder.
Still not enough. What you think on "Everyone"?! It must work!
Oh, well, it's not.
Let's see some code:
Directory.CreateDirectory("\\\\my.ip.over.da.net\\c$\\inetpub\\wwwroot\\projfolder\\otherprojfolder\\test");
And this is the message I got when I try to create that folder.
{"Message":"Access to the path \u0027\\\\\\\\my.ip.over.da.net\\\\c$\\\\inetpub
\\\\wwwroot\\\\projfolder\\\\otherprojfolder\\\\test\u0027 is denied.","StackTrace":"
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n at
System.IO.Directory.InternalCreateDirectory(String fullPath, String path,
DirectorySecurity dirSecurity)\r\n at System.IO.Directory.CreateDirectory(String path,
DirectorySecurity directorySecurity)\r\n at
NSC.Ajax.GetData.testgrid()","ExceptionType":"System.UnauthorizedAccessException"}
It's called via AJAX for easier testing, this is why the response is formatted that way.
The problem is you're not going to have access to that location using the IIS credentials, the dev server is going to be on a separate domain somewhere else, and accessing back to your machine going to the c$ admin share isn't going to work, changing permissions at that level is.. a bit risky...
If you really have to access files on your local machine from your dev server, you'd probably be better off creating a share called test (C:\inetpub\wwwroot\projfolder\otherprojfolder\test) on your machine and set the permissions on this for Everyone to read (if you're going to need to create files and folders you'll need more, but I'd suggest only giving the minimum access you can get away with), pretty insecure though, but since your dev machine won't have any way of authenticating an account on a different network (your machine you're sharing the files from) you don't have much to play with!
So create a local shared folder, then just point your code to \\\\my.ip.over.da.net\\test.
Note, you'll need to set the permissions on the share and on the folder itself, if the share has enough permissions but the ACL on the folder doesn't agree you'll still get permissions denied.
You can impersonate a different user when creating the directory
public static void CreateDirectory(string myDirectory)
{
SafeTokenHandle safeTokenHandle;
bool returnValue = LogonUser(#Username, #Domain, #Password, 2, 0, out safeTokenHandle);
if (returnValue == true)
{
WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
using (WindowsImpersonationContext impersonatedUser = newId.Impersonate())
{
System.IO.Directory.CreateDirectory(myDirectory);
}
}
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle()
: base(true)
{
}
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
}
More details here :
http://msdn.microsoft.com/en-us/library/system.security.principal.windowsimpersonationcontext.aspx
For some odd reason, when I marshal the LogonUser DLLImport parameters I am no longer able to login succesfully when using the INTERACTIVE logon type, it works for NETWORK logon type.
This is my code:
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool LogonUser
(
[MarshalAs(UnmanagedType.LPStr)]
String lpszUsername,
[MarshalAs(UnmanagedType.LPStr)]
String lpszDomain,
[MarshalAs(UnmanagedType.LPStr)]
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr hToken
);
bResult = LogonUser(
"username",
".",
"password",
(int)LogonType.INTERACTIVE, // = 2
(int)LogonProvider.DEFAULT, // = 0
out hToken
);
Now, as-is my call to LogonUser fails (Logon Exception: Logon failure: unknown user name or bad password), but if I remove the [MarshalAs(UnmanagedType.LPStr)]s from the DLLImport it works fine, also if I switch to LogonType.NETWORK it works fine, why is it different with INTERACTIVE?
Sadly I need to keep it as I use this with other functions such as LoadUserProfile that needs it to be Marshalled (only way I could get it to work and not display unknown windows characters [squares]). Do I need to do some funky marshaling of strings or something to get it to validate correctly?
Any help would be appreciated.
Thanks,
LogonUser takes an LPTSTR, not an LPSTR, as parameters. You should just use the default string marshaling, and it will work correctly.
See LogonUser and pinvoke.net's declaration for a property P/Invoke of LogonUser.
I had the same issue, but the cause was different. Then I realized that in the place I work we must log-on our machines with a digital certificate instead of user and password.
I had forgotten that we have this restriction on our domain.
So I have to use another domain account, instead of mine, to test my application.
I don't know if these information will help but, but they maybe be of some use for other people.
How do I perform a network login, to access a shared driver for instance, programmatically in c#? The same can be achieved by either attempting to open a share through the explorer, or by the net use shell command.
P/Invoke call to WNetAddConnection2 will do the trick. Look here for more info.
[DllImport("mpr.dll")]
public static extern int WNetAddConnection2A
(
[MarshalAs(UnmanagedType.LPArray)] NETRESOURCEA[] lpNetResource,
[MarshalAs(UnmanagedType.LPStr)] string lpPassword,
[MarshalAs(UnmanagedType.LPStr)] string UserName, int dwFlags
);
You'll need to use Windows Identity Impersonation, take a look at these links
http://blogs.msdn.com/shawnfa/archive/2005/03/21/400088.aspx
http://blogs.msdn.com/saurabhkv/archive/2008/05/29/windowsidentity-impersonation-using-c-code.aspx