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