forked from dotnet/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extend ProcessStartInfo to allow setting LOGON_NETCREDENTIALS_ONLY (d…
…otnet#77637) Co-authored-by: Adam Sitnik <[email protected]>
- Loading branch information
1 parent
f3e2260
commit 88868b7
Showing
13 changed files
with
381 additions
and
135 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
118 changes: 118 additions & 0 deletions
118
src/libraries/Common/tests/TestUtilities/System/WindowsTestFileShare.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Runtime.InteropServices; | ||
using System.ServiceProcess; | ||
|
||
namespace System | ||
{ | ||
public sealed partial class WindowsTestFileShare : IDisposable | ||
{ | ||
private static readonly Lazy<bool> _canShareFiles = new Lazy<bool>(() => | ||
{ | ||
if (!PlatformDetection.IsWindows || !PlatformDetection.IsPrivilegedProcess) | ||
{ | ||
return false; | ||
} | ||
try | ||
{ | ||
// the "Server Service" allows for file sharing. It can be disabled on some machines. | ||
using (ServiceController sharingService = new ServiceController("Server")) | ||
{ | ||
return sharingService.Status == ServiceControllerStatus.Running; | ||
} | ||
} | ||
catch (InvalidOperationException) | ||
{ | ||
// The service is not installed. | ||
return false; | ||
} | ||
}); | ||
|
||
private readonly string _shareName; | ||
|
||
private readonly string _path; | ||
|
||
private bool _disposedValue; | ||
|
||
public WindowsTestFileShare(string shareName, string path) | ||
{ | ||
_shareName = shareName; | ||
_path = path; | ||
Initialize(); | ||
} | ||
|
||
public static bool CanShareFiles => _canShareFiles.Value; | ||
|
||
private void Initialize() | ||
{ | ||
SHARE_INFO_502 shareInfo = default; | ||
shareInfo.shi502_netname = _shareName; | ||
shareInfo.shi502_path = _path; | ||
shareInfo.shi502_remark = "folder created to test UNC file paths"; | ||
shareInfo.shi502_max_uses = -1; | ||
|
||
int infoSize = Marshal.SizeOf(shareInfo); | ||
IntPtr infoBuffer = Marshal.AllocCoTaskMem(infoSize); | ||
|
||
try | ||
{ | ||
Marshal.StructureToPtr(shareInfo, infoBuffer, false); | ||
|
||
const int NERR_DuplicateShare = 2118; | ||
int shareResult = NetShareAdd(string.Empty, 502, infoBuffer, IntPtr.Zero); | ||
if (shareResult == NERR_DuplicateShare) | ||
{ | ||
NetShareDel(string.Empty, _shareName, 0); | ||
shareResult = NetShareAdd(string.Empty, 502, infoBuffer, IntPtr.Zero); | ||
} | ||
|
||
if (shareResult != 0 && shareResult != NERR_DuplicateShare) | ||
{ | ||
throw new Exception($"Failed to create a file share, NetShareAdd returned {shareResult}"); | ||
} | ||
} | ||
finally | ||
{ | ||
Marshal.FreeCoTaskMem(infoBuffer); | ||
} | ||
} | ||
|
||
[LibraryImport(Interop.Libraries.Netapi32)] | ||
private static partial int NetShareAdd([MarshalAs(UnmanagedType.LPWStr)] string servername, int level, IntPtr buf, IntPtr parm_err); | ||
|
||
[LibraryImport(Interop.Libraries.Netapi32)] | ||
private static partial int NetShareDel([MarshalAs(UnmanagedType.LPWStr)] string servername, [MarshalAs(UnmanagedType.LPWStr)] string netname, int reserved); | ||
|
||
public void Dispose() | ||
{ | ||
if (_disposedValue) | ||
{ | ||
return; | ||
} | ||
|
||
NetShareDel(string.Empty, _shareName, 0); | ||
_disposedValue = true; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct SHARE_INFO_502 | ||
{ | ||
[MarshalAs(UnmanagedType.LPWStr)] | ||
public string shi502_netname; | ||
public uint shi502_type; | ||
[MarshalAs(UnmanagedType.LPWStr)] | ||
public string shi502_remark; | ||
public int shi502_permissions; | ||
public int shi502_max_uses; | ||
public int shi502_current_uses; | ||
[MarshalAs(UnmanagedType.LPWStr)] | ||
public string shi502_path; | ||
public IntPtr shi502_passwd; | ||
public int shi502_reserved; | ||
public IntPtr shi502_security_descriptor; | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
72 changes: 72 additions & 0 deletions
72
src/libraries/System.Diagnostics.Process/tests/ProcessStartInfoTests.Windows.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.IO; | ||
using System.Security; | ||
using Microsoft.DotNet.RemoteExecutor; | ||
using Xunit; | ||
|
||
namespace System.Diagnostics.Tests | ||
{ | ||
partial class ProcessStartInfoTests : ProcessTestBase | ||
{ | ||
private static bool IsAdmin_IsNotNano_RemoteExecutorIsSupported_CanShareFiles | ||
=> IsAdmin_IsNotNano_RemoteExecutorIsSupported && WindowsTestFileShare.CanShareFiles; | ||
|
||
[ConditionalFact(nameof(IsAdmin_IsNotNano_RemoteExecutorIsSupported_CanShareFiles))] // Nano has no "netapi32.dll", Admin rights are required | ||
[PlatformSpecific(TestPlatforms.Windows)] | ||
[OuterLoop("Requires admin privileges")] | ||
public void TestUserNetworkCredentialsPropertiesOnWindows() | ||
{ | ||
const string ShareName = "testForDotNet"; | ||
const string TestFileContent = "42"; | ||
const string UncPathEnvVar = nameof(UncPathEnvVar); | ||
|
||
string testFilePath = GetTestFilePath(); | ||
File.WriteAllText(testFilePath, TestFileContent); | ||
|
||
using WindowsTestFileShare fileShare = new WindowsTestFileShare(ShareName, Path.GetDirectoryName(testFilePath)); | ||
string testFileUncPath = $"\\\\{Environment.MachineName}\\{ShareName}\\{Path.GetFileName(testFilePath)}"; | ||
|
||
using Process process = CreateProcess(() => | ||
{ | ||
try | ||
{ | ||
Assert.Equal(TestFileContent, File.ReadAllText(Environment.GetEnvironmentVariable(UncPathEnvVar))); | ||
return RemoteExecutor.SuccessExitCode; | ||
} | ||
catch (Exception ex) when (ex is SecurityException or UnauthorizedAccessException) | ||
{ | ||
return -1; | ||
} | ||
}); | ||
process.StartInfo.Environment[UncPathEnvVar] = testFileUncPath; | ||
process.StartInfo.UseCredentialsForNetworkingOnly = true; | ||
|
||
using TestProcessState processInfo = CreateUserAndExecute(process, Setup, Cleanup); | ||
|
||
Assert.Equal(Environment.UserName, Helpers.GetProcessUserName(process)); | ||
|
||
Assert.True(process.WaitForExit(WaitInMS)); | ||
Assert.Equal(RemoteExecutor.SuccessExitCode, process.ExitCode); | ||
|
||
void Setup(string username, string _) | ||
{ | ||
if (PlatformDetection.IsNotWindowsServerCore) // for this particular Windows version it fails with Attempted to perform an unauthorized operation (#46619) | ||
{ | ||
SetAccessControl(username, testFilePath, Path.GetDirectoryName(testFilePath), add: true); | ||
} | ||
} | ||
|
||
void Cleanup(string username, string _) | ||
{ | ||
if (PlatformDetection.IsNotWindowsServerCore) | ||
{ | ||
// remove the access | ||
SetAccessControl(username, testFilePath, Path.GetDirectoryName(testFilePath), add: false); | ||
} | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.