locked
Cannot read/write to registry - HK Current User using impersonation RRS feed

  • Question

  • I am trying to run an application whilst logged into a server using my account which has admin priveleges.  This application creates a number of users in active directory, assigns them to groups and then tries to set an environment variable for all of the users I created.

    I am trying to use impersonation as shown in the code below.

    The message boxes seem to inidcate that the impersonation is working however, when I try to create the key I get a message "Access to xxx is denied" and when I try to read the key I get the message "requested registry access is not allowed".  This happens when I impersonate one of my new users.

    If I impersonate an administrator, I do not get any errors and this works fine.

    Can anyone help?  I don't understand why a user can't access HKCU.

    MessageBox.Show( System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToString() );

     

    using ( new Impersonator( tbRegUsrNm.Text.ToString(), /*"myDomainname"*/ sDomian, tbRegPW.Text ) )

    {

     

    try

    {

     

    string sValue = "";

     

    rs.AddAccessRule(new RegistryAccessRule(tbRegUsrNm.Text.ToString(),

     

     RegistryRights.ReadKey | RegistryRights.WriteKey | RegistryRights.Delete,

     

     InheritanceFlags.None,

     

     PropagationFlags.None,

     

     AccessControlType.Allow));

     

    rk.CreateSubKey("NEWKEY", RegistryKeyPermissionCheck.Default, rs);

     

    Environment.SetEnvironmentVariable("NEWKEY", @\\path, EnvironmentVariableTarget.User);

     

    //RegistryKey rk = Registry.CurrentUser.OpenSubKey(@"Environment", false);

     

    sValue = rk.GetValue("NEWKEY", "Not Found").ToString();

     

    MessageBox.Show(sValue);

    }

     

    catch (Exception ex)

    {

    MessageBox.Show(ex.Message.ToString()); }

    Wednesday, September 1, 2010 3:04 PM

Answers

  • Your issue is probably that impersonation typically doesn't load the registry hive for that user. I don't know what's in your Impersonator class, but typically people do a LogonUser to get a token and then use it for impersonation. Look at the LoadUserProfile docs where it says that impersonation does not load the user's profile:

    http://msdn.microsoft.com/en-us/library/bb762281(VS.85).aspx

     


    Phil Wilson
    • Marked as answer by THEgaDJet Wednesday, September 8, 2010 10:46 AM
    Wednesday, September 1, 2010 11:19 PM
  • I needed to call loaduserprofile after logonuser in order to load the user's registry hive.  Can then access registry form hkey_users\SSID

    Ensure to call Unloaduserprofile

    • Marked as answer by THEgaDJet Wednesday, September 8, 2010 10:48 AM
    Wednesday, September 8, 2010 10:48 AM

All replies

  • Hi

    Have a look at my answer to this post:

    http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/8edf42c5-0e08-4415-884b-a3cc1f63ebba/#a8773d48-152c-4d31-8bbc-a7a7b53c97b4

    It should solve your issue.

    Regards

    James


    James Sales MCP, MCTS - Senior Software Developer - Solihull, England
    Wednesday, September 1, 2010 3:19 PM
  • Your issue is probably that impersonation typically doesn't load the registry hive for that user. I don't know what's in your Impersonator class, but typically people do a LogonUser to get a token and then use it for impersonation. Look at the LoadUserProfile docs where it says that impersonation does not load the user's profile:

    http://msdn.microsoft.com/en-us/library/bb762281(VS.85).aspx

     


    Phil Wilson
    • Marked as answer by THEgaDJet Wednesday, September 8, 2010 10:46 AM
    Wednesday, September 1, 2010 11:19 PM
  • Hi James, I have tried using both the non-overloaded method and putting false as the final parameter, as per the marked answer in the post you listed and this does not help.

    Also - I need to set the registry key.  As it is in HKCU, I would have though the user should have write access and not just administrators?

    Thursday, September 2, 2010 9:54 AM
  • Hi

    As Phil says it is probably to do with the Impersonation that you are using.  Is the Impersonator class one you wrote yourself or is it the SharePoint one that allows the user to run with elevated priveledges?

    Can you post a fuller code example?

    Regards

    James


    James Sales MCP, MCTS - Senior Software Developer - Solihull, England
    Thursday, September 2, 2010 10:18 AM
  • Hi Phil, I think that is the issue I am having.  I am using a LogonUser to get the token but when I try to open the registry entry from HKEY_USERS\S-XXX-XXX

    it doesn't exist.  I thought the LogonUser would load the registry hive but I am guessing not? 

    Do I also need to call LoadUserProfile in my impersonation class in order to get access to the user's registry hive?

     

    Thanks for your help

    My class is below:

    public

     

    class Impersonation

    {

     

    /// <summary>

     

    /// Windows Token.

     

    /// </summary>

     

    private IntPtr tokenHandle = new IntPtr(0);

     

    /// <summary>

     

    /// The impersonated User.

     

    /// </summary>

     

    private WindowsImpersonationContext impersonatedUser;

     

    /// <summary>

     

    /// Initializes a new instance of the Impersonation class.

     

    /// </summary>

     

    /// <param name="domainName">Domain name of the impersonated user.</param>

     

    /// <param name="userName">Name of the impersonated user.</param>

     

    /// <param name="password">Password of the impersonated user.</param>

     

    /// <remarks>

     

    /// Uses the unmanaged LogonUser function to get the user token for

     

    /// the specified user, domain, and password.

     

    /// </remarks>

     

    ///

     

    public SecurityIdentifier si;

     

    public string SDDLSID;

     

     

    public Impersonation(string userName, string domainName, string password)

    {

     

    // Use the standard logon provider.

     

    const int LOGON32_PROVIDER_DEFAULT = 0;

     

    // Create a primary token.

     

    const int LOGON32_LOGON_INTERACTIVE = 2;

     

    this.tokenHandle = IntPtr.Zero;

     

    // Call LogonUser to obtain a handle to an access token.

     

    bool returnValue = LogonUser(

     

    userName,

     

    domainName,

     

    password,

     

    LOGON32_LOGON_INTERACTIVE,

     

    LOGON32_PROVIDER_DEFAULT,

     

    ref this.tokenHandle);

     

    if (false == returnValue)

    {

     

    // Something went wrong.

     

    int ret = Marshal.GetLastWin32Error();

     

    throw new System.ComponentModel.Win32Exception(ret);

    }

     

    WindowsIdentity newId = new WindowsIdentity(this.tokenHandle);

     

     

    LoadUserProfile(this.tokenHandle,);

     

     

    MessageBox.Show(newId.User.Value);

     

    MessageBox.Show(newId.Name);

     

    SDDLSID = newId.User.Value;

     

    SecurityIdentifier si = newId.Owner;

    }

     

    /// <summary>

     

    /// Starts the impersonation.

     

    /// </summary>

     

    public void Impersonate()

    {

     

    // Create Identity.

     

    WindowsIdentity newId = new WindowsIdentity(this.tokenHandle);

     

    // Start impersonating.

     

    this%

    Friday, September 3, 2010 2:03 PM
  • Hi Phil, I think that is the issue I am having.  I am using a LogonUser to get the token but when I try to open the registry entry from HKEY_USERS\S-XXX-XXX

    it doesn't exist.  I thought the LogonUser would load the registry hive but I am guessing not? 

    Do I also need to call LoadUserProfile in my impersonation class in order to get access to the user's registry hive?

     

    Thanks for your help

    My class is below:

    public

     

    class Impersonation

    {

     

    /// <summary>

     

    /// Windows Token.

     

    /// </summary>

     

    private IntPtr tokenHandle = new IntPtr(0);

     

    /// <summary>

     

    /// The impersonated User.

     

    /// </summary>

     

    private WindowsImpersonationContext impersonatedUser;

     

    /// <summary>

     

    /// Initializes a new instance of the Impersonation class.

     

    /// </summary>

     

    /// <param name="domainName">Domain name of the impersonated user.</param>

     

    /// <param name="userName">Name of the impersonated user.</param>

     

    /// <param name="password">Password of the impersonated user.</param>

     

    /// <remarks>

     

    /// Uses the unmanaged LogonUser function to get the user token for

     

    /// the specified user, domain, and password.

     

    /// </remarks>

     

    ///

     

    public SecurityIdentifier si;

     

    public string SDDLSID;

     

     

    public Impersonation(string userName, string domainName, string password)

    {

     

    // Use the standard logon provider.

     

    const int LOGON32_PROVIDER_DEFAULT = 0;

     

    // Create a primary token.

     

    const int LOGON32_LOGON_INTERACTIVE = 2;

     

    this.tokenHandle = IntPtr.Zero;

     

    // Call LogonUser to obtain a handle to an access token.

     

    bool returnValue = LogonUser(

     

    userName,

     

    domainName,

     

    password,

     

    LOGON32_LOGON_INTERACTIVE,

     

    LOGON32_PROVIDER_DEFAULT,

     

    ref this.tokenHandle);

     

    if (false == returnValue)

    {

     

    // Something went wrong.

     

    int ret = Marshal.GetLastWin32Error();

     

    throw new System.ComponentModel.Win32Exception(ret);

    }

     

    WindowsIdentity newId = new WindowsIdentity(this.tokenHandle);

     

     

    LoadUserProfile(this.tokenHandle,);

     

     

    MessageBox.Show(newId.User.Value);

     

    MessageBox.Show(newId.Name);

     

    SDDLSID = newId.User.Value;

     

    SecurityIdentifier si = newId.Owner;

    }

     

    /// <summary>

     

    /// Starts the impersonation.

     

    /// </summary>

     

    public void Impersonate()

    {

     

    // Create Identity.

     

    WindowsIdentity newId = new WindowsIdentity(this.tokenHandle);

     

    // Start impersonating.

     

    this.impersonatedUser = newId.Impersonate();

    }

     

    /// <summary>

     

    /// Stops the impersonation and releases security token.

     

    /// </summary>

     

    public void Revert()

    {

     

    // Stop impersonating.

     

    if (this.impersonatedUser != null)

    {

     

    this.impersonatedUser.Undo();

    }

     

    // Release the token.

     

    if (this.tokenHandle != IntPtr.Zero)

    {

     

    CloseHandle(this.tokenHandle);

    }

    }

     

    [DllImport("advapi32.dll", SetLastError = true)]

     

    private static extern bool LogonUser(

     

    string lpszUsername,

     

    string lpszDomain,

     

    string lpszPassword,

     

    int dwLogonType,

     

    int dwLogonProvider,

     

    ref IntPtr phToken);

    [

    DllImport("kernel32.dll", CharSet = CharSet.Auto)]

     

    private static extern bool CloseHandle(IntPtr handle);

    }

    }

    Friday, September 3, 2010 2:03 PM
  • I needed to call loaduserprofile after logonuser in order to load the user's registry hive.  Can then access registry form hkey_users\SSID

    Ensure to call Unloaduserprofile

    • Marked as answer by THEgaDJet Wednesday, September 8, 2010 10:48 AM
    Wednesday, September 8, 2010 10:48 AM