diff --git a/src/System.Security.Principal.Windows/src/Configurations.props b/src/System.Security.Principal.Windows/src/Configurations.props index 54a08cdb99ed..d022d94deb57 100644 --- a/src/System.Security.Principal.Windows/src/Configurations.props +++ b/src/System.Security.Principal.Windows/src/Configurations.props @@ -5,6 +5,8 @@ netstandard; netcoreapp2.0-Windows_NT; netcoreapp2.0-Unix; + netcoreapp2.1-Windows_NT; + netcoreapp2.1-Unix; net461-Windows_NT; @@ -15,4 +17,4 @@ netfx-Windows_NT; - \ No newline at end of file + diff --git a/src/System.Security.Principal.Windows/src/PinvokeAnalyzerExceptionList.analyzerdata.netcoreapp2.1 b/src/System.Security.Principal.Windows/src/PinvokeAnalyzerExceptionList.analyzerdata.netcoreapp2.1 new file mode 100644 index 000000000000..6aad19cc39ff --- /dev/null +++ b/src/System.Security.Principal.Windows/src/PinvokeAnalyzerExceptionList.analyzerdata.netcoreapp2.1 @@ -0,0 +1 @@ +advapi32.dll!LsaNtStatusToWinError diff --git a/src/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj b/src/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj index 345d3aed719b..e0e538da06e2 100644 --- a/src/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj +++ b/src/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj @@ -6,7 +6,7 @@ true true SR.PlatformNotSupported_Principal - net461-Windows_NT-Debug;net461-Windows_NT-Release;netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;netcoreapp2.0-Unix-Debug;netcoreapp2.0-Unix-Release;netcoreapp2.0-Windows_NT-Debug;netcoreapp2.0-Windows_NT-Release;netfx-Windows_NT-Debug;netfx-Windows_NT-Release;netstandard-Debug;netstandard-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release + net461-Windows_NT-Debug;net461-Windows_NT-Release;netcoreapp-Unix-Debug;netcoreapp-Unix-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;netcoreapp2.0-Unix-Debug;netcoreapp2.0-Unix-Release;netcoreapp2.0-Windows_NT-Debug;netcoreapp2.0-Windows_NT-Release;netcoreapp2.1-Unix-Debug;netcoreapp2.1-Unix-Release;netcoreapp2.1-Windows_NT-Debug;netcoreapp2.1-Windows_NT-Release;netfx-Windows_NT-Debug;netfx-Windows_NT-Release;netstandard-Debug;netstandard-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release diff --git a/src/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs b/src/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs index 09435371977a..98f9a331fb65 100644 --- a/src/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs +++ b/src/System.Security.Principal.Windows/src/System/Security/Principal/SID.cs @@ -792,21 +792,44 @@ public override string ToString() { if (_sddlForm == null) { - StringBuilder result = new StringBuilder(); - // - // Typecasting of _IdentifierAuthority to a long below is important, since + // Typecasting of _IdentifierAuthority to a ulong below is important, since // otherwise you would see this: "S-1-NTAuthority-32-544" // - result.Append("S-1-").Append((long)_identifierAuthority); - +#if netcoreapp20 + StringBuilder result = new StringBuilder(); + result.Append("S-1-").Append((ulong)_identifierAuthority); for (int i = 0; i < SubAuthorityCount; i++) { result.Append('-').Append((uint)(_subAuthorities[i])); } - _sddlForm = result.ToString(); +#else + // length of buffer calculation + // prefix = "S-1-".Length: 4; + // authority: ulong.MaxValue.ToString("D") : 20; + // subauth = MaxSubAuthorities * ( uint.MaxValue.ToString("D").Length + '-'.Length ): 15 * (10+1): 165; + // max possible length = 4 + 20 + 165: 189 + Span result = stackalloc char[189]; + result[0] = 'S'; + result[1] = '-'; + result[2] = '1'; + result[3] = '-'; + int written; + int length = 4; + ((ulong)_identifierAuthority).TryFormat(result.Slice(length), out written); + length += written; + int[] values = _subAuthorities; + for (int index = 0; index < values.Length; index++) + { + result[length] = '-'; + length += 1; + ((uint)values[index]).TryFormat(result.Slice(length), out written); + length += written; + } + _sddlForm = result.Slice(0, length).ToString(); +#endif } return _sddlForm; @@ -910,9 +933,9 @@ public override IdentityReference Translate(Type targetType) } } - #endregion +#endregion - #region Operators +#region Operators public static bool operator ==(SecurityIdentifier left, SecurityIdentifier right) { @@ -938,9 +961,9 @@ public override IdentityReference Translate(Type targetType) return !(left == right); } - #endregion +#endregion - #region IComparable implementation +#region IComparable implementation public int CompareTo(SecurityIdentifier sid) { @@ -982,9 +1005,9 @@ public int CompareTo(SecurityIdentifier sid) return 0; } - #endregion +#endregion - #region Public Methods +#region Public Methods internal int GetSubAuthority(int index) { @@ -1220,6 +1243,6 @@ internal static IdentityReferenceCollection Translate(IdentityReferenceCollectio throw new ArgumentException(SR.IdentityReference_MustBeIdentityReference, nameof(targetType)); } - #endregion +#endregion } } diff --git a/src/System.Security.Principal.Windows/tests/SecurityIdentifierTests.cs b/src/System.Security.Principal.Windows/tests/SecurityIdentifierTests.cs new file mode 100644 index 000000000000..9ed06a03f2da --- /dev/null +++ b/src/System.Security.Principal.Windows/tests/SecurityIdentifierTests.cs @@ -0,0 +1,92 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Security.Principal; +using Xunit; + +public class SecurityIdentifierTests +{ + [Fact] + public void ValidateGetCurrentUser() + { + using (WindowsIdentity identity = WindowsIdentity.GetCurrent(false)) + { + Assert.NotNull(identity.User); + } + } + + [Fact] + public void ValidateToString() + { + string sddl = null; + using (WindowsIdentity me = WindowsIdentity.GetCurrent(false)) + { + sddl = me.User.ToString(); + } + + Assert.NotNull(sddl); + Assert.NotEmpty(sddl); + Assert.StartsWith("S-1-5-", sddl); // sid prefix, version 1, user account type + Assert.NotEqual('-', sddl[sddl.Length - 1]); + + string[] parts = sddl.Substring(6).Split('-'); + + Assert.NotNull(parts); + Assert.NotEmpty(parts); + + Assert.All(parts, part => uint.TryParse(part, out uint _)); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer), nameof(PlatformDetection.IsNotWindowsServerCore))] + public void ValidateToStringUsingWhoami() + { + string librarySid = null; + using (WindowsIdentity me = WindowsIdentity.GetCurrent(false)) + { + librarySid = me.User.ToString(); + } + + string windowsSid = null; + string processArguments = " /user"; + // Call whois to get current sid + Process whoamiProcess = new Process(); + whoamiProcess.StartInfo.FileName = "whoami.exe"; // whoami.exe is in system32, should already be on path + whoamiProcess.StartInfo.Arguments = " " + processArguments; + whoamiProcess.StartInfo.CreateNoWindow = true; + whoamiProcess.StartInfo.UseShellExecute = false; + whoamiProcess.StartInfo.RedirectStandardOutput = true; + whoamiProcess.Start(); + string output = whoamiProcess.StandardOutput.ReadToEnd(); + whoamiProcess.WaitForExit(); + + if (whoamiProcess.ExitCode == 0) + { + int startSid = output.IndexOf("S-1-5-"); + int endSid = 0; + if (startSid >= 0) + { + int length = Math.Min(output.Length - startSid, librarySid.Length); + windowsSid = output.Substring(startSid, length); + + if (output.Length > startSid + length) + { + Assert.True(char.IsWhiteSpace(output[startSid + length])); + } + } + if (endSid > startSid) + { + windowsSid = output.Substring(startSid, (endSid - startSid)); + } + } + Assert.NotNull(windowsSid); + Assert.NotEmpty(windowsSid); + Assert.NotNull(librarySid); + Assert.NotEmpty(librarySid); + + Assert.Equal(windowsSid, librarySid); + } +} + diff --git a/src/System.Security.Principal.Windows/tests/System.Security.Principal.Windows.Tests.csproj b/src/System.Security.Principal.Windows/tests/System.Security.Principal.Windows.Tests.csproj index e2b00270f274..4fd1b7cc8fc4 100644 --- a/src/System.Security.Principal.Windows/tests/System.Security.Principal.Windows.Tests.csproj +++ b/src/System.Security.Principal.Windows/tests/System.Security.Principal.Windows.Tests.csproj @@ -5,6 +5,7 @@ +