Skip to content

Commit ad0053c

Browse files
committed
Adds RunAsUser module
1 parent 0c3bd1f commit ad0053c

File tree

1 file changed

+231
-0
lines changed

1 file changed

+231
-0
lines changed

RunAsUser.ps1

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
<#
2+
Copyright 2014 Cloudbase Solutions Srl
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
#>
16+
17+
$Source = @"
18+
using System;
19+
using System.Text;
20+
using System.Runtime.InteropServices;
21+
using System.Security.Principal;
22+
using System.ComponentModel;
23+
24+
namespace PSCloudbase
25+
{
26+
public class ProcessManager
27+
{
28+
const int LOGON32_LOGON_SERVICE = 5;
29+
const int LOGON32_PROVIDER_DEFAULT = 0;
30+
31+
const uint GENERIC_ALL_ACCESS = 0x10000000;
32+
33+
const uint INFINITE = 0xFFFFFFFF;
34+
35+
enum SECURITY_IMPERSONATION_LEVEL
36+
{
37+
SecurityAnonymous,
38+
SecurityIdentification,
39+
SecurityImpersonation,
40+
SecurityDelegation
41+
}
42+
43+
enum TOKEN_TYPE
44+
{
45+
TokenPrimary = 1,
46+
TokenImpersonation
47+
}
48+
49+
[StructLayout(LayoutKind.Sequential)]
50+
struct SECURITY_ATTRIBUTES
51+
{
52+
public int nLength;
53+
public IntPtr lpSecurityDescriptor;
54+
public int bInheritHandle;
55+
}
56+
57+
[StructLayout(LayoutKind.Sequential)]
58+
struct PROCESS_INFORMATION
59+
{
60+
public IntPtr hProcess;
61+
public IntPtr hThread;
62+
public int dwProcessId;
63+
public int dwThreadId;
64+
}
65+
66+
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
67+
struct STARTUPINFO
68+
{
69+
public Int32 cb;
70+
public string lpReserved;
71+
public string lpDesktop;
72+
public string lpTitle;
73+
public Int32 dwX;
74+
public Int32 dwY;
75+
public Int32 dwXSize;
76+
public Int32 dwYSize;
77+
public Int32 dwXCountChars;
78+
public Int32 dwYCountChars;
79+
public Int32 dwFillAttribute;
80+
public Int32 dwFlags;
81+
public Int16 wShowWindow;
82+
public Int16 cbReserved2;
83+
public IntPtr lpReserved2;
84+
public IntPtr hStdInput;
85+
public IntPtr hStdOutput;
86+
public IntPtr hStdError;
87+
}
88+
89+
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
90+
extern static bool DuplicateTokenEx(
91+
IntPtr hExistingToken,
92+
uint dwDesiredAccess,
93+
ref SECURITY_ATTRIBUTES lpTokenAttributes,
94+
SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
95+
TOKEN_TYPE TokenType,
96+
out IntPtr phNewToken);
97+
98+
[DllImport("advapi32.dll", SetLastError=true)]
99+
static extern bool LogonUser(
100+
string lpszUsername,
101+
string lpszDomain,
102+
string lpszPassword,
103+
int dwLogonType,
104+
int dwLogonProvider,
105+
out IntPtr phToken);
106+
107+
[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)]
108+
static extern bool CreateProcessAsUser(
109+
IntPtr hToken,
110+
string lpApplicationName,
111+
string lpCommandLine,
112+
ref SECURITY_ATTRIBUTES lpProcessAttributes,
113+
ref SECURITY_ATTRIBUTES lpThreadAttributes,
114+
bool bInheritHandles,
115+
uint dwCreationFlags,
116+
IntPtr lpEnvironment,
117+
string lpCurrentDirectory,
118+
ref STARTUPINFO lpStartupInfo,
119+
out PROCESS_INFORMATION lpProcessInformation);
120+
121+
[DllImport("kernel32.dll", SetLastError=true)]
122+
static extern UInt32 WaitForSingleObject(IntPtr hHandle,
123+
UInt32 dwMilliseconds);
124+
125+
[DllImport("Kernel32.dll")]
126+
static extern int GetLastError();
127+
128+
[DllImport("Kernel32.dll")]
129+
extern static int CloseHandle(IntPtr handle);
130+
131+
[DllImport("kernel32.dll", SetLastError = true)]
132+
[return: MarshalAs(UnmanagedType.Bool)]
133+
static extern bool GetExitCodeProcess(IntPtr hProcess,
134+
out uint lpExitCode);
135+
136+
public static uint RunProcess(string userName, string password,
137+
string domain, string cmd,
138+
string arguments)
139+
{
140+
bool retValue;
141+
IntPtr phToken = IntPtr.Zero;
142+
IntPtr phTokenDup = IntPtr.Zero;
143+
PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
144+
145+
try
146+
{
147+
retValue = LogonUser(userName, domain, password,
148+
LOGON32_LOGON_SERVICE,
149+
LOGON32_PROVIDER_DEFAULT,
150+
out phToken);
151+
if(!retValue)
152+
throw new Win32Exception(GetLastError());
153+
154+
var sa = new SECURITY_ATTRIBUTES();
155+
sa.nLength = Marshal.SizeOf(sa);
156+
157+
retValue = DuplicateTokenEx(
158+
phToken, GENERIC_ALL_ACCESS, ref sa,
159+
SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
160+
TOKEN_TYPE.TokenPrimary, out phTokenDup);
161+
if(!retValue)
162+
throw new Win32Exception(GetLastError());
163+
164+
STARTUPINFO sInfo = new STARTUPINFO();
165+
sInfo.lpDesktop = "";
166+
167+
retValue = CreateProcessAsUser(phTokenDup, cmd, arguments,
168+
ref sa, ref sa, false, 0,
169+
IntPtr.Zero, null,
170+
ref sInfo, out pInfo);
171+
if(!retValue)
172+
throw new Win32Exception(GetLastError());
173+
174+
WaitForSingleObject(pInfo.hProcess, INFINITE);
175+
176+
var lastErr = GetLastError();
177+
if(lastErr != 0)
178+
throw new Win32Exception(GetLastError());
179+
180+
uint exitCode;
181+
retValue = GetExitCodeProcess(pInfo.hProcess, out exitCode);
182+
if(!retValue)
183+
throw new Win32Exception(GetLastError());
184+
185+
return exitCode;
186+
}
187+
finally
188+
{
189+
if(phToken != IntPtr.Zero)
190+
CloseHandle(phToken);
191+
if(phTokenDup != IntPtr.Zero)
192+
CloseHandle(phTokenDup);
193+
if(pInfo.hProcess != IntPtr.Zero)
194+
CloseHandle(pInfo.hProcess);
195+
}
196+
}
197+
}
198+
}
199+
"@
200+
201+
Add-Type -TypeDefinition $Source -Language CSharp
202+
203+
function Start-ProcessAsUser
204+
{
205+
[CmdletBinding()]
206+
param
207+
(
208+
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
209+
[string]$Command,
210+
211+
[parameter()]
212+
[string]$Arguments,
213+
214+
[parameter(Mandatory=$true)]
215+
[PSCredential]$Credential
216+
)
217+
process
218+
{
219+
$nc = $Credential.GetNetworkCredential()
220+
221+
$domain = "."
222+
if($nc.Domain)
223+
{
224+
$domain = $nc.Domain
225+
}
226+
227+
[PSCloudbase.ProcessManager]::RunProcess($nc.UserName, $nc.Password,
228+
$domain, $Command,
229+
$Arguments)
230+
}
231+
}

0 commit comments

Comments
 (0)