github.com/wallyworld/juju@v0.0.0-20161013125918-6cf1bc9d917a/cloudconfig/winuserdata.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Copyright 2016 Cloudbase Solutions SRL 3 // Licensed under the AGPLv3, see LICENCE file for details. 4 5 package cloudconfig 6 7 // Generated code - do not edit. 8 9 const addJujuUser = ` 10 function create-account ([string]$accountName, [string]$accountDescription, [string]$password) { 11 $hostname = hostname 12 $comp = [adsi]"WinNT://$hostname" 13 $user = $comp.Create("User", $accountName) 14 $user.SetPassword($password) 15 $user.SetInfo() 16 $user.description = $accountDescription 17 $user.SetInfo() 18 $User.UserFlags[0] = $User.UserFlags[0] -bor 0x10000 19 $user.SetInfo() 20 21 # This gets the Administrator group name that is localized on different windows versions. 22 # However the SID S-1-5-32-544 is the same on all versions. 23 $adminGroup = (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")).Translate([System.Security.Principal.NTAccount]).Value.Split("\")[1] 24 25 $objOU = [ADSI]"WinNT://$hostname/$adminGroup,group" 26 $objOU.add("WinNT://$hostname/$accountName") 27 } 28 29 $Source = @" 30 using System; 31 using System.Text; 32 using System.Runtime.InteropServices; 33 34 namespace PSCloudbase 35 { 36 public sealed class Win32CryptApi 37 { 38 public static long CRYPT_SILENT = 0x00000040; 39 public static long CRYPT_VERIFYCONTEXT = 0xF0000000; 40 public static int PROV_RSA_FULL = 1; 41 42 [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 43 [return : MarshalAs(UnmanagedType.Bool)] 44 public static extern bool CryptAcquireContext(ref IntPtr hProv, 45 StringBuilder pszContainer, // Don't use string, as Powershell replaces $null with an empty string 46 StringBuilder pszProvider, // Don't use string, as Powershell replaces $null with an empty string 47 uint dwProvType, 48 uint dwFlags); 49 50 [DllImport("Advapi32.dll", EntryPoint = "CryptReleaseContext", CharSet = CharSet.Unicode, SetLastError = true)] 51 public static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags); 52 53 [DllImport("advapi32.dll", SetLastError=true)] 54 public static extern bool CryptGenRandom(IntPtr hProv, uint dwLen, byte[] pbBuffer); 55 56 [DllImport("Kernel32.dll")] 57 public static extern uint GetLastError(); 58 } 59 } 60 "@ 61 62 Add-Type -TypeDefinition $Source -Language CSharp 63 64 function Get-RandomPassword 65 { 66 [CmdletBinding()] 67 param 68 ( 69 [parameter(Mandatory=$true)] 70 [int]$Length 71 ) 72 process 73 { 74 $hProvider = 0 75 try 76 { 77 if(![PSCloudbase.Win32CryptApi]::CryptAcquireContext([ref]$hProvider, $null, $null, 78 [PSCloudbase.Win32CryptApi]::PROV_RSA_FULL, 79 ([PSCloudbase.Win32CryptApi]::CRYPT_VERIFYCONTEXT -bor 80 [PSCloudbase.Win32CryptApi]::CRYPT_SILENT))) 81 { 82 throw "CryptAcquireContext failed with error: 0x" + "{0:X0}" -f [PSCloudbase.Win32CryptApi]::GetLastError() 83 } 84 85 $buffer = New-Object byte[] $Length 86 if(![PSCloudbase.Win32CryptApi]::CryptGenRandom($hProvider, $Length, $buffer)) 87 { 88 throw "CryptGenRandom failed with error: 0x" + "{0:X0}" -f [PSCloudbase.Win32CryptApi]::GetLastError() 89 } 90 91 $buffer | ForEach-Object { $password += "{0:X0}" -f $_ } 92 return $password 93 } 94 finally 95 { 96 if($hProvider) 97 { 98 $retVal = [PSCloudbase.Win32CryptApi]::CryptReleaseContext($hProvider, 0) 99 } 100 } 101 } 102 } 103 104 $SourcePolicy = @" 105 /* 106 Original sources available at: https://bitbucket.org/splatteredbits/carbon 107 */ 108 109 using System; 110 using System.Collections.Generic; 111 using System.ComponentModel; 112 using System.Runtime.InteropServices; 113 using System.Security.Principal; 114 using System.Text; 115 116 namespace PSCarbon 117 { 118 public sealed class Lsa 119 { 120 // ReSharper disable InconsistentNaming 121 [StructLayout(LayoutKind.Sequential)] 122 internal struct LSA_UNICODE_STRING 123 { 124 internal LSA_UNICODE_STRING(string inputString) 125 { 126 if (inputString == null) 127 { 128 Buffer = IntPtr.Zero; 129 Length = 0; 130 MaximumLength = 0; 131 } 132 else 133 { 134 Buffer = Marshal.StringToHGlobalAuto(inputString); 135 Length = (ushort)(inputString.Length * UnicodeEncoding.CharSize); 136 MaximumLength = (ushort)((inputString.Length + 1) * UnicodeEncoding.CharSize); 137 } 138 } 139 140 internal ushort Length; 141 internal ushort MaximumLength; 142 internal IntPtr Buffer; 143 } 144 145 [StructLayout(LayoutKind.Sequential)] 146 internal struct LSA_OBJECT_ATTRIBUTES 147 { 148 internal uint Length; 149 internal IntPtr RootDirectory; 150 internal LSA_UNICODE_STRING ObjectName; 151 internal uint Attributes; 152 internal IntPtr SecurityDescriptor; 153 internal IntPtr SecurityQualityOfService; 154 } 155 156 [StructLayout(LayoutKind.Sequential)] 157 public struct LUID 158 { 159 public uint LowPart; 160 public int HighPart; 161 } 162 163 // ReSharper disable UnusedMember.Local 164 private const uint POLICY_VIEW_LOCAL_INFORMATION = 0x00000001; 165 private const uint POLICY_VIEW_AUDIT_INFORMATION = 0x00000002; 166 private const uint POLICY_GET_PRIVATE_INFORMATION = 0x00000004; 167 private const uint POLICY_TRUST_ADMIN = 0x00000008; 168 private const uint POLICY_CREATE_ACCOUNT = 0x00000010; 169 private const uint POLICY_CREATE_SECRET = 0x00000014; 170 private const uint POLICY_CREATE_PRIVILEGE = 0x00000040; 171 private const uint POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080; 172 private const uint POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100; 173 private const uint POLICY_AUDIT_LOG_ADMIN = 0x00000200; 174 private const uint POLICY_SERVER_ADMIN = 0x00000400; 175 private const uint POLICY_LOOKUP_NAMES = 0x00000800; 176 private const uint POLICY_NOTIFICATION = 0x00001000; 177 // ReSharper restore UnusedMember.Local 178 179 [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 180 public static extern bool LookupPrivilegeValue( 181 [MarshalAs(UnmanagedType.LPTStr)] string lpSystemName, 182 [MarshalAs(UnmanagedType.LPTStr)] string lpName, 183 out LUID lpLuid); 184 185 [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] 186 private static extern uint LsaAddAccountRights( 187 IntPtr PolicyHandle, 188 IntPtr AccountSid, 189 LSA_UNICODE_STRING[] UserRights, 190 uint CountOfRights); 191 192 [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = false)] 193 private static extern uint LsaClose(IntPtr ObjectHandle); 194 195 [DllImport("advapi32.dll", SetLastError = true)] 196 private static extern uint LsaEnumerateAccountRights(IntPtr PolicyHandle, 197 IntPtr AccountSid, 198 out IntPtr UserRights, 199 out uint CountOfRights 200 ); 201 202 [DllImport("advapi32.dll", SetLastError = true)] 203 private static extern uint LsaFreeMemory(IntPtr pBuffer); 204 205 [DllImport("advapi32.dll")] 206 private static extern int LsaNtStatusToWinError(long status); 207 208 [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] 209 private static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, uint DesiredAccess, out IntPtr PolicyHandle ); 210 211 [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] 212 static extern uint LsaRemoveAccountRights( 213 IntPtr PolicyHandle, 214 IntPtr AccountSid, 215 [MarshalAs(UnmanagedType.U1)] 216 bool AllRights, 217 LSA_UNICODE_STRING[] UserRights, 218 uint CountOfRights); 219 // ReSharper restore InconsistentNaming 220 221 private static IntPtr GetIdentitySid(string identity) 222 { 223 SecurityIdentifier sid = 224 new NTAccount(identity).Translate(typeof (SecurityIdentifier)) as SecurityIdentifier; 225 if (sid == null) 226 { 227 throw new ArgumentException(string.Format("Account {0} not found.", identity)); 228 } 229 byte[] sidBytes = new byte[sid.BinaryLength]; 230 sid.GetBinaryForm(sidBytes, 0); 231 System.IntPtr sidPtr = Marshal.AllocHGlobal(sidBytes.Length); 232 Marshal.Copy(sidBytes, 0, sidPtr, sidBytes.Length); 233 return sidPtr; 234 } 235 236 private static IntPtr GetLsaPolicyHandle() 237 { 238 string computerName = Environment.MachineName; 239 IntPtr hPolicy; 240 LSA_OBJECT_ATTRIBUTES objectAttributes = new LSA_OBJECT_ATTRIBUTES(); 241 objectAttributes.Length = 0; 242 objectAttributes.RootDirectory = IntPtr.Zero; 243 objectAttributes.Attributes = 0; 244 objectAttributes.SecurityDescriptor = IntPtr.Zero; 245 objectAttributes.SecurityQualityOfService = IntPtr.Zero; 246 247 const uint ACCESS_MASK = POLICY_CREATE_SECRET | POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION; 248 LSA_UNICODE_STRING machineNameLsa = new LSA_UNICODE_STRING(computerName); 249 uint result = LsaOpenPolicy(ref machineNameLsa, ref objectAttributes, ACCESS_MASK, out hPolicy); 250 HandleLsaResult(result); 251 return hPolicy; 252 } 253 254 public static string[] GetPrivileges(string identity) 255 { 256 IntPtr sidPtr = GetIdentitySid(identity); 257 IntPtr hPolicy = GetLsaPolicyHandle(); 258 IntPtr rightsPtr = IntPtr.Zero; 259 260 try 261 { 262 263 List<string> privileges = new List<string>(); 264 265 uint rightsCount; 266 uint result = LsaEnumerateAccountRights(hPolicy, sidPtr, out rightsPtr, out rightsCount); 267 int win32ErrorCode = LsaNtStatusToWinError(result); 268 // the user has no privileges 269 if( win32ErrorCode == STATUS_OBJECT_NAME_NOT_FOUND ) 270 { 271 return new string[0]; 272 } 273 HandleLsaResult(result); 274 275 LSA_UNICODE_STRING myLsaus = new LSA_UNICODE_STRING(); 276 for (ulong i = 0; i < rightsCount; i++) 277 { 278 IntPtr itemAddr = new IntPtr(rightsPtr.ToInt64() + (long) (i*(ulong) Marshal.SizeOf(myLsaus))); 279 myLsaus = (LSA_UNICODE_STRING) Marshal.PtrToStructure(itemAddr, myLsaus.GetType()); 280 char[] cvt = new char[myLsaus.Length/UnicodeEncoding.CharSize]; 281 Marshal.Copy(myLsaus.Buffer, cvt, 0, myLsaus.Length/UnicodeEncoding.CharSize); 282 string thisRight = new string(cvt); 283 privileges.Add(thisRight); 284 } 285 return privileges.ToArray(); 286 } 287 finally 288 { 289 Marshal.FreeHGlobal(sidPtr); 290 uint result = LsaClose(hPolicy); 291 HandleLsaResult(result); 292 result = LsaFreeMemory(rightsPtr); 293 HandleLsaResult(result); 294 } 295 } 296 297 public static void GrantPrivileges(string identity, string[] privileges) 298 { 299 IntPtr sidPtr = GetIdentitySid(identity); 300 IntPtr hPolicy = GetLsaPolicyHandle(); 301 302 try 303 { 304 LSA_UNICODE_STRING[] lsaPrivileges = StringsToLsaStrings(privileges); 305 uint result = LsaAddAccountRights(hPolicy, sidPtr, lsaPrivileges, (uint)lsaPrivileges.Length); 306 HandleLsaResult(result); 307 } 308 finally 309 { 310 Marshal.FreeHGlobal(sidPtr); 311 uint result = LsaClose(hPolicy); 312 HandleLsaResult(result); 313 } 314 } 315 316 const int STATUS_SUCCESS = 0x0; 317 const int STATUS_OBJECT_NAME_NOT_FOUND = 0x00000002; 318 const int STATUS_ACCESS_DENIED = 0x00000005; 319 const int STATUS_INVALID_HANDLE = 0x00000006; 320 const int STATUS_UNSUCCESSFUL = 0x0000001F; 321 const int STATUS_INVALID_PARAMETER = 0x00000057; 322 const int STATUS_NO_SUCH_PRIVILEGE = 0x00000521; 323 const int STATUS_INVALID_SERVER_STATE = 0x00000548; 324 const int STATUS_INTERNAL_DB_ERROR = 0x00000567; 325 const int STATUS_INSUFFICIENT_RESOURCES = 0x000005AA; 326 327 private static Dictionary<int, string> ErrorMessages = new Dictionary<int, string>(); 328 public Lsa () { 329 ErrorMessages.Add(STATUS_ACCESS_DENIED, "Access denied. Caller does not have the appropriate access to complete the operation."); 330 ErrorMessages.Add(STATUS_INVALID_HANDLE, "Invalid handle. Indicates an object or RPC handle is not valid in the context used."); 331 ErrorMessages.Add(STATUS_UNSUCCESSFUL, "Unsuccessful. Generic failure, such as RPC connection failure."); 332 ErrorMessages.Add(STATUS_INVALID_PARAMETER, "Invalid parameter. One of the parameters is not valid."); 333 ErrorMessages.Add(STATUS_NO_SUCH_PRIVILEGE, "No such privilege. Indicates a specified privilege does not exist."); 334 ErrorMessages.Add(STATUS_INVALID_SERVER_STATE, "Invalid server state. Indicates the LSA server is currently disabled."); 335 ErrorMessages.Add(STATUS_INTERNAL_DB_ERROR, "Internal database error. The LSA database contains an internal inconsistency."); 336 ErrorMessages.Add(STATUS_INSUFFICIENT_RESOURCES, "Insufficient resources. There are not enough system resources (such as memory to allocate buffers) to complete the call."); 337 ErrorMessages.Add(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."); 338 } 339 340 private static void HandleLsaResult(uint returnCode) 341 { 342 int win32ErrorCode = LsaNtStatusToWinError(returnCode); 343 344 if( win32ErrorCode == STATUS_SUCCESS) 345 return; 346 347 if( ErrorMessages.ContainsKey(win32ErrorCode) ) 348 { 349 throw new Win32Exception(win32ErrorCode, ErrorMessages[win32ErrorCode]); 350 } 351 352 throw new Win32Exception(win32ErrorCode); 353 } 354 355 public static void RevokePrivileges(string identity, string[] privileges) 356 { 357 IntPtr sidPtr = GetIdentitySid(identity); 358 IntPtr hPolicy = GetLsaPolicyHandle(); 359 360 try 361 { 362 string[] currentPrivileges = GetPrivileges(identity); 363 if (currentPrivileges.Length == 0) 364 { 365 return; 366 } 367 LSA_UNICODE_STRING[] lsaPrivileges = StringsToLsaStrings(privileges); 368 uint result = LsaRemoveAccountRights(hPolicy, sidPtr, false, lsaPrivileges, (uint)lsaPrivileges.Length); 369 HandleLsaResult(result); 370 } 371 finally 372 { 373 Marshal.FreeHGlobal(sidPtr); 374 uint result = LsaClose(hPolicy); 375 HandleLsaResult(result); 376 } 377 378 } 379 380 private static LSA_UNICODE_STRING[] StringsToLsaStrings(string[] privileges) 381 { 382 LSA_UNICODE_STRING[] lsaPrivileges = new LSA_UNICODE_STRING[privileges.Length]; 383 for (int idx = 0; idx < privileges.Length; ++idx) 384 { 385 lsaPrivileges[idx] = new LSA_UNICODE_STRING(privileges[idx]); 386 } 387 return lsaPrivileges; 388 } 389 } 390 } 391 "@ 392 393 Add-Type -TypeDefinition $SourcePolicy -Language CSharp 394 395 function SetAssignPrimaryTokenPrivilege($UserName) 396 { 397 $privilege = "SeAssignPrimaryTokenPrivilege" 398 if (!([PSCarbon.Lsa]::GetPrivileges($UserName) -contains $privilege)) 399 { 400 [PSCarbon.Lsa]::GrantPrivileges($UserName, $privilege) 401 } 402 } 403 404 function SetUserLogonAsServiceRights($UserName) 405 { 406 $privilege = "SeServiceLogonRight" 407 if (!([PSCarbon.Lsa]::GetPrivileges($UserName) -Contains $privilege)) 408 { 409 [PSCarbon.Lsa]::GrantPrivileges($UserName, $privilege) 410 } 411 } 412 413 $juju_passwd = Get-RandomPassword 20 414 $juju_passwd += "^" 415 create-account jujud "Juju Admin user" $juju_passwd 416 $hostname = hostname 417 $juju_user = "$hostname\jujud" 418 419 SetUserLogonAsServiceRights $juju_user 420 SetAssignPrimaryTokenPrivilege $juju_user 421 422 $path = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" 423 if(!(Test-Path $path)){ 424 New-Item -Path $path -force 425 } 426 New-ItemProperty $path -Name "jujud" -Value 0 -PropertyType "DWord" 427 428 $secpasswd = ConvertTo-SecureString $juju_passwd -AsPlainText -Force 429 $jujuCreds = New-Object System.Management.Automation.PSCredential ($juju_user, $secpasswd) 430 ` 431 const windowsPowershellHelpers = ` 432 433 $ErrorActionPreference = "Stop" 434 435 function ExecRetry($command, $retryInterval = 15) 436 { 437 $currErrorActionPreference = $ErrorActionPreference 438 $ErrorActionPreference = "Continue" 439 440 while ($true) 441 { 442 try 443 { 444 & $command 445 break 446 } 447 catch [System.Exception] 448 { 449 Write-Error $_.Exception 450 Start-Sleep $retryInterval 451 } 452 } 453 454 $ErrorActionPreference = $currErrorActionPreference 455 } 456 457 # TryExecAll attempts all of the commands in the supplied array until 458 # one can be executed without throwing an exception. If none of the 459 # commands succeeds, an exception will be raised. 460 function TryExecAll($commands) 461 { 462 $currErrorActionPreference = $ErrorActionPreference 463 $ErrorActionPreference = "Continue" 464 465 foreach ($command in $commands) 466 { 467 try 468 { 469 & $command 470 $ErrorActionPreference = $currErrorActionPreference 471 return 472 } 473 catch [System.Exception] 474 { 475 Write-Error $_.Exception 476 } 477 } 478 479 $ErrorActionPreference = $currErrorActionPreference 480 throw "All commands failed" 481 } 482 483 Function GUnZip-File{ 484 Param( 485 $infile, 486 $outdir 487 ) 488 489 $input = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) 490 $tempFile = "$env:TEMP\jujud.tar" 491 $tempOut = New-Object System.IO.FileStream $tempFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None) 492 $gzipStream = New-Object System.IO.Compression.GzipStream $input, ([IO.Compression.CompressionMode]::Decompress) 493 494 $buffer = New-Object byte[](1024) 495 while($true) { 496 $read = $gzipstream.Read($buffer, 0, 1024) 497 if ($read -le 0){break} 498 $tempOut.Write($buffer, 0, $read) 499 } 500 $gzipStream.Close() 501 $tempOut.Close() 502 $input.Close() 503 504 $in = New-Object System.IO.FileStream $tempFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) 505 Untar-File $in $outdir 506 $in.Close() 507 rm $tempFile 508 } 509 510 $HEADERSIZE = 512 511 512 Function Untar-File { 513 Param( 514 $inStream, 515 $outdir 516 ) 517 $DirectoryEntryType = 0x35 518 $headerBytes = New-Object byte[]($HEADERSIZE) 519 520 # $headerBytes is written inside, function returns whether we've reached the end 521 while(GetHeaderBytes $inStream $headerBytes) { 522 $fileName, $entryType, $sizeInBytes = GetFileInfoFromHeader $headerBytes 523 524 $totalPath = Join-Path $outDir $fileName 525 if ($entryType -eq $DirectoryEntryType) { 526 [System.IO.Directory]::CreateDirectory($totalPath) 527 continue; 528 } 529 530 $fName = [System.IO.Path]::GetFileName($totalPath) 531 $dirName = [System.IO.Path]::GetDirectoryName($totalPath) 532 [System.IO.Directory]::CreateDirectory($dirName) 533 $file = [System.IO.File]::Create($totalPath) 534 WriteTarEntryToFile $inStream $file $sizeInBytes 535 $file.Close() 536 } 537 } 538 539 Function WriteTarEntryToFile { 540 Param( 541 $inStream, 542 $outFile, 543 $sizeInBytes 544 ) 545 $moveToAlign512 = 0 546 $toRead = 0 547 $buf = New-Object byte[](512) 548 549 $remainingBytesInFile = $sizeInBytes 550 while ($remainingBytesInFile -ne 0) { 551 if ($remainingBytesInFile - 512 -lt 0) { 552 $moveToAlign512 = 512 - $remainingBytesInFile 553 $toRead = $remainingBytesInFile 554 } else { 555 $toRead = 512 556 } 557 558 $bytesRead = 0 559 $bytesRemainingToRead = $toRead 560 while ($bytesRead -lt $toRead -and $bytesRemainingToRead -gt 0) { 561 $bytesRead = $inStream.Read($buf, $toRead - $bytesRemainingToRead, $bytesRemainingToRead) 562 $bytesRemainingToRead = $bytesRemainingToRead - $bytesRead 563 $remainingBytesInFile = $remainingBytesInFile - $bytesRead 564 $outFile.Write($buf, 0, $bytesRead) 565 } 566 567 if ($moveToAlign512 -ne 0) { 568 $inStream.Seek($moveToAlign512, [System.IO.SeekOrigin]::Current) 569 } 570 } 571 } 572 573 Function GetHeaderBytes { 574 Param($inStream, $headerBytes) 575 576 $headerRead = 0 577 $bytesRemaining = $HEADERSIZE 578 while ($bytesRemaining -gt 0) { 579 $headerRead = $inStream.Read($headerBytes, $HEADERSIZE - $bytesRemaining, $bytesRemaining) 580 $bytesRemaining -= $headerRead 581 if ($headerRead -le 0 -and $bytesRemaining -gt 0) { 582 throw "Error reading tar header. Header size invalid" 583 } 584 } 585 586 # Proper end of archive is 2 empty headers 587 if (IsEmptyByteArray $headerBytes) { 588 $bytesRemaining = $HEADERSIZE 589 while ($bytesRemaining -gt 0) { 590 $headerRead = $inStream.Read($headerBytes, $HEADERSIZE - $bytesRemaining, $bytesRemaining) 591 $bytesRemaining -= $headerRead 592 if ($headerRead -le 0 -and $bytesRemaining -gt 0) { 593 throw "Broken end archive" 594 } 595 } 596 if ($bytesRemaining -eq 0 -and (IsEmptyByteArray($headerBytes))) { 597 return $false 598 } 599 throw "Error occurred: expected end of archive" 600 } 601 602 return $true 603 } 604 605 Function GetFileInfoFromHeader { 606 Param($headerBytes) 607 608 $FileName = [System.Text.Encoding]::UTF8.GetString($headerBytes, 0, 100); 609 $EntryType = $headerBytes[156]; 610 $SizeInBytes = [Convert]::ToInt64([System.Text.Encoding]::ASCII.GetString($headerBytes, 124, 11).Trim(), 8); 611 Return $FileName.replace("` + "`" + `0", [String].Empty), $EntryType, $SizeInBytes 612 } 613 614 Function IsEmptyByteArray { 615 Param ($bytes) 616 foreach($b in $bytes) { 617 if ($b -ne 0) { 618 return $false 619 } 620 } 621 return $true 622 } 623 624 Function Get-FileSHA256{ 625 Param( 626 $FilePath 627 ) 628 try { 629 $hash = [Security.Cryptography.HashAlgorithm]::Create( "SHA256" ) 630 $stream = ([IO.StreamReader]$FilePath).BaseStream 631 $res = -join ($hash.ComputeHash($stream) | ForEach { "{0:x2}" -f $_ }) 632 $stream.Close() 633 return $res 634 } catch [System.Management.Automation.RuntimeException] { 635 return (Get-FileHash -Path $FilePath).Hash 636 } 637 } 638 639 Function Invoke-FastWebRequest { 640 Param( 641 $URI, 642 $OutFile 643 ) 644 645 if(!([System.Management.Automation.PSTypeName]'System.Net.Http.HttpClient').Type) 646 { 647 $assembly = [System.Reflection.Assembly]::LoadWithPartialName("System.Net.Http") 648 } 649 650 $client = new-object System.Net.Http.HttpClient 651 652 $task = $client.GetStreamAsync($URI) 653 $response = $task.Result 654 $outStream = New-Object IO.FileStream $OutFile, Create, Write, None 655 656 try { 657 $totRead = 0 658 $buffer = New-Object Byte[] 1MB 659 while (($read = $response.Read($buffer, 0, $buffer.Length)) -gt 0) { 660 $totRead += $read 661 $outStream.Write($buffer, 0, $read); 662 } 663 } 664 finally { 665 $outStream.Close() 666 } 667 } 668 669 `