سؤال

Using the following method I impersonate as local administrator user (with elevated privileges) and pass the function that has to be executed within the impersonation context.

    /// <summary>
    /// Attemps to impersonate a given windows user and to run a given function within the impersonation context.
    /// </summary>
    /// <param name="userInformation">The user name and password for impersonation.</param>
    /// <param name="functionAsImpersonatedUser">The function to be executed within the impersonation context.</param>
    /// <returns>True if the operation was successful, false and an error message otherwise.</returns>
    public static BooleanResult ExecuteAsImpersonatedUser(UserInformation userInformation, Func<BooleanResult> functionAsImpersonatedUser)
    {
        BooleanResult retval = new BooleanResult();
        IntPtr returnedToken = IntPtr.Zero;
        try
        {
            //Note: the logon type 'batch' seems to return a token with elevated privileges
            bool success = NativeMethods.LogonUser(userInformation.Name, userInformation.Domain ?? ".", userInformation.Password, (int)LogonType.Batch, (int)LogonProvider.Default, out returnedToken);
            if (false == success)
            {
                int ret = Marshal.GetLastWin32Error();
                throw new Win32Exception(ret);
            }
            using (WindowsImpersonationContext impersonatedUser = WindowsIdentity.Impersonate(returnedToken))
            {
                retval = functionAsImpersonatedUser();
            }
        }
        catch (OutOfMemoryException o)
        {
            string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorImpersonatingUser, userInformation.Domain, userInformation.Name, o.Message);
            retval.ProcessGeneralException(o, logMessage);
        }
        catch (SecurityException s)
        {
            string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorImpersonatingUser, userInformation.Domain, userInformation.Name, s.Message);
            retval.ProcessGeneralException(s, logMessage);
        }
        catch (UnauthorizedAccessException u)
        {
            string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorImpersonatingUser, userInformation.Domain, userInformation.Name, u.Message);
            retval.ProcessGeneralException(u, logMessage);
        }
        catch (Win32Exception w)
        {
            string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorImpersonatingUser, userInformation.Domain, userInformation.Name, w.Message);
            retval.ProcessGeneralException(w, logMessage);
        }
        finally
        {
            if (NativeMethods.CloseHandle(returnedToken))
                LogUtility.Instance.Write(String.Format(CultureInfo.InvariantCulture, TranslationStrings.CloseUserHandleSuccess, userInformation.Domain, userInformation.Name), 4);
            else
                LogUtility.Instance.Write(String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorCloseUserHandle, userInformation.Domain, userInformation.Name), 2);
        }
        return retval;
    }

No problems with that so far. After replacing LogonType.Interactive by LogonType.Batch even seems to return a user token with elevated privileges.

The function within the impersonation context creates a localDB instance if required, starts it and then tries to set up the database using insallation scripts and SMO. The first thing that occurs to me is that the instance owner is not the impersonated local administrator, why is that: do I have a wrong understanding of how impersonation or localDB works?

As only to be expected using a connecting like "Data Source=(localdb).[instanceName];Initial Catalog=[databaseName];Integrated Security=true" doesn’t work. That consequently results in a ConnectionFailureException.

But I still don’t get it, why is my impersonated local administrator not the owner of the instance (even if I create the instance within the impersonated context) , and thus not able to access the database?

The solution might be obvious, but I’m stuck.

Best Regards,

Stephan

هل كانت مفيدة؟

المحلول

Silly me!

By setting the verb, user name and password properties in the process start info it is possible to install the localDB instance and specify a different owner...

    public static ConsoleOutputResult CreateInstance(UserInformation user)
    {
        if (user == null)
            throw new ArgumentNullException("user");

        ConsoleOutputResult retval = new ConsoleOutputResult();
        try
        {
            ProcessStartInfo startInfo = new ProcessStartInfo(Path.Combine(localDBPath, "SqlLocalDB.exe"), String.Format(CultureInfo.InvariantCulture, "create {0}", instanceName))
            {
                CreateNoWindow = true,
                Domain = user.Domain,
                ErrorDialog = false,
                LoadUserProfile = true,
                Password = user.Password.ConvertToSecureString(),
                RedirectStandardError = true,
                RedirectStandardOutput = true,
                UserName = user.Name,
                UseShellExecute = false,
                Verb = "runas"
            };
            using (Process process = Process.Start(startInfo))
            {
                process.WaitForExit();
                retval.Error = process.StandardError.ReadToEnd();
                retval.Output = process.StandardOutput.ReadToEnd();
                retval.Success = String.IsNullOrEmpty(retval.Error);
                if (retval.Success)
                    LogUtility.Instance.Write(retval.Output, 4);
            }
        }
        catch (Exception e)
        {
            string logMessage = String.Format(CultureInfo.InvariantCulture, ErrorMessages.ErrorCreateLocalDB, e.Message);
            retval.ProcessGeneralException(e, logMessage);
            throw new SmartAppWizardException(logMessage, e.InnerException);
        }
        return retval;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top