github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/cloudconfig/powershell_helpers.go (about) 1 // Copyright 2014, 2015 Canonical Ltd. 2 // Copyright 2014, 2015 Cloudbase Solutions 3 // Copyright 2012 Aaron Jensen 4 // 5 // Licensed under the AGPLv3, see LICENCE file for details. 6 // 7 // This file borrowed some code from https://bitbucket.org/splatteredbits/carbon 8 // (see Source/Security/Privilege.cs). This external source is licensed under 9 // Apache-2.0 license which is compatible with AGPLv3 license. Because it's 10 // compatible we can and have licensed this derived work under AGPLv3. The original 11 // Apache-2.0 license for the external source can be found inside Apache-License.txt. 12 // Copyright statement of the external source: Copyright 2012 Aaron Jensen 13 14 package cloudconfig 15 16 var winPowershellHelperFunctions = ` 17 18 $ErrorActionPreference = "Stop" 19 20 function ExecRetry($command, $maxRetryCount = 10, $retryInterval=2) 21 { 22 $currErrorActionPreference = $ErrorActionPreference 23 $ErrorActionPreference = "Continue" 24 25 $retryCount = 0 26 while ($true) 27 { 28 try 29 { 30 & $command 31 break 32 } 33 catch [System.Exception] 34 { 35 $retryCount++ 36 if ($retryCount -ge $maxRetryCount) 37 { 38 $ErrorActionPreference = $currErrorActionPreference 39 throw 40 } 41 else 42 { 43 Write-Error $_.Exception 44 Start-Sleep $retryInterval 45 } 46 } 47 } 48 49 $ErrorActionPreference = $currErrorActionPreference 50 } 51 52 function create-account ([string]$accountName, [string]$accountDescription, [string]$password) { 53 $hostname = hostname 54 $comp = [adsi]"WinNT://$hostname" 55 $user = $comp.Create("User", $accountName) 56 $user.SetPassword($password) 57 $user.SetInfo() 58 $user.description = $accountDescription 59 $user.SetInfo() 60 $User.UserFlags[0] = $User.UserFlags[0] -bor 0x10000 61 $user.SetInfo() 62 63 $objOU = [ADSI]"WinNT://$hostname/Administrators,group" 64 $objOU.add("WinNT://$hostname/$accountName") 65 } 66 67 $Source = @" 68 using System; 69 using System.Text; 70 using System.Runtime.InteropServices; 71 72 namespace PSCloudbase 73 { 74 public sealed class Win32CryptApi 75 { 76 public static long CRYPT_SILENT = 0x00000040; 77 public static long CRYPT_VERIFYCONTEXT = 0xF0000000; 78 public static int PROV_RSA_FULL = 1; 79 80 [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 81 [return : MarshalAs(UnmanagedType.Bool)] 82 public static extern bool CryptAcquireContext(ref IntPtr hProv, 83 StringBuilder pszContainer, // Don't use string, as Powershell replaces $null with an empty string 84 StringBuilder pszProvider, // Don't use string, as Powershell replaces $null with an empty string 85 uint dwProvType, 86 uint dwFlags); 87 88 [DllImport("Advapi32.dll", EntryPoint = "CryptReleaseContext", CharSet = CharSet.Unicode, SetLastError = true)] 89 public static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags); 90 91 [DllImport("advapi32.dll", SetLastError=true)] 92 public static extern bool CryptGenRandom(IntPtr hProv, uint dwLen, byte[] pbBuffer); 93 94 [DllImport("Kernel32.dll")] 95 public static extern uint GetLastError(); 96 } 97 } 98 "@ 99 100 Add-Type -TypeDefinition $Source -Language CSharp 101 102 function Get-RandomPassword 103 { 104 [CmdletBinding()] 105 param 106 ( 107 [parameter(Mandatory=$true)] 108 [int]$Length 109 ) 110 process 111 { 112 $hProvider = 0 113 try 114 { 115 if(![PSCloudbase.Win32CryptApi]::CryptAcquireContext([ref]$hProvider, $null, $null, 116 [PSCloudbase.Win32CryptApi]::PROV_RSA_FULL, 117 ([PSCloudbase.Win32CryptApi]::CRYPT_VERIFYCONTEXT -bor 118 [PSCloudbase.Win32CryptApi]::CRYPT_SILENT))) 119 { 120 throw "CryptAcquireContext failed with error: 0x" + "{0:X0}" -f [PSCloudbase.Win32CryptApi]::GetLastError() 121 } 122 123 $buffer = New-Object byte[] $Length 124 if(![PSCloudbase.Win32CryptApi]::CryptGenRandom($hProvider, $Length, $buffer)) 125 { 126 throw "CryptGenRandom failed with error: 0x" + "{0:X0}" -f [PSCloudbase.Win32CryptApi]::GetLastError() 127 } 128 129 $buffer | ForEach-Object { $password += "{0:X0}" -f $_ } 130 return $password 131 } 132 finally 133 { 134 if($hProvider) 135 { 136 $retVal = [PSCloudbase.Win32CryptApi]::CryptReleaseContext($hProvider, 0) 137 } 138 } 139 } 140 } 141 142 $SourcePolicy = @" 143 /* 144 Original sources available at: https://bitbucket.org/splatteredbits/carbon 145 */ 146 147 using System; 148 using System.Collections.Generic; 149 using System.ComponentModel; 150 using System.Runtime.InteropServices; 151 using System.Security.Principal; 152 using System.Text; 153 154 namespace PSCarbon 155 { 156 public sealed class Lsa 157 { 158 // ReSharper disable InconsistentNaming 159 [StructLayout(LayoutKind.Sequential)] 160 internal struct LSA_UNICODE_STRING 161 { 162 internal LSA_UNICODE_STRING(string inputString) 163 { 164 if (inputString == null) 165 { 166 Buffer = IntPtr.Zero; 167 Length = 0; 168 MaximumLength = 0; 169 } 170 else 171 { 172 Buffer = Marshal.StringToHGlobalAuto(inputString); 173 Length = (ushort)(inputString.Length * UnicodeEncoding.CharSize); 174 MaximumLength = (ushort)((inputString.Length + 1) * UnicodeEncoding.CharSize); 175 } 176 } 177 178 internal ushort Length; 179 internal ushort MaximumLength; 180 internal IntPtr Buffer; 181 } 182 183 [StructLayout(LayoutKind.Sequential)] 184 internal struct LSA_OBJECT_ATTRIBUTES 185 { 186 internal uint Length; 187 internal IntPtr RootDirectory; 188 internal LSA_UNICODE_STRING ObjectName; 189 internal uint Attributes; 190 internal IntPtr SecurityDescriptor; 191 internal IntPtr SecurityQualityOfService; 192 } 193 194 [StructLayout(LayoutKind.Sequential)] 195 public struct LUID 196 { 197 public uint LowPart; 198 public int HighPart; 199 } 200 201 // ReSharper disable UnusedMember.Local 202 private const uint POLICY_VIEW_LOCAL_INFORMATION = 0x00000001; 203 private const uint POLICY_VIEW_AUDIT_INFORMATION = 0x00000002; 204 private const uint POLICY_GET_PRIVATE_INFORMATION = 0x00000004; 205 private const uint POLICY_TRUST_ADMIN = 0x00000008; 206 private const uint POLICY_CREATE_ACCOUNT = 0x00000010; 207 private const uint POLICY_CREATE_SECRET = 0x00000014; 208 private const uint POLICY_CREATE_PRIVILEGE = 0x00000040; 209 private const uint POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080; 210 private const uint POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100; 211 private const uint POLICY_AUDIT_LOG_ADMIN = 0x00000200; 212 private const uint POLICY_SERVER_ADMIN = 0x00000400; 213 private const uint POLICY_LOOKUP_NAMES = 0x00000800; 214 private const uint POLICY_NOTIFICATION = 0x00001000; 215 // ReSharper restore UnusedMember.Local 216 217 [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 218 public static extern bool LookupPrivilegeValue( 219 [MarshalAs(UnmanagedType.LPTStr)] string lpSystemName, 220 [MarshalAs(UnmanagedType.LPTStr)] string lpName, 221 out LUID lpLuid); 222 223 [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] 224 private static extern uint LsaAddAccountRights( 225 IntPtr PolicyHandle, 226 IntPtr AccountSid, 227 LSA_UNICODE_STRING[] UserRights, 228 uint CountOfRights); 229 230 [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = false)] 231 private static extern uint LsaClose(IntPtr ObjectHandle); 232 233 [DllImport("advapi32.dll", SetLastError = true)] 234 private static extern uint LsaEnumerateAccountRights(IntPtr PolicyHandle, 235 IntPtr AccountSid, 236 out IntPtr UserRights, 237 out uint CountOfRights 238 ); 239 240 [DllImport("advapi32.dll", SetLastError = true)] 241 private static extern uint LsaFreeMemory(IntPtr pBuffer); 242 243 [DllImport("advapi32.dll")] 244 private static extern int LsaNtStatusToWinError(long status); 245 246 [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] 247 private static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, uint DesiredAccess, out IntPtr PolicyHandle ); 248 249 [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] 250 static extern uint LsaRemoveAccountRights( 251 IntPtr PolicyHandle, 252 IntPtr AccountSid, 253 [MarshalAs(UnmanagedType.U1)] 254 bool AllRights, 255 LSA_UNICODE_STRING[] UserRights, 256 uint CountOfRights); 257 // ReSharper restore InconsistentNaming 258 259 private static IntPtr GetIdentitySid(string identity) 260 { 261 var sid = 262 new NTAccount(identity).Translate(typeof (SecurityIdentifier)) as SecurityIdentifier; 263 if (sid == null) 264 { 265 throw new ArgumentException(string.Format("Account {0} not found.", identity)); 266 } 267 var sidBytes = new byte[sid.BinaryLength]; 268 sid.GetBinaryForm(sidBytes, 0); 269 var sidPtr = Marshal.AllocHGlobal(sidBytes.Length); 270 Marshal.Copy(sidBytes, 0, sidPtr, sidBytes.Length); 271 return sidPtr; 272 } 273 274 private static IntPtr GetLsaPolicyHandle() 275 { 276 var computerName = Environment.MachineName; 277 IntPtr hPolicy; 278 var objectAttributes = new LSA_OBJECT_ATTRIBUTES 279 { 280 Length = 0, 281 RootDirectory = IntPtr.Zero, 282 Attributes = 0, 283 SecurityDescriptor = IntPtr.Zero, 284 SecurityQualityOfService = IntPtr.Zero 285 }; 286 287 const uint ACCESS_MASK = POLICY_CREATE_SECRET | POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION; 288 var machineNameLsa = new LSA_UNICODE_STRING(computerName); 289 var result = LsaOpenPolicy(ref machineNameLsa, ref objectAttributes, ACCESS_MASK, out hPolicy); 290 HandleLsaResult(result); 291 return hPolicy; 292 } 293 294 public static string[] GetPrivileges(string identity) 295 { 296 var sidPtr = GetIdentitySid(identity); 297 var hPolicy = GetLsaPolicyHandle(); 298 var rightsPtr = IntPtr.Zero; 299 300 try 301 { 302 303 var privileges = new List<string>(); 304 305 uint rightsCount; 306 var result = LsaEnumerateAccountRights(hPolicy, sidPtr, out rightsPtr, out rightsCount); 307 var win32ErrorCode = LsaNtStatusToWinError(result); 308 // the user has no privileges 309 if( win32ErrorCode == STATUS_OBJECT_NAME_NOT_FOUND ) 310 { 311 return new string[0]; 312 } 313 HandleLsaResult(result); 314 315 var myLsaus = new LSA_UNICODE_STRING(); 316 for (ulong i = 0; i < rightsCount; i++) 317 { 318 var itemAddr = new IntPtr(rightsPtr.ToInt64() + (long) (i*(ulong) Marshal.SizeOf(myLsaus))); 319 myLsaus = (LSA_UNICODE_STRING) Marshal.PtrToStructure(itemAddr, myLsaus.GetType()); 320 var cvt = new char[myLsaus.Length/UnicodeEncoding.CharSize]; 321 Marshal.Copy(myLsaus.Buffer, cvt, 0, myLsaus.Length/UnicodeEncoding.CharSize); 322 var thisRight = new string(cvt); 323 privileges.Add(thisRight); 324 } 325 return privileges.ToArray(); 326 } 327 finally 328 { 329 Marshal.FreeHGlobal(sidPtr); 330 var result = LsaClose(hPolicy); 331 HandleLsaResult(result); 332 result = LsaFreeMemory(rightsPtr); 333 HandleLsaResult(result); 334 } 335 } 336 337 public static void GrantPrivileges(string identity, string[] privileges) 338 { 339 var sidPtr = GetIdentitySid(identity); 340 var hPolicy = GetLsaPolicyHandle(); 341 342 try 343 { 344 var lsaPrivileges = StringsToLsaStrings(privileges); 345 var result = LsaAddAccountRights(hPolicy, sidPtr, lsaPrivileges, (uint)lsaPrivileges.Length); 346 HandleLsaResult(result); 347 } 348 finally 349 { 350 Marshal.FreeHGlobal(sidPtr); 351 var result = LsaClose(hPolicy); 352 HandleLsaResult(result); 353 } 354 } 355 356 const int STATUS_SUCCESS = 0x0; 357 const int STATUS_OBJECT_NAME_NOT_FOUND = 0x00000002; 358 const int STATUS_ACCESS_DENIED = 0x00000005; 359 const int STATUS_INVALID_HANDLE = 0x00000006; 360 const int STATUS_UNSUCCESSFUL = 0x0000001F; 361 const int STATUS_INVALID_PARAMETER = 0x00000057; 362 const int STATUS_NO_SUCH_PRIVILEGE = 0x00000521; 363 const int STATUS_INVALID_SERVER_STATE = 0x00000548; 364 const int STATUS_INTERNAL_DB_ERROR = 0x00000567; 365 const int STATUS_INSUFFICIENT_RESOURCES = 0x000005AA; 366 367 private static readonly Dictionary<int, string> ErrorMessages = new Dictionary<int, string> 368 { 369 {STATUS_OBJECT_NAME_NOT_FOUND, "Object name not found. An object in the LSA policy database was not found. The object may have been specified either by SID or by name, depending on its type."}, 370 {STATUS_ACCESS_DENIED, "Access denied. Caller does not have the appropriate access to complete the operation."}, 371 {STATUS_INVALID_HANDLE, "Invalid handle. Indicates an object or RPC handle is not valid in the context used."}, 372 {STATUS_UNSUCCESSFUL, "Unsuccessful. Generic failure, such as RPC connection failure."}, 373 {STATUS_INVALID_PARAMETER, "Invalid parameter. One of the parameters is not valid."}, 374 {STATUS_NO_SUCH_PRIVILEGE, "No such privilege. Indicates a specified privilege does not exist."}, 375 {STATUS_INVALID_SERVER_STATE, "Invalid server state. Indicates the LSA server is currently disabled."}, 376 {STATUS_INTERNAL_DB_ERROR, "Internal database error. The LSA database contains an internal inconsistency."}, 377 {STATUS_INSUFFICIENT_RESOURCES, "Insufficient resources. There are not enough system resources (such as memory to allocate buffers) to complete the call."} 378 }; 379 380 private static void HandleLsaResult(uint returnCode) 381 { 382 var win32ErrorCode = LsaNtStatusToWinError(returnCode); 383 384 if( win32ErrorCode == STATUS_SUCCESS) 385 return; 386 387 if( ErrorMessages.ContainsKey(win32ErrorCode) ) 388 { 389 throw new Win32Exception(win32ErrorCode, ErrorMessages[win32ErrorCode]); 390 } 391 392 throw new Win32Exception(win32ErrorCode); 393 } 394 395 public static void RevokePrivileges(string identity, string[] privileges) 396 { 397 var sidPtr = GetIdentitySid(identity); 398 var hPolicy = GetLsaPolicyHandle(); 399 400 try 401 { 402 var currentPrivileges = GetPrivileges(identity); 403 if (currentPrivileges.Length == 0) 404 { 405 return; 406 } 407 var lsaPrivileges = StringsToLsaStrings(privileges); 408 var result = LsaRemoveAccountRights(hPolicy, sidPtr, false, lsaPrivileges, (uint)lsaPrivileges.Length); 409 HandleLsaResult(result); 410 } 411 finally 412 { 413 Marshal.FreeHGlobal(sidPtr); 414 var result = LsaClose(hPolicy); 415 HandleLsaResult(result); 416 } 417 418 } 419 420 private static LSA_UNICODE_STRING[] StringsToLsaStrings(string[] privileges) 421 { 422 var lsaPrivileges = new LSA_UNICODE_STRING[privileges.Length]; 423 for (var idx = 0; idx < privileges.Length; ++idx) 424 { 425 lsaPrivileges[idx] = new LSA_UNICODE_STRING(privileges[idx]); 426 } 427 return lsaPrivileges; 428 } 429 } 430 } 431 "@ 432 433 Add-Type -TypeDefinition $SourcePolicy -Language CSharp 434 435 $ServiceChangeErrors = @{} 436 $ServiceChangeErrors.Add(1, "Not Supported") 437 $ServiceChangeErrors.Add(2, "Access Denied") 438 $ServiceChangeErrors.Add(3, "Dependent Services Running") 439 $ServiceChangeErrors.Add(4, "Invalid Service Control") 440 $ServiceChangeErrors.Add(5, "Service Cannot Accept Control") 441 $ServiceChangeErrors.Add(6, "Service Not Active") 442 $ServiceChangeErrors.Add(7, "Service Request Timeout") 443 $ServiceChangeErrors.Add(8, "Unknown Failure") 444 $ServiceChangeErrors.Add(9, "Path Not Found") 445 $ServiceChangeErrors.Add(10, "Service Already Running") 446 $ServiceChangeErrors.Add(11, "Service Database Locked") 447 $ServiceChangeErrors.Add(12, "Service Dependency Deleted") 448 $ServiceChangeErrors.Add(13, "Service Dependency Failure") 449 $ServiceChangeErrors.Add(14, "Service Disabled") 450 $ServiceChangeErrors.Add(15, "Service Logon Failure") 451 $ServiceChangeErrors.Add(16, "Service Marked For Deletion") 452 $ServiceChangeErrors.Add(17, "Service No Thread") 453 $ServiceChangeErrors.Add(18, "Status Circular Dependency") 454 $ServiceChangeErrors.Add(19, "Status Duplicate Name") 455 $ServiceChangeErrors.Add(20, "Status Invalid Name") 456 $ServiceChangeErrors.Add(21, "Status Invalid Parameter") 457 $ServiceChangeErrors.Add(22, "Status Invalid Service Account") 458 $ServiceChangeErrors.Add(23, "Status Service Exists") 459 $ServiceChangeErrors.Add(24, "Service Already Paused") 460 461 462 function SetAssignPrimaryTokenPrivilege($UserName) 463 { 464 $privilege = "SeAssignPrimaryTokenPrivilege" 465 if (![PSCarbon.Lsa]::GetPrivileges($UserName).Contains($privilege)) 466 { 467 [PSCarbon.Lsa]::GrantPrivileges($UserName, $privilege) 468 } 469 } 470 471 function SetUserLogonAsServiceRights($UserName) 472 { 473 $privilege = "SeServiceLogonRight" 474 if (![PSCarbon.Lsa]::GetPrivileges($UserName).Contains($privilege)) 475 { 476 [PSCarbon.Lsa]::GrantPrivileges($UserName, $privilege) 477 } 478 } 479 480 $Source = @" 481 using System; 482 using System.Text; 483 using System.Runtime.InteropServices; 484 using System.Security.Principal; 485 using System.ComponentModel; 486 487 namespace PSCloudbase 488 { 489 public class ProcessManager 490 { 491 const int LOGON32_LOGON_SERVICE = 5; 492 const int LOGON32_PROVIDER_DEFAULT = 0; 493 const int TOKEN_ALL_ACCESS = 0x000f01ff; 494 const uint GENERIC_ALL_ACCESS = 0x10000000; 495 const uint INFINITE = 0xFFFFFFFF; 496 const uint PI_NOUI = 0x00000001; 497 const uint WAIT_FAILED = 0xFFFFFFFF; 498 499 enum SECURITY_IMPERSONATION_LEVEL 500 { 501 SecurityAnonymous, 502 SecurityIdentification, 503 SecurityImpersonation, 504 SecurityDelegation 505 } 506 507 enum TOKEN_TYPE 508 { 509 TokenPrimary = 1, 510 TokenImpersonation 511 } 512 513 [StructLayout(LayoutKind.Sequential)] 514 struct SECURITY_ATTRIBUTES 515 { 516 public int nLength; 517 public IntPtr lpSecurityDescriptor; 518 public int bInheritHandle; 519 } 520 521 [StructLayout(LayoutKind.Sequential)] 522 struct PROCESS_INFORMATION 523 { 524 public IntPtr hProcess; 525 public IntPtr hThread; 526 public int dwProcessId; 527 public int dwThreadId; 528 } 529 530 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 531 struct STARTUPINFO 532 { 533 public Int32 cb; 534 public string lpReserved; 535 public string lpDesktop; 536 public string lpTitle; 537 public Int32 dwX; 538 public Int32 dwY; 539 public Int32 dwXSize; 540 public Int32 dwYSize; 541 public Int32 dwXCountChars; 542 public Int32 dwYCountChars; 543 public Int32 dwFillAttribute; 544 public Int32 dwFlags; 545 public Int16 wShowWindow; 546 public Int16 cbReserved2; 547 public IntPtr lpReserved2; 548 public IntPtr hStdInput; 549 public IntPtr hStdOutput; 550 public IntPtr hStdError; 551 } 552 553 [StructLayout(LayoutKind.Sequential)] 554 struct PROFILEINFO { 555 public int dwSize; 556 public uint dwFlags; 557 [MarshalAs(UnmanagedType.LPTStr)] 558 public String lpUserName; 559 [MarshalAs(UnmanagedType.LPTStr)] 560 public String lpProfilePath; 561 [MarshalAs(UnmanagedType.LPTStr)] 562 public String lpDefaultPath; 563 [MarshalAs(UnmanagedType.LPTStr)] 564 public String lpServerName; 565 [MarshalAs(UnmanagedType.LPTStr)] 566 public String lpPolicyPath; 567 public IntPtr hProfile; 568 } 569 570 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 571 public struct USER_INFO_4 572 { 573 public string name; 574 public string password; 575 public int password_age; 576 public uint priv; 577 public string home_dir; 578 public string comment; 579 public uint flags; 580 public string script_path; 581 public uint auth_flags; 582 public string full_name; 583 public string usr_comment; 584 public string parms; 585 public string workstations; 586 public int last_logon; 587 public int last_logoff; 588 public int acct_expires; 589 public int max_storage; 590 public int units_per_week; 591 public IntPtr logon_hours; // This is a PBYTE 592 public int bad_pw_count; 593 public int num_logons; 594 public string logon_server; 595 public int country_code; 596 public int code_page; 597 public IntPtr user_sid; // This is a PSID 598 public int primary_group_id; 599 public string profile; 600 public string home_dir_drive; 601 public int password_expired; 602 } 603 604 [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 605 extern static bool DuplicateTokenEx( 606 IntPtr hExistingToken, 607 uint dwDesiredAccess, 608 ref SECURITY_ATTRIBUTES lpTokenAttributes, 609 SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, 610 TOKEN_TYPE TokenType, 611 out IntPtr phNewToken); 612 613 [DllImport("advapi32.dll", SetLastError=true)] 614 static extern bool LogonUser( 615 string lpszUsername, 616 string lpszDomain, 617 string lpszPassword, 618 int dwLogonType, 619 int dwLogonProvider, 620 out IntPtr phToken); 621 622 [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Auto)] 623 static extern bool CreateProcessAsUser( 624 IntPtr hToken, 625 string lpApplicationName, 626 string lpCommandLine, 627 ref SECURITY_ATTRIBUTES lpProcessAttributes, 628 ref SECURITY_ATTRIBUTES lpThreadAttributes, 629 bool bInheritHandles, 630 uint dwCreationFlags, 631 IntPtr lpEnvironment, 632 string lpCurrentDirectory, 633 ref STARTUPINFO lpStartupInfo, 634 out PROCESS_INFORMATION lpProcessInformation); 635 636 [DllImport("kernel32.dll", SetLastError=true)] 637 static extern UInt32 WaitForSingleObject(IntPtr hHandle, 638 UInt32 dwMilliseconds); 639 640 [DllImport("Kernel32.dll")] 641 static extern int GetLastError(); 642 643 [DllImport("Kernel32.dll")] 644 extern static int CloseHandle(IntPtr handle); 645 646 [DllImport("kernel32.dll", SetLastError = true)] 647 [return: MarshalAs(UnmanagedType.Bool)] 648 static extern bool GetExitCodeProcess(IntPtr hProcess, 649 out uint lpExitCode); 650 651 [DllImport("userenv.dll", SetLastError=true, CharSet=CharSet.Auto)] 652 [return: MarshalAs(UnmanagedType.Bool)] 653 static extern bool LoadUserProfile(IntPtr hToken, 654 ref PROFILEINFO lpProfileInfo); 655 656 [DllImport("userenv.dll", SetLastError=true, CharSet=CharSet.Auto)] 657 [return: MarshalAs(UnmanagedType.Bool)] 658 static extern bool UnloadUserProfile(IntPtr hToken, IntPtr hProfile); 659 660 [DllImport("Netapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)] 661 extern static int NetUserGetInfo( 662 [MarshalAs(UnmanagedType.LPWStr)] string ServerName, 663 [MarshalAs(UnmanagedType.LPWStr)] string UserName, 664 int level, out IntPtr BufPtr); 665 666 public static uint RunProcess(string userName, string password, 667 string domain, string cmd, 668 string arguments, 669 bool loadUserProfile = true) 670 { 671 bool retValue; 672 IntPtr phToken = IntPtr.Zero; 673 IntPtr phTokenDup = IntPtr.Zero; 674 PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION(); 675 PROFILEINFO pi = new PROFILEINFO(); 676 677 try 678 { 679 retValue = LogonUser(userName, domain, password, 680 LOGON32_LOGON_SERVICE, 681 LOGON32_PROVIDER_DEFAULT, 682 out phToken); 683 if(!retValue) 684 throw new Win32Exception(GetLastError()); 685 686 var sa = new SECURITY_ATTRIBUTES(); 687 sa.nLength = Marshal.SizeOf(sa); 688 689 retValue = DuplicateTokenEx( 690 phToken, GENERIC_ALL_ACCESS, ref sa, 691 SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, 692 TOKEN_TYPE.TokenPrimary, out phTokenDup); 693 if(!retValue) 694 throw new Win32Exception(GetLastError()); 695 696 STARTUPINFO sInfo = new STARTUPINFO(); 697 sInfo.lpDesktop = ""; 698 699 if(loadUserProfile) 700 { 701 IntPtr userInfoPtr = IntPtr.Zero; 702 int retValueNetUser = NetUserGetInfo(null, userName, 4, 703 out userInfoPtr); 704 if(retValueNetUser != 0) 705 throw new Win32Exception(retValueNetUser); 706 707 USER_INFO_4 userInfo = (USER_INFO_4)Marshal.PtrToStructure( 708 userInfoPtr, typeof(USER_INFO_4)); 709 710 pi.dwSize = Marshal.SizeOf(pi); 711 pi.dwFlags = PI_NOUI; 712 pi.lpUserName = userName; 713 pi.lpProfilePath = userInfo.profile; 714 715 retValue = LoadUserProfile(phTokenDup, ref pi); 716 if(!retValue) 717 throw new Win32Exception(GetLastError()); 718 } 719 720 retValue = CreateProcessAsUser(phTokenDup, cmd, arguments, 721 ref sa, ref sa, false, 0, 722 IntPtr.Zero, null, 723 ref sInfo, out pInfo); 724 if(!retValue) 725 throw new Win32Exception(GetLastError()); 726 727 if(WaitForSingleObject(pInfo.hProcess, INFINITE) == WAIT_FAILED) 728 throw new Win32Exception(GetLastError()); 729 730 uint exitCode; 731 retValue = GetExitCodeProcess(pInfo.hProcess, out exitCode); 732 if(!retValue) 733 throw new Win32Exception(GetLastError()); 734 735 return exitCode; 736 } 737 finally 738 { 739 if(pi.hProfile != IntPtr.Zero) 740 UnloadUserProfile(phTokenDup, pi.hProfile); 741 if(phToken != IntPtr.Zero) 742 CloseHandle(phToken); 743 if(phTokenDup != IntPtr.Zero) 744 CloseHandle(phTokenDup); 745 if(pInfo.hProcess != IntPtr.Zero) 746 CloseHandle(pInfo.hProcess); 747 } 748 } 749 } 750 } 751 "@ 752 753 Add-Type -TypeDefinition $Source -Language CSharp 754 755 function Start-ProcessAsUser 756 { 757 [CmdletBinding()] 758 param 759 ( 760 [parameter(Mandatory=$true, ValueFromPipeline=$true)] 761 [string]$Command, 762 763 [parameter()] 764 [string]$Arguments, 765 766 [parameter(Mandatory=$true)] 767 [PSCredential]$Credential, 768 769 [parameter()] 770 [bool]$LoadUserProfile = $true 771 ) 772 process 773 { 774 $nc = $Credential.GetNetworkCredential() 775 776 $domain = "." 777 if($nc.Domain) 778 { 779 $domain = $nc.Domain 780 } 781 782 [PSCloudbase.ProcessManager]::RunProcess($nc.UserName, $nc.Password, 783 $domain, $Command, 784 $Arguments, $LoadUserProfile) 785 } 786 } 787 788 $powershell = "$ENV:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" 789 $cmdExe = "$ENV:SystemRoot\System32\cmd.exe" 790 791 $juju_passwd = Get-RandomPassword 20 792 $juju_passwd += "^" 793 create-account jujud "Juju Admin user" $juju_passwd 794 $hostname = hostname 795 $juju_user = "$hostname\jujud" 796 797 SetUserLogonAsServiceRights $juju_user 798 SetAssignPrimaryTokenPrivilege $juju_user 799 800 New-ItemProperty "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" -Name "jujud" -Value 0 -PropertyType "DWord" 801 802 $secpasswd = ConvertTo-SecureString $juju_passwd -AsPlainText -Force 803 $jujuCreds = New-Object System.Management.Automation.PSCredential ($juju_user, $secpasswd) 804 805 ` 806 807 var winSetPasswdScript = ` 808 809 Set-Content "C:\juju\bin\save_pass.ps1" @" 810 Param ( 811 [Parameter(Mandatory=` + "`$true" + `)] 812 [string]` + "`$pass" + ` 813 ) 814 815 ` + "`$secpasswd" + ` = ConvertTo-SecureString ` + "`$pass" + ` -AsPlainText -Force 816 ` + "`$secpasswd" + ` | convertfrom-securestring | Add-Content C:\Juju\Jujud.pass 817 "@ 818 819 `