github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/cloudconfig/powershell_helpers.go (about) 1 // Copyright 2014, 2015 Canonical Ltd. 2 // Copyright 2014, 2015 Cloudbase Solutions 3 // Copyright 2012 Aaron Jensen 4 // Copyright (c) 2009, Vladimir Vasiltsov All rights reserved. 5 // 6 // Licensed under the AGPLv3, see LICENCE file for details. 7 // 8 // This file borrowed some code from https://bitbucket.org/splatteredbits/carbon 9 // (see Source/Security/Privilege.cs). This external source is licensed under 10 // Apache-2.0 license which is compatible with AGPLv3 license. Because it's 11 // compatible we can and have licensed this derived work under AGPLv3. The original 12 // Apache-2.0 license for the external source can be found inside Apache-License.txt. 13 // Copyright statement of the external source: Copyright 2012 Aaron Jensen 14 // 15 // This file borrowed some code from https://code.google.com/p/tar-cs/ which is 16 // This external source is licensed under BSD3 License which is compatible with 17 // AGPLv3 license. Because it's compatible we can have have licensed this 18 // derived work under AGPLv3. The original BSD3 license for the external source 19 // can be found inside BSD3-License.txt. 20 // Copyright statement of the external source: 21 // Copyright (c) 2009, Vladimir Vasiltsov All rights reserved. 22 23 package cloudconfig 24 25 var winPowershellHelperFunctions = ` 26 27 $ErrorActionPreference = "Stop" 28 29 function ExecRetry($command, $maxRetryCount = 10, $retryInterval=2) 30 { 31 $currErrorActionPreference = $ErrorActionPreference 32 $ErrorActionPreference = "Continue" 33 34 $retryCount = 0 35 while ($true) 36 { 37 try 38 { 39 & $command 40 break 41 } 42 catch [System.Exception] 43 { 44 $retryCount++ 45 if ($retryCount -ge $maxRetryCount) 46 { 47 $ErrorActionPreference = $currErrorActionPreference 48 throw 49 } 50 else 51 { 52 Write-Error $_.Exception 53 Start-Sleep $retryInterval 54 } 55 } 56 } 57 58 $ErrorActionPreference = $currErrorActionPreference 59 } 60 61 function create-account ([string]$accountName, [string]$accountDescription, [string]$password) { 62 $hostname = hostname 63 $comp = [adsi]"WinNT://$hostname" 64 $user = $comp.Create("User", $accountName) 65 $user.SetPassword($password) 66 $user.SetInfo() 67 $user.description = $accountDescription 68 $user.SetInfo() 69 $User.UserFlags[0] = $User.UserFlags[0] -bor 0x10000 70 $user.SetInfo() 71 72 # This gets the Administrator group name that is localized on different windows versions. 73 # However the SID S-1-5-32-544 is the same on all versions. 74 $adminGroup = (New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")).Translate([System.Security.Principal.NTAccount]).Value.Split("\")[1] 75 76 $objOU = [ADSI]"WinNT://$hostname/$adminGroup,group" 77 $objOU.add("WinNT://$hostname/$accountName") 78 } 79 80 $Source = @" 81 using System; 82 using System.Text; 83 using System.Runtime.InteropServices; 84 85 namespace PSCloudbase 86 { 87 public sealed class Win32CryptApi 88 { 89 public static long CRYPT_SILENT = 0x00000040; 90 public static long CRYPT_VERIFYCONTEXT = 0xF0000000; 91 public static int PROV_RSA_FULL = 1; 92 93 [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 94 [return : MarshalAs(UnmanagedType.Bool)] 95 public static extern bool CryptAcquireContext(ref IntPtr hProv, 96 StringBuilder pszContainer, // Don't use string, as Powershell replaces $null with an empty string 97 StringBuilder pszProvider, // Don't use string, as Powershell replaces $null with an empty string 98 uint dwProvType, 99 uint dwFlags); 100 101 [DllImport("Advapi32.dll", EntryPoint = "CryptReleaseContext", CharSet = CharSet.Unicode, SetLastError = true)] 102 public static extern bool CryptReleaseContext(IntPtr hProv, Int32 dwFlags); 103 104 [DllImport("advapi32.dll", SetLastError=true)] 105 public static extern bool CryptGenRandom(IntPtr hProv, uint dwLen, byte[] pbBuffer); 106 107 [DllImport("Kernel32.dll")] 108 public static extern uint GetLastError(); 109 } 110 } 111 "@ 112 113 Add-Type -TypeDefinition $Source -Language CSharp 114 115 function Get-RandomPassword 116 { 117 [CmdletBinding()] 118 param 119 ( 120 [parameter(Mandatory=$true)] 121 [int]$Length 122 ) 123 process 124 { 125 $hProvider = 0 126 try 127 { 128 if(![PSCloudbase.Win32CryptApi]::CryptAcquireContext([ref]$hProvider, $null, $null, 129 [PSCloudbase.Win32CryptApi]::PROV_RSA_FULL, 130 ([PSCloudbase.Win32CryptApi]::CRYPT_VERIFYCONTEXT -bor 131 [PSCloudbase.Win32CryptApi]::CRYPT_SILENT))) 132 { 133 throw "CryptAcquireContext failed with error: 0x" + "{0:X0}" -f [PSCloudbase.Win32CryptApi]::GetLastError() 134 } 135 136 $buffer = New-Object byte[] $Length 137 if(![PSCloudbase.Win32CryptApi]::CryptGenRandom($hProvider, $Length, $buffer)) 138 { 139 throw "CryptGenRandom failed with error: 0x" + "{0:X0}" -f [PSCloudbase.Win32CryptApi]::GetLastError() 140 } 141 142 $buffer | ForEach-Object { $password += "{0:X0}" -f $_ } 143 return $password 144 } 145 finally 146 { 147 if($hProvider) 148 { 149 $retVal = [PSCloudbase.Win32CryptApi]::CryptReleaseContext($hProvider, 0) 150 } 151 } 152 } 153 } 154 155 $SourcePolicy = @" 156 /* 157 Original sources available at: https://bitbucket.org/splatteredbits/carbon 158 */ 159 160 using System; 161 using System.Collections.Generic; 162 using System.ComponentModel; 163 using System.Runtime.InteropServices; 164 using System.Security.Principal; 165 using System.Text; 166 167 namespace PSCarbon 168 { 169 public sealed class Lsa 170 { 171 // ReSharper disable InconsistentNaming 172 [StructLayout(LayoutKind.Sequential)] 173 internal struct LSA_UNICODE_STRING 174 { 175 internal LSA_UNICODE_STRING(string inputString) 176 { 177 if (inputString == null) 178 { 179 Buffer = IntPtr.Zero; 180 Length = 0; 181 MaximumLength = 0; 182 } 183 else 184 { 185 Buffer = Marshal.StringToHGlobalAuto(inputString); 186 Length = (ushort)(inputString.Length * UnicodeEncoding.CharSize); 187 MaximumLength = (ushort)((inputString.Length + 1) * UnicodeEncoding.CharSize); 188 } 189 } 190 191 internal ushort Length; 192 internal ushort MaximumLength; 193 internal IntPtr Buffer; 194 } 195 196 [StructLayout(LayoutKind.Sequential)] 197 internal struct LSA_OBJECT_ATTRIBUTES 198 { 199 internal uint Length; 200 internal IntPtr RootDirectory; 201 internal LSA_UNICODE_STRING ObjectName; 202 internal uint Attributes; 203 internal IntPtr SecurityDescriptor; 204 internal IntPtr SecurityQualityOfService; 205 } 206 207 [StructLayout(LayoutKind.Sequential)] 208 public struct LUID 209 { 210 public uint LowPart; 211 public int HighPart; 212 } 213 214 // ReSharper disable UnusedMember.Local 215 private const uint POLICY_VIEW_LOCAL_INFORMATION = 0x00000001; 216 private const uint POLICY_VIEW_AUDIT_INFORMATION = 0x00000002; 217 private const uint POLICY_GET_PRIVATE_INFORMATION = 0x00000004; 218 private const uint POLICY_TRUST_ADMIN = 0x00000008; 219 private const uint POLICY_CREATE_ACCOUNT = 0x00000010; 220 private const uint POLICY_CREATE_SECRET = 0x00000014; 221 private const uint POLICY_CREATE_PRIVILEGE = 0x00000040; 222 private const uint POLICY_SET_DEFAULT_QUOTA_LIMITS = 0x00000080; 223 private const uint POLICY_SET_AUDIT_REQUIREMENTS = 0x00000100; 224 private const uint POLICY_AUDIT_LOG_ADMIN = 0x00000200; 225 private const uint POLICY_SERVER_ADMIN = 0x00000400; 226 private const uint POLICY_LOOKUP_NAMES = 0x00000800; 227 private const uint POLICY_NOTIFICATION = 0x00001000; 228 // ReSharper restore UnusedMember.Local 229 230 [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 231 public static extern bool LookupPrivilegeValue( 232 [MarshalAs(UnmanagedType.LPTStr)] string lpSystemName, 233 [MarshalAs(UnmanagedType.LPTStr)] string lpName, 234 out LUID lpLuid); 235 236 [DllImport("advapi32.dll", CharSet = CharSet.Unicode)] 237 private static extern uint LsaAddAccountRights( 238 IntPtr PolicyHandle, 239 IntPtr AccountSid, 240 LSA_UNICODE_STRING[] UserRights, 241 uint CountOfRights); 242 243 [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = false)] 244 private static extern uint LsaClose(IntPtr ObjectHandle); 245 246 [DllImport("advapi32.dll", SetLastError = true)] 247 private static extern uint LsaEnumerateAccountRights(IntPtr PolicyHandle, 248 IntPtr AccountSid, 249 out IntPtr UserRights, 250 out uint CountOfRights 251 ); 252 253 [DllImport("advapi32.dll", SetLastError = true)] 254 private static extern uint LsaFreeMemory(IntPtr pBuffer); 255 256 [DllImport("advapi32.dll")] 257 private static extern int LsaNtStatusToWinError(long status); 258 259 [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] 260 private static extern uint LsaOpenPolicy(ref LSA_UNICODE_STRING SystemName, ref LSA_OBJECT_ATTRIBUTES ObjectAttributes, uint DesiredAccess, out IntPtr PolicyHandle ); 261 262 [DllImport("advapi32.dll", SetLastError = true, PreserveSig = true)] 263 static extern uint LsaRemoveAccountRights( 264 IntPtr PolicyHandle, 265 IntPtr AccountSid, 266 [MarshalAs(UnmanagedType.U1)] 267 bool AllRights, 268 LSA_UNICODE_STRING[] UserRights, 269 uint CountOfRights); 270 // ReSharper restore InconsistentNaming 271 272 private static IntPtr GetIdentitySid(string identity) 273 { 274 var sid = 275 new NTAccount(identity).Translate(typeof (SecurityIdentifier)) as SecurityIdentifier; 276 if (sid == null) 277 { 278 throw new ArgumentException(string.Format("Account {0} not found.", identity)); 279 } 280 var sidBytes = new byte[sid.BinaryLength]; 281 sid.GetBinaryForm(sidBytes, 0); 282 var sidPtr = Marshal.AllocHGlobal(sidBytes.Length); 283 Marshal.Copy(sidBytes, 0, sidPtr, sidBytes.Length); 284 return sidPtr; 285 } 286 287 private static IntPtr GetLsaPolicyHandle() 288 { 289 var computerName = Environment.MachineName; 290 IntPtr hPolicy; 291 var objectAttributes = new LSA_OBJECT_ATTRIBUTES 292 { 293 Length = 0, 294 RootDirectory = IntPtr.Zero, 295 Attributes = 0, 296 SecurityDescriptor = IntPtr.Zero, 297 SecurityQualityOfService = IntPtr.Zero 298 }; 299 300 const uint ACCESS_MASK = POLICY_CREATE_SECRET | POLICY_LOOKUP_NAMES | POLICY_VIEW_LOCAL_INFORMATION; 301 var machineNameLsa = new LSA_UNICODE_STRING(computerName); 302 var result = LsaOpenPolicy(ref machineNameLsa, ref objectAttributes, ACCESS_MASK, out hPolicy); 303 HandleLsaResult(result); 304 return hPolicy; 305 } 306 307 public static string[] GetPrivileges(string identity) 308 { 309 var sidPtr = GetIdentitySid(identity); 310 var hPolicy = GetLsaPolicyHandle(); 311 var rightsPtr = IntPtr.Zero; 312 313 try 314 { 315 316 var privileges = new List<string>(); 317 318 uint rightsCount; 319 var result = LsaEnumerateAccountRights(hPolicy, sidPtr, out rightsPtr, out rightsCount); 320 var win32ErrorCode = LsaNtStatusToWinError(result); 321 // the user has no privileges 322 if( win32ErrorCode == STATUS_OBJECT_NAME_NOT_FOUND ) 323 { 324 return new string[0]; 325 } 326 HandleLsaResult(result); 327 328 var myLsaus = new LSA_UNICODE_STRING(); 329 for (ulong i = 0; i < rightsCount; i++) 330 { 331 var itemAddr = new IntPtr(rightsPtr.ToInt64() + (long) (i*(ulong) Marshal.SizeOf(myLsaus))); 332 myLsaus = (LSA_UNICODE_STRING) Marshal.PtrToStructure(itemAddr, myLsaus.GetType()); 333 var cvt = new char[myLsaus.Length/UnicodeEncoding.CharSize]; 334 Marshal.Copy(myLsaus.Buffer, cvt, 0, myLsaus.Length/UnicodeEncoding.CharSize); 335 var thisRight = new string(cvt); 336 privileges.Add(thisRight); 337 } 338 return privileges.ToArray(); 339 } 340 finally 341 { 342 Marshal.FreeHGlobal(sidPtr); 343 var result = LsaClose(hPolicy); 344 HandleLsaResult(result); 345 result = LsaFreeMemory(rightsPtr); 346 HandleLsaResult(result); 347 } 348 } 349 350 public static void GrantPrivileges(string identity, string[] privileges) 351 { 352 var sidPtr = GetIdentitySid(identity); 353 var hPolicy = GetLsaPolicyHandle(); 354 355 try 356 { 357 var lsaPrivileges = StringsToLsaStrings(privileges); 358 var result = LsaAddAccountRights(hPolicy, sidPtr, lsaPrivileges, (uint)lsaPrivileges.Length); 359 HandleLsaResult(result); 360 } 361 finally 362 { 363 Marshal.FreeHGlobal(sidPtr); 364 var result = LsaClose(hPolicy); 365 HandleLsaResult(result); 366 } 367 } 368 369 const int STATUS_SUCCESS = 0x0; 370 const int STATUS_OBJECT_NAME_NOT_FOUND = 0x00000002; 371 const int STATUS_ACCESS_DENIED = 0x00000005; 372 const int STATUS_INVALID_HANDLE = 0x00000006; 373 const int STATUS_UNSUCCESSFUL = 0x0000001F; 374 const int STATUS_INVALID_PARAMETER = 0x00000057; 375 const int STATUS_NO_SUCH_PRIVILEGE = 0x00000521; 376 const int STATUS_INVALID_SERVER_STATE = 0x00000548; 377 const int STATUS_INTERNAL_DB_ERROR = 0x00000567; 378 const int STATUS_INSUFFICIENT_RESOURCES = 0x000005AA; 379 380 private static Dictionary<int, string> ErrorMessages = new Dictionary<int, string> 381 { 382 {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."}, 383 {STATUS_ACCESS_DENIED, "Access denied. Caller does not have the appropriate access to complete the operation."}, 384 {STATUS_INVALID_HANDLE, "Invalid handle. Indicates an object or RPC handle is not valid in the context used."}, 385 {STATUS_UNSUCCESSFUL, "Unsuccessful. Generic failure, such as RPC connection failure."}, 386 {STATUS_INVALID_PARAMETER, "Invalid parameter. One of the parameters is not valid."}, 387 {STATUS_NO_SUCH_PRIVILEGE, "No such privilege. Indicates a specified privilege does not exist."}, 388 {STATUS_INVALID_SERVER_STATE, "Invalid server state. Indicates the LSA server is currently disabled."}, 389 {STATUS_INTERNAL_DB_ERROR, "Internal database error. The LSA database contains an internal inconsistency."}, 390 {STATUS_INSUFFICIENT_RESOURCES, "Insufficient resources. There are not enough system resources (such as memory to allocate buffers) to complete the call."} 391 }; 392 393 private static void HandleLsaResult(uint returnCode) 394 { 395 var win32ErrorCode = LsaNtStatusToWinError(returnCode); 396 397 if( win32ErrorCode == STATUS_SUCCESS) 398 return; 399 400 if( ErrorMessages.ContainsKey(win32ErrorCode) ) 401 { 402 throw new Win32Exception(win32ErrorCode, ErrorMessages[win32ErrorCode]); 403 } 404 405 throw new Win32Exception(win32ErrorCode); 406 } 407 408 public static void RevokePrivileges(string identity, string[] privileges) 409 { 410 var sidPtr = GetIdentitySid(identity); 411 var hPolicy = GetLsaPolicyHandle(); 412 413 try 414 { 415 var currentPrivileges = GetPrivileges(identity); 416 if (currentPrivileges.Length == 0) 417 { 418 return; 419 } 420 var lsaPrivileges = StringsToLsaStrings(privileges); 421 var result = LsaRemoveAccountRights(hPolicy, sidPtr, false, lsaPrivileges, (uint)lsaPrivileges.Length); 422 HandleLsaResult(result); 423 } 424 finally 425 { 426 Marshal.FreeHGlobal(sidPtr); 427 var result = LsaClose(hPolicy); 428 HandleLsaResult(result); 429 } 430 431 } 432 433 private static LSA_UNICODE_STRING[] StringsToLsaStrings(string[] privileges) 434 { 435 var lsaPrivileges = new LSA_UNICODE_STRING[privileges.Length]; 436 for (var idx = 0; idx < privileges.Length; ++idx) 437 { 438 lsaPrivileges[idx] = new LSA_UNICODE_STRING(privileges[idx]); 439 } 440 return lsaPrivileges; 441 } 442 } 443 } 444 "@ 445 446 Add-Type -TypeDefinition $SourcePolicy -Language CSharp 447 448 function SetAssignPrimaryTokenPrivilege($UserName) 449 { 450 $privilege = "SeAssignPrimaryTokenPrivilege" 451 if (![PSCarbon.Lsa]::GetPrivileges($UserName).Contains($privilege)) 452 { 453 [PSCarbon.Lsa]::GrantPrivileges($UserName, $privilege) 454 } 455 } 456 457 function SetUserLogonAsServiceRights($UserName) 458 { 459 $privilege = "SeServiceLogonRight" 460 if (![PSCarbon.Lsa]::GetPrivileges($UserName).Contains($privilege)) 461 { 462 [PSCarbon.Lsa]::GrantPrivileges($UserName, $privilege) 463 } 464 } 465 466 $Source = @" 467 using System; 468 using System.Collections.Generic; 469 using System.Diagnostics; 470 using System.IO; 471 using System.Net; 472 using System.Text; 473 474 namespace Tarer 475 { 476 public enum EntryType : byte 477 { 478 File = 0, 479 FileObsolete = 0x30, 480 HardLink = 0x31, 481 SymLink = 0x32, 482 CharDevice = 0x33, 483 BlockDevice = 0x34, 484 Directory = 0x35, 485 Fifo = 0x36, 486 } 487 488 public interface ITarHeader 489 { 490 string FileName { get; set; } 491 long SizeInBytes { get; set; } 492 DateTime LastModification { get; set; } 493 int HeaderSize { get; } 494 EntryType EntryType { get; set; } 495 } 496 497 public class Tar 498 { 499 private byte[] dataBuffer = new byte[512]; 500 private UsTarHeader header; 501 private Stream inStream; 502 private long remainingBytesInFile; 503 504 public Tar(Stream tarredData) { 505 inStream = tarredData; 506 header = new UsTarHeader(); 507 } 508 509 public ITarHeader FileInfo 510 { 511 get { return header; } 512 } 513 514 public void ReadToEnd(string destDirectory) 515 { 516 while (MoveNext()) 517 { 518 string fileNameFromArchive = FileInfo.FileName; 519 string totalPath = destDirectory + Path.DirectorySeparatorChar + fileNameFromArchive; 520 if(UsTarHeader.IsPathSeparator(fileNameFromArchive[fileNameFromArchive.Length -1]) || FileInfo.EntryType == EntryType.Directory) 521 { 522 Directory.CreateDirectory(totalPath); 523 continue; 524 } 525 string fileName = Path.GetFileName(totalPath); 526 string directory = totalPath.Remove(totalPath.Length - fileName.Length); 527 Directory.CreateDirectory(directory); 528 using (FileStream file = File.Create(totalPath)) 529 { 530 Read(file); 531 } 532 } 533 } 534 535 public void Read(Stream dataDestination) 536 { 537 int readBytes; 538 byte[] read; 539 while ((readBytes = Read(out read)) != -1) 540 { 541 dataDestination.Write(read, 0, readBytes); 542 } 543 } 544 545 protected int Read(out byte[] buffer) 546 { 547 if(remainingBytesInFile == 0) 548 { 549 buffer = null; 550 return -1; 551 } 552 int align512 = -1; 553 long toRead = remainingBytesInFile - 512; 554 555 if (toRead > 0) 556 { 557 toRead = 512; 558 } 559 else 560 { 561 align512 = 512 - (int)remainingBytesInFile; 562 toRead = remainingBytesInFile; 563 } 564 565 int bytesRead = 0; 566 long bytesRemainingToRead = toRead; 567 while (bytesRead < toRead && bytesRemainingToRead > 0) 568 { 569 bytesRead = inStream.Read(dataBuffer, (int)(toRead-bytesRemainingToRead), (int)bytesRemainingToRead); 570 bytesRemainingToRead -= bytesRead; 571 remainingBytesInFile -= bytesRead; 572 } 573 574 if(inStream.CanSeek && align512 > 0) 575 { 576 inStream.Seek(align512, SeekOrigin.Current); 577 } 578 else 579 { 580 while(align512 > 0) 581 { 582 inStream.ReadByte(); 583 --align512; 584 } 585 } 586 587 buffer = dataBuffer; 588 return bytesRead; 589 } 590 591 private static bool IsEmpty(IEnumerable<byte> buffer) 592 { 593 foreach(byte b in buffer) 594 { 595 if (b != 0) 596 { 597 return false; 598 } 599 } 600 return true; 601 } 602 603 public bool MoveNext() 604 { 605 byte[] bytes = header.GetBytes(); 606 int headerRead; 607 int bytesRemaining = header.HeaderSize; 608 while (bytesRemaining > 0) 609 { 610 headerRead = inStream.Read(bytes, header.HeaderSize - bytesRemaining, bytesRemaining); 611 bytesRemaining -= headerRead; 612 if (headerRead <= 0 && bytesRemaining > 0) 613 { 614 throw new Exception("Error reading tar header. Header size invalid"); 615 } 616 } 617 618 if(IsEmpty(bytes)) 619 { 620 bytesRemaining = header.HeaderSize; 621 while (bytesRemaining > 0) 622 { 623 headerRead = inStream.Read(bytes, header.HeaderSize - bytesRemaining, bytesRemaining); 624 bytesRemaining -= headerRead; 625 if (headerRead <= 0 && bytesRemaining > 0) 626 { 627 throw new Exception("Broken archive"); 628 } 629 } 630 if (bytesRemaining == 0 && IsEmpty(bytes)) 631 { 632 return false; 633 } 634 throw new Exception("Error occured: expected end of archive"); 635 } 636 637 if (!header.UpdateHeaderFromBytes()) 638 { 639 throw new Exception("Checksum check failed"); 640 } 641 642 remainingBytesInFile = header.SizeInBytes; 643 return true; 644 } 645 } 646 647 internal class TarHeader : ITarHeader 648 { 649 private byte[] buffer = new byte[512]; 650 private long headerChecksum; 651 652 private string fileName; 653 protected DateTime dateTime1970 = new DateTime(1970, 1, 1, 0, 0, 0); 654 public EntryType EntryType { get; set; } 655 private static byte[] spaces = Encoding.ASCII.GetBytes(" "); 656 657 public virtual string FileName 658 { 659 get { return fileName.Replace("\0",string.Empty); } 660 set { fileName = value; } 661 } 662 663 public long SizeInBytes { get; set; } 664 665 public string SizeString { get { return Convert.ToString(SizeInBytes, 8).PadLeft(11, '0'); } } 666 667 public DateTime LastModification { get; set; } 668 669 public virtual int HeaderSize { get { return 512; } } 670 671 public byte[] GetBytes() 672 { 673 return buffer; 674 } 675 676 public virtual bool UpdateHeaderFromBytes() 677 { 678 FileName = Encoding.UTF8.GetString(buffer, 0, 100); 679 680 EntryType = (EntryType)buffer[156]; 681 682 if((buffer[124] & 0x80) == 0x80) // if size in binary 683 { 684 long sizeBigEndian = BitConverter.ToInt64(buffer,0x80); 685 SizeInBytes = IPAddress.NetworkToHostOrder(sizeBigEndian); 686 } 687 else 688 { 689 SizeInBytes = Convert.ToInt64(Encoding.ASCII.GetString(buffer, 124, 11).Trim(), 8); 690 } 691 long unixTimeStamp = Convert.ToInt64(Encoding.ASCII.GetString(buffer,136,11).Trim(),8); 692 LastModification = dateTime1970.AddSeconds(unixTimeStamp); 693 694 var storedChecksum = Convert.ToInt64(Encoding.ASCII.GetString(buffer,148,6).Trim(), 8); 695 RecalculateChecksum(buffer); 696 if (storedChecksum == headerChecksum) 697 { 698 return true; 699 } 700 701 RecalculateAltChecksum(buffer); 702 return storedChecksum == headerChecksum; 703 } 704 705 private void RecalculateAltChecksum(byte[] buf) 706 { 707 spaces.CopyTo(buf, 148); 708 headerChecksum = 0; 709 foreach(byte b in buf) 710 { 711 if((b & 0x80) == 0x80) 712 { 713 headerChecksum -= b ^ 0x80; 714 } 715 else 716 { 717 headerChecksum += b; 718 } 719 } 720 } 721 722 protected virtual void RecalculateChecksum(byte[] buf) 723 { 724 // Set default value for checksum. That is 8 spaces. 725 spaces.CopyTo(buf, 148); 726 // Calculate checksum 727 headerChecksum = 0; 728 foreach (byte b in buf) 729 { 730 headerChecksum += b; 731 } 732 } 733 } 734 internal class UsTarHeader : TarHeader 735 { 736 private const string magic = "ustar"; 737 private const string version = " "; 738 739 private string namePrefix = string.Empty; 740 741 public override string FileName 742 { 743 get { return namePrefix.Replace("\0", string.Empty) + base.FileName.Replace("\0", string.Empty); } 744 set 745 { 746 if (value.Length > 255) 747 { 748 throw new Exception("UsTar fileName can not be longer than 255 chars"); 749 } 750 if (value.Length > 100) 751 { 752 int position = value.Length - 100; 753 while (!IsPathSeparator(value[position])) 754 { 755 ++position; 756 if (position == value.Length) 757 { 758 break; 759 } 760 } 761 if (position == value.Length) 762 { 763 position = value.Length - 100; 764 } 765 namePrefix = value.Substring(0, position); 766 base.FileName = value.Substring(position, value.Length - position); 767 } 768 else 769 { 770 base.FileName = value; 771 } 772 } 773 } 774 775 public override bool UpdateHeaderFromBytes() 776 { 777 byte[] bytes = GetBytes(); 778 namePrefix = Encoding.UTF8.GetString(bytes, 347, 157); 779 return base.UpdateHeaderFromBytes(); 780 } 781 782 internal static bool IsPathSeparator(char ch) 783 { 784 return (ch == '\\' || ch == '/' || ch == '|'); 785 } 786 } 787 } 788 "@ 789 790 Add-Type -TypeDefinition $Source -Language CSharp 791 792 Function GUnZip-File{ 793 Param( 794 $infile, 795 $outdir 796 ) 797 798 $input = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) 799 $tempFile = "$env:TEMP\jujud.tar" 800 $tempOut = New-Object System.IO.FileStream $tempFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None) 801 $gzipStream = New-Object System.IO.Compression.GzipStream $input, ([IO.Compression.CompressionMode]::Decompress) 802 803 $buffer = New-Object byte[](1024) 804 while($true){ 805 $read = $gzipstream.Read($buffer, 0, 1024) 806 if ($read -le 0){break} 807 $tempOut.Write($buffer, 0, $read) 808 } 809 $gzipStream.Close() 810 $tempOut.Close() 811 $input.Close() 812 813 $in = New-Object System.IO.FileStream $tempFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) 814 $tar = New-Object Tarer.Tar($in) 815 $tar.ReadToEnd($outdir) 816 $in.Close() 817 rm $tempFile 818 } 819 820 Function Get-FileSHA256{ 821 Param( 822 $FilePath 823 ) 824 $hash = [Security.Cryptography.HashAlgorithm]::Create( "SHA256" ) 825 $stream = ([IO.StreamReader]$FilePath).BaseStream 826 $res = -join ($hash.ComputeHash($stream) | ForEach { "{0:x2}" -f $_ }) 827 $stream.Close() 828 return $res 829 } 830 831 $juju_passwd = Get-RandomPassword 20 832 $juju_passwd += "^" 833 create-account jujud "Juju Admin user" $juju_passwd 834 $hostname = hostname 835 $juju_user = "$hostname\jujud" 836 837 SetUserLogonAsServiceRights $juju_user 838 SetAssignPrimaryTokenPrivilege $juju_user 839 840 $path = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" 841 if(!(Test-Path $path)){ 842 New-Item -Path $path -force 843 } 844 New-ItemProperty $path -Name "jujud" -Value 0 -PropertyType "DWord" 845 846 $secpasswd = ConvertTo-SecureString $juju_passwd -AsPlainText -Force 847 $jujuCreds = New-Object System.Management.Automation.PSCredential ($juju_user, $secpasswd) 848 849 ` 850 851 var UserdataScript = `#ps1_sysnative 852 $userdata=@" 853 %s 854 "@ 855 856 Function Decode-Base64 { 857 Param( 858 $inFile, 859 $outFile 860 ) 861 $bufferSize = 9000 # should be a multiplier of 4 862 $buffer = New-Object char[] $bufferSize 863 864 $reader = [System.IO.File]::OpenText($inFile) 865 $writer = [System.IO.File]::OpenWrite($outFile) 866 867 $bytesRead = 0 868 do 869 { 870 $bytesRead = $reader.Read($buffer, 0, $bufferSize); 871 $bytes = [Convert]::FromBase64CharArray($buffer, 0, $bytesRead); 872 $writer.Write($bytes, 0, $bytes.Length); 873 } while ($bytesRead -eq $bufferSize); 874 875 $reader.Dispose() 876 $writer.Dispose() 877 } 878 879 Function GUnZip-File { 880 Param( 881 $inFile, 882 $outFile 883 ) 884 $in = New-Object System.IO.FileStream $inFile, ([IO.FileMode]::Open), ([IO.FileAccess]::Read), ([IO.FileShare]::Read) 885 $out = New-Object System.IO.FileStream $outFile, ([IO.FileMode]::Create), ([IO.FileAccess]::Write), ([IO.FileShare]::None) 886 $gzipStream = New-Object System.IO.Compression.GZipStream $in, ([IO.Compression.CompressionMode]::Decompress) 887 $buffer = New-Object byte[](1024) 888 while($true){ 889 $read = $gzipstream.Read($buffer, 0, 1024) 890 if ($read -le 0){break} 891 $out.Write($buffer, 0, $read) 892 } 893 $gzipStream.Close() 894 $out.Close() 895 $in.Close() 896 } 897 898 $b64File = "$env:TEMP\juju\udata.b64" 899 $gzFile = "$env:TEMP\juju\udata.gz" 900 $udataScript = "$env:TEMP\juju\udata.ps1" 901 mkdir "$env:TEMP\juju" 902 903 Set-Content $b64File $userdata 904 Decode-Base64 -inFile $b64File -outFile $gzFile 905 GUnZip-File -inFile $gzFile -outFile $udataScript 906 907 & $udataScript 908 909 rm -Recurse "$env:TEMP\juju" 910 `