~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cloudconfig/winuserdata.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
`