protected override void Dispose(bool disposing) { if (stream != null) { stream.Dispose(); } GC.SuppressFinalize(this); if (isOriginal == false) { return; } cts.Cancel(); if (basePtr != null) { Win32MemoryMapNativeMethods.UnmapViewOfFile(basePtr); } if (mmf != IntPtr.Zero) { Win32NativeMethods.CloseHandle(mmf); } if (fileHandle != null) { fileHandle.Close(); } }
/// <summary> /// Uses P/Invoke to start the process using the login token obtained for the user. /// </summary> /// <param name="token">The login token to use to create the process with.</param> private void StartWithCreateProcessAsUser(IntPtr token) { var startinfo = _process.StartInfo; var path = Path.GetFullPath(startinfo.FileName); var dir = Path.GetDirectoryName(path); bool processCreated = false; Win32NativeMethods.PROCESS_INFORMATION pi = new Win32NativeMethods.PROCESS_INFORMATION(); Win32NativeMethods.SECURITY_ATTRIBUTES saProcess = new Win32NativeMethods.SECURITY_ATTRIBUTES(); saProcess.bInheritHandle = true; saProcess.nLength = (uint)Marshal.SizeOf(saProcess); Win32NativeMethods.SECURITY_ATTRIBUTES saThread = new Win32NativeMethods.SECURITY_ATTRIBUTES(); saThread.bInheritHandle = true; saThread.nLength = (uint)Marshal.SizeOf(saThread); Win32NativeMethods.STARTUPINFO si = new Win32NativeMethods.STARTUPINFO(); si.lpDesktop = string.Empty; si.cb = (uint)Marshal.SizeOf(si); lock (createProcessLock) { _pipeServerToClient = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.Inheritable); _pipeServerFromClient = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable); _pipeServerErrorFromClient = new AnonymousPipeServerStream(PipeDirection.In, HandleInheritability.Inheritable); try { // although these are separate if statements, in reality all standard streams must be // redirected otherwise it just won't work in SACS. if (startinfo.RedirectStandardInput) { _standardInput = new StreamWriter(_pipeServerToClient); _standardInput.AutoFlush = true; } if (startinfo.RedirectStandardOutput) { Encoding encoding = (startinfo.StandardOutputEncoding != null) ? startinfo.StandardOutputEncoding : Console.OutputEncoding; _standardOutput = new StreamReader(_pipeServerFromClient); } if (startinfo.RedirectStandardError) { Encoding encoding2 = (startinfo.StandardErrorEncoding != null) ? startinfo.StandardErrorEncoding : Console.OutputEncoding; _standardError = new StreamReader(_pipeServerErrorFromClient); } ArgumentObject["pipeIn"] = _pipeServerToClient.GetClientHandleAsString(); ArgumentObject["pipeOut"] = _pipeServerFromClient.GetClientHandleAsString(); ArgumentObject["pipeErr"] = _pipeServerErrorFromClient.GetClientHandleAsString(); processCreated = Win32NativeMethods.CreateProcessAsUser( token, path, string.Format("\"{0}\" {1}", startinfo.FileName.Replace("\"", "\"\""), JsonConvert.SerializeObject(this.ArgumentObject)), ref saProcess, ref saThread, true, 0, IntPtr.Zero, dir, ref si, out pi); if (!processCreated) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // For the last step, since we're not using the in-build methods to start the process, // we need to replace the now outdated process _process = Process.GetProcessById((int)pi.dwProcessId); } finally { _pipeServerToClient.DisposeLocalCopyOfClientHandle(); _pipeServerFromClient.DisposeLocalCopyOfClientHandle(); _pipeServerErrorFromClient.DisposeLocalCopyOfClientHandle(); if (pi.hProcess != IntPtr.Zero) { Win32NativeMethods.CloseHandle(pi.hProcess); } if (pi.hThread != IntPtr.Zero) { Win32NativeMethods.CloseHandle(pi.hThread); } } } }
/// <summary> /// Impersonates the specified user account. /// </summary> /// <param name="userName">Name of the user.</param> /// <param name="domainName">Name of the domain.</param> /// <param name="password">The password. <see cref="System.String"/></param> /// <param name="logonType">Type of the logon.</param> /// <param name="logonProvider">The logon provider. <see cref="Mit.Sharepoint.WebParts.EventLogQuery.Network.LogonProvider"/></param> private void Impersonate(string NetworkLocation, string userName, string domainName, string password, LogonType logonType, LogonProvider logonProvider) { try { UndoImpersonation(); /* * if (userName.Contains("\\") || userName.Contains("/")) * { * string[] tokens = userName.Split(new char[] { '\\', '/' }); * if (tokens.Length != 2) throw new Exception("Expected user name to contain at most one / or \\ character. User name: " + userName); * if (domainName.Trim().Length != 0) throw new Exception("Cannot specify a / or \\ in user name when domain is also given. User name: " + userName + " Domain: " + domainName); * domainName = tokens[0]; * userName = tokens[1]; * } */ IntPtr logonToken = IntPtr.Zero; IntPtr logonTokenDuplicate = IntPtr.Zero; try { // revert to the application pool identity, saving the identity of the current requestor _wic = WindowsIdentity.Impersonate(IntPtr.Zero); // do logon & impersonate if (Win32NativeMethods.LogonUser(userName, domainName, password, (int)logonType, (int)logonProvider, ref logonToken) != 0) { if (Win32NativeMethods.DuplicateToken(logonToken, (int)ImpersonationLevel.SecurityImpersonation, ref logonTokenDuplicate) != 0) { var wi = new WindowsIdentity(logonTokenDuplicate); wi.Impersonate(); // discard the returned identity context (which is the context of the application pool) } else { ThrowSpecificException(); } } else { ThrowSpecificException(); } } finally { if (logonToken != IntPtr.Zero) { Win32NativeMethods.CloseHandle(logonToken); } if (logonTokenDuplicate != IntPtr.Zero) { Win32NativeMethods.CloseHandle(logonTokenDuplicate); } } } catch (Exception ex) { throw new IOException("Unable to access path:\n" + NetworkLocation + "\nAs username: "******"\nOn domain: " + domainName + "\nError: " + ex.ToString()); } }
/// <summary> /// Impersonates the specified user account. /// </summary> /// <param name="userName">Name of the user.</param> /// <param name="domainName">Name of the domain.</param> /// <param name="password">The password. <see cref="String"/></param> /// <param name="logonType">Type of the logon.</param> /// <param name="logonProvider">The logon provider.</param> /// /// <param name="impersonationAction">A callback to perform during the impersonation initialization.</param> public virtual void Impersonate(string userName, string domainName, SecureString password, LogonType logonType, LogonProvider logonProvider, Action <IntPtr> impersonationAction = null) { UndoImpersonation(); IntPtr logonToken = IntPtr.Zero; IntPtr logonTokenDuplicate = IntPtr.Zero; IntPtr passwordPtr = new IntPtr(); passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password); bool logonValue = false; try { // revert to the application pool identity, saving the identity of the current requestor this._wic = WindowsIdentity.Impersonate(IntPtr.Zero); // do logon & impersonate logonValue = Win32NativeMethods.LogonUser( userName, domainName, passwordPtr, (int)logonType, (int)logonProvider, ref logonToken); if (logonValue) { Win32NativeMethods.SECURITY_ATTRIBUTES sa = new Win32NativeMethods.SECURITY_ATTRIBUTES(); sa.nLength = (uint)Marshal.SizeOf(sa); if (Win32NativeMethods.DuplicateTokenEx( logonToken, Win32NativeMethods.TOKEN_ASSIGN_PRIMARY | Win32NativeMethods.TOKEN_DUPLICATE | Win32NativeMethods.TOKEN_QUERY, ref sa, (int)Win32NativeMethods.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, (int)Win32NativeMethods.TOKEN_TYPE.TokenPrimary, ref logonTokenDuplicate)) { // Looks like it is working without impersonating. To be revisited. ////var wi = new WindowsIdentity(logonTokenDuplicate); ////wi.Impersonate(); // discard the returned identity context (which is the context of the application) ////this.IsImpersonating = true; if (impersonationAction != null) { impersonationAction(logonTokenDuplicate); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } else { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr); if (logonToken != IntPtr.Zero) { Win32NativeMethods.CloseHandle(logonToken); } if (logonTokenDuplicate != IntPtr.Zero) { Win32NativeMethods.CloseHandle(logonTokenDuplicate); } } }