GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Fix 'Debug-Runspace' for Unix platforms and properly enable Windows i… · PowerShell/PowerShell@bc29337

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
  • src/System.Management.Automation/engine
    • Utils.cs
    • hostifaces
      • LocalPipeline.cs
    • remoting
      • client
        • remoterunspace.cs
      • fanin
        • BaseTransportManager.cs
        • WSManTransportManager.cs
      • server
        • OutOfProcServerMediator.cs
        • ServerRunspacePoolDriver.cs
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/System.Management.Automation/engine/Utils.cs‎

Copy file name to clipboardExpand all lines: src/System.Management.Automation/engine/Utils.cs
+66-41Lines changed: 66 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,36 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
using System.Security;
5-
using System.Runtime.InteropServices;
4+
using System.Collections;
5+
using System.Collections.Concurrent;
6+
using System.Collections.Generic;
7+
using System.Collections.ObjectModel;
8+
using System.Diagnostics;
69
using System.Diagnostics.CodeAnalysis;
10+
using System.Globalization;
11+
using System.IO;
12+
using System.Linq;
13+
using System.ComponentModel;
714
using System.Management.Automation.Configuration;
815
using System.Management.Automation.Internal;
916
using System.Management.Automation.Language;
1017
using System.Management.Automation.Runspaces;
1118
using System.Management.Automation.Security;
1219
using System.Reflection;
13-
using Microsoft.PowerShell.Commands;
14-
using Microsoft.Win32;
15-
using System.Globalization;
16-
using System.IO;
17-
using System.Linq;
18-
using System.Collections;
19-
using System.Collections.ObjectModel;
20-
using System.Collections.Generic;
21-
using System.Collections.Concurrent;
22-
using System.ComponentModel;
2320
using System.Runtime.CompilerServices;
24-
using System.Threading;
21+
using System.Runtime.InteropServices;
22+
using System.Security;
23+
#if !UNIX
24+
using System.Security.Principal;
25+
#endif
2526
using System.Text;
27+
using System.Threading;
28+
using Microsoft.PowerShell.Commands;
29+
using Microsoft.Win32;
30+
using Microsoft.Win32.SafeHandles;
2631

2732
using TypeTable = System.Management.Automation.Runspaces.TypeTable;
2833

29-
using System.Diagnostics;
30-
using Microsoft.Win32.SafeHandles;
31-
3234
namespace System.Management.Automation
3335
{
3436
/// <summary>
@@ -870,6 +872,40 @@ internal static List<PSModuleInfo> GetModules(ModuleSpecification fullyQualified
870872
return result;
871873
}
872874

875+
#if !UNIX
876+
private static bool TryGetWindowsCurrentIdentity(out WindowsIdentity currentIdentity)
877+
{
878+
try
879+
{
880+
currentIdentity = WindowsIdentity.GetCurrent();
881+
}
882+
catch (SecurityException)
883+
{
884+
currentIdentity = null;
885+
}
886+
887+
return (currentIdentity != null);
888+
}
889+
890+
/// <summary>
891+
/// Gets the current impersonating Windows identity, if any
892+
/// </summary>
893+
/// <param name="impersonatedIdentity">Current impersonated Windows identity or null</param>
894+
/// <returns>True if current identity is impersonated</returns>
895+
internal static bool TryGetWindowsImpersonatedIdentity(out WindowsIdentity impersonatedIdentity)
896+
{
897+
WindowsIdentity currentIdentity;
898+
if (TryGetWindowsCurrentIdentity(out currentIdentity) && (currentIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation))
899+
{
900+
impersonatedIdentity = currentIdentity;
901+
return true;
902+
}
903+
904+
impersonatedIdentity = null;
905+
return false;
906+
}
907+
#endif
908+
873909
internal static bool IsAdministrator()
874910
{
875911
// Porting note: only Windows supports the SecurityPrincipal API of .NET. Due to
@@ -881,10 +917,13 @@ internal static bool IsAdministrator()
881917
#if UNIX
882918
return true;
883919
#else
884-
System.Security.Principal.WindowsIdentity currentIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
885-
System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(currentIdentity);
886-
887-
return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
920+
WindowsIdentity currentIdentity;
921+
if (TryGetWindowsCurrentIdentity(out currentIdentity))
922+
{
923+
var principal = new WindowsPrincipal(currentIdentity);
924+
return principal.IsInRole(WindowsBuiltInRole.Administrator);
925+
}
926+
return false;
888927
#endif
889928
}
890929

@@ -1171,7 +1210,7 @@ internal static Encoding GetEncoding(string path)
11711210
internal static readonly UTF8Encoding utf8NoBom =
11721211
new UTF8Encoding(encoderShouldEmitUTF8Identifier: false);
11731212

1174-
#if !CORECLR // TODO:CORECLR - WindowsIdentity.Impersonate() is not available. Use WindowsIdentity.RunImpersonated to replace it.
1213+
#if !UNIX
11751214
/// <summary>
11761215
/// Queues a CLR worker thread with impersonation of provided Windows identity.
11771216
/// </summary>
@@ -1197,28 +1236,14 @@ private static void WorkItemCallback(object callBackArgs)
11971236
WaitCallback callback = args[1] as WaitCallback;
11981237
object state = args[2];
11991238

1200-
WindowsImpersonationContext impersonationContext = null;
1201-
if ((identityToImpersonate != null) &&
1202-
(identityToImpersonate.ImpersonationLevel == TokenImpersonationLevel.Impersonation))
1203-
{
1204-
impersonationContext = identityToImpersonate.Impersonate();
1205-
}
1206-
try
1239+
if (identityToImpersonate != null)
12071240
{
1208-
callback(state);
1209-
}
1210-
finally
1211-
{
1212-
if (impersonationContext != null)
1213-
{
1214-
try
1215-
{
1216-
impersonationContext.Undo();
1217-
impersonationContext.Dispose();
1218-
}
1219-
catch (System.Security.SecurityException) { }
1220-
}
1241+
WindowsIdentity.RunImpersonated(
1242+
identityToImpersonate.AccessToken,
1243+
() => callback(state));
1244+
return;
12211245
}
1246+
callback(state);
12221247
}
12231248
#endif
12241249

Collapse file

‎src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs‎

Copy file name to clipboardExpand all lines: src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs
+57-50Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License.
33

4-
using System.Diagnostics;
54
using System.Collections.Generic;
5+
using System.Diagnostics;
66
using System.Globalization;
7-
using System.Threading;
8-
using Microsoft.Win32;
97
using System.Management.Automation.Internal;
108
using System.Management.Automation.Internal.Host;
119
using System.Management.Automation.Tracing;
10+
#if !UNIX
11+
using System.Security.Principal;
12+
#endif
13+
using System.Threading;
1214
using Microsoft.PowerShell.Commands;
15+
using Microsoft.Win32;
1316

1417
using Dbg = System.Management.Automation.Diagnostics;
1518

@@ -152,13 +155,29 @@ protected override void StartPipelineExecution()
152155

153156
PSThreadOptions memberOptions = this.IsNested ? PSThreadOptions.UseCurrentThread : this.LocalRunspace.ThreadOptions;
154157

158+
#if !UNIX
159+
// Use thread proc that supports impersonation flow for new thread start.
160+
ThreadStart invokeThreadProcDelegate = InvokeThreadProcImpersonate;
161+
_identityToImpersonate = null;
162+
163+
// If impersonation identity flow is requested, then get current thread impersonation, if any.
164+
if ((InvocationSettings != null) && InvocationSettings.FlowImpersonationPolicy)
165+
{
166+
Utils.TryGetWindowsImpersonatedIdentity(out _identityToImpersonate);
167+
}
168+
#else
169+
// UNIX does not support thread impersonation flow.
170+
ThreadStart invokeThreadProcDelegate = InvokeThreadProc;
171+
#endif
172+
155173
switch (memberOptions)
156174
{
157175
case PSThreadOptions.Default:
158176
case PSThreadOptions.UseNewThread:
159177
{
160-
// Start execution of pipeline in another thread
161-
Thread invokeThread = new Thread(new ThreadStart(this.InvokeThreadProc), DefaultPipelineStackSize);
178+
// Start execution of pipeline in another thread,
179+
// and support impersonation flow as needed (Windows only).
180+
Thread invokeThread = new Thread(new ThreadStart(invokeThreadProcDelegate), DefaultPipelineStackSize);
162181
SetupInvokeThread(invokeThread, true);
163182
#if !CORECLR
164183
// No ApartmentState in CoreCLR
@@ -187,16 +206,18 @@ protected override void StartPipelineExecution()
187206
{
188207
if (this.IsNested)
189208
{
190-
// if this a nested pipeline we are already in the appropriate thread so we just execute the pipeline here
209+
// If this a nested pipeline we are already in the appropriate thread so we just execute the pipeline here.
210+
// Impersonation flow (Windows only) is not needed when using existing thread.
191211
SetupInvokeThread(Thread.CurrentThread, true);
192-
this.InvokeThreadProc();
212+
InvokeThreadProc();
193213
}
194214
else
195215
{
196-
// otherwise we execute the pipeline in the Runspace's thread
216+
// Otherwise we execute the pipeline in the Runspace's thread,
217+
// and support information flow on new thread as needed (Windows only).
197218
PipelineThread invokeThread = this.LocalRunspace.GetPipelineThread();
198219
SetupInvokeThread(invokeThread.Worker, true);
199-
invokeThread.Start(this.InvokeThreadProc);
220+
invokeThread.Start(invokeThreadProcDelegate);
200221
}
201222
break;
202223
}
@@ -210,9 +231,10 @@ protected override void StartPipelineExecution()
210231

211232
try
212233
{
213-
// prepare invoke thread
234+
// Prepare invoke thread.
235+
// Impersonation flow (Windows only) is not needed when using existing thread.
214236
SetupInvokeThread(Thread.CurrentThread, false);
215-
this.InvokeThreadProc();
237+
InvokeThreadProc();
216238
}
217239
finally
218240
{
@@ -508,8 +530,26 @@ private FlowControlException InvokeHelper()
508530
return flowControlException;
509531
}
510532

511-
// NTRAID#Windows Out Of Band Releases-915506-2005/09/09
512-
// Removed HandleUnexpectedExceptions infrastructure
533+
#if !UNIX
534+
/// <summary>
535+
/// Invokes the InvokeThreadProc() method on new thread, and flows calling thread
536+
/// impersonation as needed.
537+
/// </summary>
538+
private void InvokeThreadProcImpersonate()
539+
{
540+
if (_identityToImpersonate != null)
541+
{
542+
WindowsIdentity.RunImpersonated(
543+
_identityToImpersonate.AccessToken,
544+
() => InvokeThreadProc());
545+
546+
return;
547+
}
548+
549+
InvokeThreadProc();
550+
}
551+
#endif
552+
513553
/// <summary>
514554
/// Start thread method for asynchronous pipeline execution.
515555
/// </summary>
@@ -520,19 +560,6 @@ private void InvokeThreadProc()
520560

521561
try
522562
{
523-
#if !CORECLR // Impersonation is not supported in CoreCLR.
524-
// Used to store old impersonation context if we impersonate.
525-
System.Security.Principal.WindowsImpersonationContext oldImpersonationCtxt = null;
526-
try
527-
{
528-
if ((InvocationSettings != null) && (InvocationSettings.FlowImpersonationPolicy))
529-
{
530-
// we have a valid identity to impersonate.
531-
System.Security.Principal.WindowsIdentity identityToImPersonate =
532-
new System.Security.Principal.WindowsIdentity(InvocationSettings.WindowsIdentityToImpersonate.Token);
533-
oldImpersonationCtxt = identityToImPersonate.Impersonate();
534-
}
535-
#endif
536563
// Set up pipeline internal host if it is available.
537564
if (InvocationSettings != null && InvocationSettings.Host != null)
538565
{
@@ -575,29 +602,6 @@ private void InvokeThreadProc()
575602
// Invoke finished successfully. Set state to Completed.
576603
SetPipelineState(PipelineState.Completed);
577604
}
578-
#if !CORECLR
579-
}
580-
finally
581-
{
582-
// Impersonation is not supported in CoreCLR.
583-
// This finally block is needed to handle fxcop CA2124
584-
// If sensitive operations such as impersonation occur in the try block, and an
585-
// exception is thrown, the filter can execute before the finally block. For the
586-
// impersonation example, this means that the filter would execute as the impersonated user.
587-
if (oldImpersonationCtxt != null)
588-
{
589-
try
590-
{
591-
oldImpersonationCtxt.Undo();
592-
oldImpersonationCtxt.Dispose();
593-
oldImpersonationCtxt = null;
594-
}
595-
catch (System.Security.SecurityException)
596-
{
597-
}
598-
}
599-
}
600-
#endif
601605
}
602606
catch (PipelineStoppedException ex)
603607
{
@@ -1101,12 +1105,15 @@ private LocalRunspace LocalRunspace
11011105
}
11021106
}
11031107

1104-
// NTRAID#Windows Out Of Band Releases-925566-2005/12/09-JonN
11051108
private bool _useExternalInput;
11061109

11071110
private PipelineWriter _oldExternalErrorOutput;
11081111
private PipelineWriter _oldExternalSuccessOutput;
11091112

1113+
#if !UNIX
1114+
private WindowsIdentity _identityToImpersonate;
1115+
#endif
1116+
11101117
#endregion private_fields
11111118

11121119
#region invoke_loop_detection

0 commit comments

Comments
0 (0)
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.