1

I have two user accounts in my computer

User 1 (regular user)

Admin

Now I have folder "e:\Folder1" for which only Admin account has full access. User ! cannot access the folder.

I have a WPF Application Where It would run only within the User 1 account. I want the user 1 to user the wpf application to access "Folder1".

I want to know how to do it using C#.

I tried the following it doesnt work.

NetworkCredential theNetworkCredential = new NetworkCredential(@"admin", "pass");
            CredentialCache theNetCache = new CredentialCache();
            theNetCache.Add(new Uri(@"E:\SDAVideo"), "Basic", theNetworkCredential);
            string[] theFolders = Directory.GetDirectories(@"E:\SDAVideo");

Here is what I have tried. Using following code I am able to get the Windows of Identity of Admin user account

SafeTokenHandle safeTokenHandle;
        try
        {
            const int LOGON32_PROVIDER_DEFAULT = 0;
            //This parameter causes LogonUser to create a primary token. 
            const int LOGON32_LOGON_INTERACTIVE = 2;

            // Call LogonUser to obtain a handle to an access token. 
            bool returnValue = LogonUser("admin", "", "pass",
                LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
                out safeTokenHandle);
            if (false == returnValue)
            {
                int ret = Marshal.GetLastWin32Error();
                Debug.Write("\nLogonUser failed with error code : " + ret);
                throw new System.ComponentModel.Win32Exception(ret);
            }
            using (safeTokenHandle)
            {
                Debug.Write("\nDid LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
                Debug.Write("\nValue of Windows NT token: " + safeTokenHandle);

                // Check the identity.
                Debug.Write("\nBefore impersonation: "
                    + WindowsIdentity.GetCurrent().Name);
                Debug.Write("\nWriteAccess before: " + DirectoryHasPermission(@"E:\SDAVideo", WindowsIdentity.GetCurrent(), FileSystemRights.Write));
                // Use the token handle returned by LogonUser. 
                using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(safeTokenHandle.DangerousGetHandle()))
                {

                    // Check the identity.
                    Debug.Write("\nAfter impersonation: "
                        + WindowsIdentity.GetCurrent().Name);
                    AccessFolder(WindowsIdentity.GetCurrent(), @"E:\SDAVideo");
                    //Debug.Write("\nWriteAccess after: " + DirectoryHasPermission(@"E:\SDAVideo", WindowsIdentity.GetCurrent(), FileSystemRights.Write));
                }
                // Releasing the context object stops the impersonation 
                // Check the identity.
                Debug.Write("\nAfter closing the context: " + WindowsIdentity.GetCurrent().Name);

            }

        }
        catch (Exception ex)
        {
            Debug.Write("\n1" + ex.ToString());
        }

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);
        }
    }

public static bool DirectoryHasPermission(string DirectoryPath,  WindowsIdentity identity, FileSystemRights AccessRight)
    {
        //if (string.IsNullOrEmpty(DirectoryPath)) return false;

        try
        {
            AuthorizationRuleCollection rules = Directory.GetAccessControl(DirectoryPath).GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier));
            //WindowsIdentity identity = WindowsIdentity.GetCurrent();
            Debug.Write("\nUSER: " + identity.Name);
            foreach (FileSystemAccessRule rule in rules)
            {
                if (identity.Groups.Contains(rule.IdentityReference))
                {
                    if ((AccessRight & rule.FileSystemRights) == AccessRight)
                    {
                        if (rule.AccessControlType == AccessControlType.Allow)
                            return true;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Debug.Write("\n2 " + ex.ToString());
        }
        return false;
    }

public static void AccessFolder(WindowsIdentity identity, string DirectoryPath)
    {
        try
        {
            Debug.Write("\nUSER: " + identity.Name);
            DirectoryInfo myDirectoryInfo = new DirectoryInfo(DirectoryPath);
            DirectorySecurity myDirectorySecurity = myDirectoryInfo.GetAccessControl();

            myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(identity.Name, FileSystemRights.Write, AccessControlType.Allow));

            myDirectoryInfo.SetAccessControl(myDirectorySecurity);
            string pathString = System.IO.Path.Combine(DirectoryPath, "test.txt");
            if (!System.IO.File.Exists(pathString))
            {
                using (System.IO.FileStream fs = System.IO.File.Create(pathString))
                {
                    for (byte i = 0; i < 100; i++)
                    {
                        fs.WriteByte(i);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Debug.Write("\n3 " + ex.ToString());
        }
    }

Error I get as follows System.UnauthorizedAccessException: Attempted to perform an unauthorized operation.

System.InvalidOperationException: Method failed with unexpected error code 1346.


All of these failed, Only thing I am able to do is successfully get the Admin user windows identity. Now with that I need to solve the two issues 1. How to check if app has write access using the windows identity of the admin 2. If so how to write something into the folder.

1 Answers1

1

Try that:

using System;
using System.IO;
using System.Security.AccessControl;

namespace MyWpfApplication
{
    public class AccessRules
    {
        private void SetAccessRuleForCurrentUser()
        {
            DirectoryInfo myDirectoryInfo = new DirectoryInfo(@"e:\Folder1");
            DirectorySecurity myDirectorySecurity = myDirectoryInfo.GetAccessControl();

            myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(System.Security.Principal.WindowsIdentity.GetCurrent().Name, FileSystemRights.Read, AccessControlType.Allow));

            myDirectoryInfo.SetAccessControl(myDirectorySecurity);
        }
    }
}
Orkun Bekar
  • 1,447
  • 1
  • 15
  • 36
  • Thanks for your help. I tried yours and updated the result. I got the windows identity of the admin account. Now I need to write to the folder using the admin account windows identity. – Raghulan Gowthaman May 12 '15 at 14:29