Guga
Guga

Reputation: 37

How to change folders permission to the current user by using admin credentials?

Ok, so I've been searching for a while and the title explains pretty much what I want to do. Also, there is no problem hard-coding the admin credentials in the code.

Initially I wrote some code in c# that ALMOST solved the problem:

private void button2_Click(object sender, EventArgs e)
    {

        DirectoryInfo myDirectoryInfo = new DirectoryInfo(textBox1.Text);

        DirectorySecurity myDirectorySecurity = myDirectoryInfo.GetAccessControl();
        string User = System.Environment.UserDomainName + "\\" + comboBox1.SelectedItem.ToString();


        myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(User, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));

        //myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(User, FileSystemRights.Write, InheritanceFlags.ContainerInherit, PropagationFlags.None, AccessControlType.Allow));

        myDirectoryInfo.SetAccessControl(myDirectorySecurity);
        MessageBox.Show("Permissions Altered Successfully" + User);

    }

This works just fine if I use on a folder that I already have permission, but what I need is a method that uses admin credentials to grant permission to a folder that a regular user don't have.

Later I tried to write some stuff in vbscript:

    strHomeFolder = "C:\test"
strUser = " DOMAIN\user"

Set WshShell = CreateObject("WScript.Shell")

WshShell.Run "%COMSPEC% /c Echo Y| cacls  "& strHomeFolder & " /e /c /g "& strUser &":F", 2, True

But i couldn't find a way to pass the admin credentials. So lastly I wrote another code to try to get it done:

private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            //string passwordPre = "PASSWORD";
            //char[] passwordChars = passwordPre.ToCharArray();
            //SecureString password = new SecureString();
            //foreach (char c in passwordChars)
            //{
            //    password.AppendChar(c);
            //}


            ProcessStartInfo p = new ProcessStartInfo(@"D:\\test.vbs");
            //p.UseShellExecute = false;
            //p.UserName = "username";
            //p.Domain = "DOMAIN";

            //p.Password = password;
            Process.Start(p);
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }
    }

This time I just tried to pass admin credentials using a process, but it generated the message: The specified executable is not a valid application for this OS plataform.

So, is there any method that I can use to pass credentials? (Can be in c# or vbscript).

Thanks in advance.

Upvotes: 0

Views: 3292

Answers (1)

Kurubaran
Kurubaran

Reputation: 8902

Impersonation will solve your problem. When you execute the code within the impersonated context, logic placed within that context will be executed with the previlege of the impersonated user. Following class reards the impersonation configuration values from the web.config file. You can modify it read from app.config or whatever the source.

Required configurations

  1. User Name
  2. Password
  3. Domain Name

Impersonation Class

 public class Impersonator : IDisposable
    {
        #region Win32 Advanced API calls

        /// <summary>
        /// Logons the user.
        /// </summary>
        /// <param name="lpszUserName">Name of the LPSZ user.</param>
        /// <param name="lpszDomain">The LPSZ domain.</param>
        /// <param name="lpszPassword">The LPSZ password.</param>
        /// <param name="dwLogOnType">Type of the dw log on.</param>
        /// <param name="dwLogOnProvider">The dw log on provider.</param>
        /// <param name="phToken">The ph token.</param>
        /// <returns></returns>
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        private static extern int LogonUser(String lpszUserName,
                String lpszDomain,
                String lpszPassword,
                int dwLogOnType,
                int dwLogOnProvider,
                ref IntPtr phToken);

        /// <summary>
        /// Duplicates the token.
        /// </summary>
        /// <param name="hToken">The h token.</param>
        /// <param name="impersonationLevel">The impersonation level.</param>
        /// <param name="hNewToken">The h new token.</param>
        /// <returns></returns>
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        private static extern int DuplicateToken(IntPtr hToken,
                int impersonationLevel,
                ref IntPtr hNewToken);

        /// <summary>
        /// Reverts to self.
        /// </summary>
        /// <returns></returns>
        [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        private static extern bool RevertToSelf();


        /// <summary>
        /// Closes the handle.
        /// </summary>
        /// <param name="handle">The handle.</param>
        /// <returns></returns>
        [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true,
            BestFitMapping = false, ThrowOnUnmappableChar = true)]
        private static extern bool CloseHandle(IntPtr handle);

        #endregion

        #region Fields

        /// <summary>
        /// Field to hold the impersonation Context
        /// </summary>
        WindowsImpersonationContext impersonationContext;

        /// <summary>
        /// Track whether Dispose has been called.
        /// </summary>
        private bool disposed;

        #region Constants
        /// <summary>
        /// Logon32 Logon Interactive 
        /// </summary>
        public const int INTERACTIVE_NUMBER = 2;

        /// <summary>
        /// Logon32 Provider Default
        /// </summary>
        public const int DEFAULT_NUMBER = 0;

        /// <summary>
        /// Impersonating user name key
        /// </summary>
        public const string ImpersonatingUserNameKey = "ImpersonatingUserName";

        /// <summary>
        /// Impersonating user password key
        /// </summary>
        public const string ImpersonatingPasswordKey = "ImpersonatingUserPassword";

        /// <summary>
        /// Impersonating user domain key
        /// </summary>
        public const string ImpersonatingDomainNameKey = "ImpersonatingDomain";

        #endregion

        #endregion

        #region Construction/Destruction/Initialization

        /// <summary>
        /// Constructor of the impersonator
        /// </summary>
        public Impersonator()
        {
            if (!ImpersonateUser(ConfigurationManager.AppSettings[ImpersonatingUserNameKey],
                                    ConfigurationManager.AppSettings[ImpersonatingDomainNameKey],
                                    ConfigurationManager.AppSettings[ImpersonatingPasswordKey]))
            {
                //TODO: Log Exception
            }
        }

        #endregion

        #region Public Methods

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Impersonate User with the given user credentials
        /// </summary>
        /// <param name="userName">User Name</param>
        /// <param name="domain">Domain</param>
        /// <param name="password">Password</param>
        /// <returns>True if success, false otherwise</returns>
        private bool ImpersonateUser(String userName, String domain, String password)
        {
            WindowsIdentity tempWindowsIdentity;
            IntPtr token = IntPtr.Zero;
            IntPtr tokenDuplicate = IntPtr.Zero;

            if (RevertToSelf())
            {
                if (LogonUser(userName, domain, password, INTERACTIVE_NUMBER,
                        DEFAULT_NUMBER, ref token) != 0)
                {
                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
                    {
                        tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                        impersonationContext = tempWindowsIdentity.Impersonate();
                        if (impersonationContext != null)
                        {
                            CloseHandle(token);
                            CloseHandle(tokenDuplicate);
                            return true;
                        }
                    }
                }
            }
            if (token != IntPtr.Zero)
                CloseHandle(token);
            if (tokenDuplicate != IntPtr.Zero)
                CloseHandle(tokenDuplicate);
            return false;
        }

        /// <summary>
        /// Undo impersonation
        /// </summary>
        private void StopImpersonation()
        {
            impersonationContext.Undo();
        }

        #endregion

        #region Protected Methods

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    StopImpersonation();
                }

                // Note disposing has been done.
                disposed = true;
            }
        }

        #endregion
    }

How to call the method

Using(Impersonator impersonator = new Impersonator())
{
  //Write the folder accessing logic here
}

Upvotes: 3

Related Questions