Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corefx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilip Navara <filip.navara@gmail.com>2018-06-24 07:29:39 +0300
committerMarek Safar <marek.safar@gmail.com>2018-06-25 13:09:14 +0300
commit0170839010a12396b4346a9a31a58b3b806e5bba (patch)
tree00c76bd1c4d1ee19e4938c1dfc8c370e5a012740
parentd4245e369a2edfde950c93328147adab31e48e70 (diff)
NetFX compatibility fixes for X500DistinguishedName.
* Don't write a separator after the empty DN * Make T61String behave like it does on Windows (UTF-8 with a Latin-1 fallback) * Use the managed decoder on Linux, instead of a lot of P/Invokes back into OpenSSL.
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs27
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs39
-rw-r--r--src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509NameEntry.cs61
-rw-r--r--src/Common/src/Microsoft/Win32/SafeHandles/SafeX509NameHandle.Unix.cs30
-rw-r--r--src/Common/src/System/Security/Cryptography/DerSequenceReader.cs35
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.c58
-rw-r--r--src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h63
-rw-r--r--src/System.Net.Http/src/System.Net.Http.csproj3
-rw-r--r--src/System.Net.Security/src/System.Net.Security.csproj3
-rw-r--r--src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj1
-rw-r--r--src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj1
-rw-r--r--src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs4
-rw-r--r--src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.OpenSslDecode.cs123
-rw-r--r--src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs7
-rw-r--r--src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj10
-rw-r--r--src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs69
16 files changed, 114 insertions, 420 deletions
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs
index 962eaa426f..5bd2e8b9b4 100644
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs
@@ -61,22 +61,6 @@ internal static partial class Interop
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1StringFree")]
internal static extern void Asn1StringFree(IntPtr o);
- internal static string GetOidValue(SafeSharedAsn1ObjectHandle asn1Object)
- {
- Debug.Assert(asn1Object != null);
-
- bool added = false;
- asn1Object.DangerousAddRef(ref added);
- try
- {
- return GetOidValue(asn1Object.DangerousGetHandle());
- }
- finally
- {
- asn1Object.DangerousRelease();
- }
- }
-
internal static unsafe string GetOidValue(IntPtr asn1ObjectPtr)
{
// OBJ_obj2txt returns the number of bytes that should have been in the answer, but it does not accept
@@ -127,14 +111,3 @@ internal static partial class Interop
}
}
}
-
-namespace Microsoft.Win32.SafeHandles
-{
- internal class SafeSharedAsn1ObjectHandle : SafeInteriorHandle
- {
- private SafeSharedAsn1ObjectHandle() :
- base(IntPtr.Zero, ownsHandle: true)
- {
- }
- }
-}
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs
index 0f0fecad24..70097d7db2 100644
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs
@@ -15,16 +15,6 @@ internal static partial class Interop
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameStackFieldCount")]
internal static extern int GetX509NameStackFieldCount(SafeSharedX509NameStackHandle sk);
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PushX509NameStackField")]
- [return: MarshalAs(UnmanagedType.Bool)]
- internal static extern bool PushX509NameStackField(SafeX509NameStackHandle stack, SafeX509NameHandle x509_Name);
-
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RecursiveFreeX509NameStack")]
- internal static extern void RecursiveFreeX509NameStack(IntPtr stack);
-
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_NewX509NameStack")]
- internal static extern SafeX509NameStackHandle NewX509NameStack();
-
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameStackField")]
private static extern SafeSharedX509NameHandle GetX509NameStackField_private(SafeSharedX509NameStackHandle sk,
int loc);
@@ -32,15 +22,6 @@ internal static partial class Interop
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameRawBytes")]
private static extern int GetX509NameRawBytes(SafeSharedX509NameHandle x509Name, byte[] buf, int cBuf);
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509Name")]
- internal static extern SafeX509NameHandle DecodeX509Name(byte[] buf, int len);
-
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509NameDestroy")]
- internal static extern void X509NameDestroy(IntPtr a);
-
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameEntryCount")]
- internal static extern int GetX509NameEntryCount(SafeX509NameHandle x509Name);
-
internal static X500DistinguishedName LoadX500Name(SafeSharedX509NameHandle namePtr)
{
CheckValidOpenSslHandle(namePtr);
@@ -86,25 +67,5 @@ namespace Microsoft.Win32.SafeHandles
{
}
}
-
- internal sealed class SafeX509NameStackHandle : SafeHandle
- {
- private SafeX509NameStackHandle() :
- base(IntPtr.Zero, ownsHandle: true)
- {
- }
-
- protected override bool ReleaseHandle()
- {
- Interop.Crypto.RecursiveFreeX509NameStack(handle);
- SetHandle(IntPtr.Zero);
- return true;
- }
-
- public override bool IsInvalid
- {
- get { return handle == IntPtr.Zero; }
- }
- }
}
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509NameEntry.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509NameEntry.cs
deleted file mode 100644
index eeeea54d0c..0000000000
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509NameEntry.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-// 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.Runtime.InteropServices;
-using Microsoft.Win32.SafeHandles;
-
-internal static partial class Interop
-{
- internal static partial class Crypto
- {
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameEntry")]
- private static extern SafeSharedX509NameEntryHandle GetX509NameEntry_private(SafeX509NameHandle x509Name, int loc);
-
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameEntryOid")]
- private static extern SafeSharedAsn1ObjectHandle GetX509NameEntryOid_private(SafeSharedX509NameEntryHandle nameEntry);
-
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameEntryData")]
- private static extern SafeSharedAsn1StringHandle GetX509NameEntryData_private(SafeSharedX509NameEntryHandle nameEntry);
-
- internal static SafeSharedX509NameEntryHandle GetX509NameEntry(SafeX509NameHandle x509Name, int loc)
- {
- CheckValidOpenSslHandle(x509Name);
-
- return SafeInteriorHandle.OpenInteriorHandle(
- (nameHandle, i) => GetX509NameEntry_private(nameHandle, i),
- x509Name,
- loc);
- }
-
- internal static SafeSharedAsn1ObjectHandle GetX509NameEntryOid(SafeSharedX509NameEntryHandle nameEntry)
- {
- CheckValidOpenSslHandle(nameEntry);
-
- return SafeInteriorHandle.OpenInteriorHandle(
- handle => GetX509NameEntryOid_private(handle),
- nameEntry);
- }
-
- internal static SafeSharedAsn1StringHandle GetX509NameEntryData(SafeSharedX509NameEntryHandle nameEntry)
- {
- CheckValidOpenSslHandle(nameEntry);
-
- return SafeInteriorHandle.OpenInteriorHandle(
- handle => GetX509NameEntryData_private(handle),
- nameEntry);
- }
- }
-}
-
-namespace Microsoft.Win32.SafeHandles
-{
- internal sealed class SafeSharedX509NameEntryHandle : SafeInteriorHandle
- {
- private SafeSharedX509NameEntryHandle() :
- base(IntPtr.Zero, ownsHandle: true)
- {
- }
- }
-}
diff --git a/src/Common/src/Microsoft/Win32/SafeHandles/SafeX509NameHandle.Unix.cs b/src/Common/src/Microsoft/Win32/SafeHandles/SafeX509NameHandle.Unix.cs
deleted file mode 100644
index ae22b92303..0000000000
--- a/src/Common/src/Microsoft/Win32/SafeHandles/SafeX509NameHandle.Unix.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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.Security;
-using System.Runtime.InteropServices;
-
-namespace Microsoft.Win32.SafeHandles
-{
- internal sealed class SafeX509NameHandle : SafeHandle
- {
- private SafeX509NameHandle() :
- base(IntPtr.Zero, ownsHandle: true)
- {
- }
-
- protected override bool ReleaseHandle()
- {
- Interop.Crypto.X509NameDestroy(handle);
- SetHandle(IntPtr.Zero);
- return true;
- }
-
- public override bool IsInvalid
- {
- get { return handle == IntPtr.Zero; }
- }
- }
-}
diff --git a/src/Common/src/System/Security/Cryptography/DerSequenceReader.cs b/src/Common/src/System/Security/Cryptography/DerSequenceReader.cs
index b68c9da093..68d9ac1bd2 100644
--- a/src/Common/src/System/Security/Cryptography/DerSequenceReader.cs
+++ b/src/Common/src/System/Security/Cryptography/DerSequenceReader.cs
@@ -30,6 +30,9 @@ namespace System.Security.Cryptography
internal static DateTimeFormatInfo s_validityDateTimeFormatInfo;
+ private static System.Text.Encoding s_utf8EncodingWithExceptionFallback;
+ private static System.Text.Encoding s_latin1Encoding;
+
private readonly byte[] _data;
private readonly int _end;
private int _position;
@@ -383,6 +386,38 @@ namespace System.Security.Cryptography
return TrimTrailingNulls(ia5String);
}
+ internal string ReadT61String()
+ {
+ EatTag(DerTag.T61String);
+ int contentLength = EatLength();
+ string t61String;
+
+ // Technically the T.61 encoding (code page 20261) should be used here, but many
+ // implementations don't follow that and use different character sets. CryptoAPI
+ // on NetFX seems to interpret it as UTF-8 with fallback to ISO 8859-1. OpenSSL
+ // seems to interpret it as ISO 8859-1 with no support for UTF-8.
+ // https://github.com/dotnet/corefx/issues/27466
+
+ System.Text.Encoding utf8EncodingWithExceptionFallback = LazyInitializer.EnsureInitialized(
+ ref s_utf8EncodingWithExceptionFallback,
+ () => new UTF8Encoding(false, true));
+ System.Text.Encoding latin1Encoding = LazyInitializer.EnsureInitialized(
+ ref s_latin1Encoding,
+ () => System.Text.Encoding.GetEncoding("iso-8859-1"));
+
+ try
+ {
+ t61String = utf8EncodingWithExceptionFallback.GetString(_data, _position, contentLength);
+ }
+ catch (DecoderFallbackException)
+ {
+ t61String = latin1Encoding.GetString(_data, _position, contentLength);
+ }
+ _position += contentLength;
+
+ return TrimTrailingNulls(t61String);
+ }
+
internal DateTime ReadX509Date()
{
byte tag = PeekTag();
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.c b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.c
index ee77a5df03..8cb1485467 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.c
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.c
@@ -13,61 +13,3 @@ X509_NAME* CryptoNative_GetX509NameStackField(X509NameStack* sk, int32_t loc)
{
return sk_X509_NAME_value(sk, loc);
}
-
-X509_NAME* CryptoNative_DecodeX509Name(const uint8_t* buf, int32_t len)
-{
- if (!buf || !len)
- {
- return NULL;
- }
-
- return d2i_X509_NAME(NULL, &buf, len);
-}
-
-void CryptoNative_X509NameDestroy(X509_NAME* a)
-{
- if (a != NULL)
- {
- X509_NAME_free(a);
- }
-}
-
-STACK_OF(X509_NAME) * CryptoNative_NewX509NameStack()
-{
- return sk_X509_NAME_new_null();
-}
-
-int32_t CryptoNative_PushX509NameStackField(STACK_OF(X509_NAME) * stack, X509_NAME* x509Name)
-{
- if (!stack)
- {
- return 0;
- }
-
- return sk_X509_NAME_push(stack, x509Name);
-}
-
-void CryptoNative_RecursiveFreeX509NameStack(STACK_OF(X509_NAME) * stack)
-{
- sk_X509_NAME_pop_free(stack, X509_NAME_free);
-}
-
-int32_t CryptoNative_GetX509NameEntryCount(X509_NAME* x509Name)
-{
- return X509_NAME_entry_count(x509Name);
-}
-
-X509_NAME_ENTRY* CryptoNative_GetX509NameEntry(X509_NAME* x509Name, int32_t loc)
-{
- return X509_NAME_get_entry(x509Name, loc);
-}
-
-ASN1_OBJECT* CryptoNative_GetX509NameEntryOid(X509_NAME_ENTRY* nameEntry)
-{
- return X509_NAME_ENTRY_get_object(nameEntry);
-}
-
-ASN1_STRING* CryptoNative_GetX509NameEntryData(X509_NAME_ENTRY* nameEntry)
-{
- return X509_NAME_ENTRY_get_data(nameEntry);
-}
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h
index 52231e85fb..a24fdef4f2 100644
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_x509_name.h
@@ -18,66 +18,3 @@ DLLEXPORT int32_t CryptoNative_GetX509NameStackFieldCount(X509NameStack* sk);
Direct shim to sk_X509_NAME_value
*/
DLLEXPORT X509_NAME* CryptoNative_GetX509NameStackField(X509NameStack* sk, int32_t loc);
-
-/*
-Shims the d2i_X509_NAME method and makes it easier to invoke from managed code.
-*/
-DLLEXPORT X509_NAME* CryptoNative_DecodeX509Name(const uint8_t* buf, int32_t len);
-
-/*
-Cleans up and deletes an X509_NAME instance.
-
-Implemented by calling X509_NAME_free.
-
-No-op if a is null.
-The given X509_NAME pointer is invalid after this call.
-Always succeeds.
-*/
-DLLEXPORT void CryptoNative_X509NameDestroy(X509_NAME* a);
-
-/*
-Function:
-NewX509NameStack
-
-Direct shim to sk_X509_NAME_new_null
-*/
-DLLEXPORT STACK_OF(X509_NAME) * CryptoNative_NewX509NameStack(void);
-
-/*
-Function:
-PushX509NameStackField
-
-Direct shim to sk_X509_NAME_push
-Return values:
-1 on success
-0 on a NULL stack, or an error within sk_X509_NAME_push
-*/
-DLLEXPORT int32_t CryptoNative_PushX509NameStackField(STACK_OF(X509_NAME) * stack, X509_NAME* x509Name);
-
-/*
-Function:
-RecursiveFreeX509NameStack
-
-Direct shim to sk_X509_NAME_pop_free
-*/
-DLLEXPORT void CryptoNative_RecursiveFreeX509NameStack(STACK_OF(X509_NAME) * stack);
-
-/*
-Direct shim to X509_NAME_entry_count
-*/
-DLLEXPORT int32_t CryptoNative_GetX509NameEntryCount(X509_NAME* x509Name);
-
-/*
-Direct shim to X509_NAME_get_entry
-*/
-DLLEXPORT X509_NAME_ENTRY* CryptoNative_GetX509NameEntry(X509_NAME* x509Name, int32_t loc);
-
-/*
-Direct shim to X509_NAME_ENTRY_get_object
-*/
-DLLEXPORT ASN1_OBJECT* CryptoNative_GetX509NameEntryOid(X509_NAME_ENTRY* nameEntry);
-
-/*
-Direct shim to X509_NAME_ENTRY_get_data
-*/
-DLLEXPORT ASN1_STRING* CryptoNative_GetX509NameEntryData(X509_NAME_ENTRY* nameEntry);
diff --git a/src/System.Net.Http/src/System.Net.Http.csproj b/src/System.Net.Http/src/System.Net.Http.csproj
index 056aac2572..416e515ce9 100644
--- a/src/System.Net.Http/src/System.Net.Http.csproj
+++ b/src/System.Net.Http/src/System.Net.Http.csproj
@@ -530,9 +530,6 @@
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs">
<Link>Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs">
- <Link>Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs">
<Link>Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs</Link>
</Compile>
diff --git a/src/System.Net.Security/src/System.Net.Security.csproj b/src/System.Net.Security/src/System.Net.Security.csproj
index 9dff20160e..bf8d773a4e 100644
--- a/src/System.Net.Security/src/System.Net.Security.csproj
+++ b/src/System.Net.Security/src/System.Net.Security.csproj
@@ -328,9 +328,6 @@
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs">
<Link>Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs">
- <Link>Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs">
<Link>Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs</Link>
</Compile>
diff --git a/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj b/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj
index 9681ef62e4..388d4f36a6 100644
--- a/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj
+++ b/src/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj
@@ -106,6 +106,7 @@
<Reference Include="System.Runtime.Extensions" />
<Reference Include="System.Runtime.InteropServices" />
<Reference Include="System.Security.Cryptography.Primitives" />
+ <Reference Include="System.Text.Encoding.Extensions" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetsOSX)' == 'true' ">
<Reference Include="System.Runtime.Numerics" />
diff --git a/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj b/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj
index 095d62bc6d..3846bcad23 100644
--- a/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj
+++ b/src/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj
@@ -160,6 +160,7 @@
<Reference Include="System.Security.Cryptography.Algorithms" />
<Reference Include="System.Security.Cryptography.Encoding" />
<Reference Include="System.Security.Cryptography.Primitives" />
+ <Reference Include="System.Text.Encoding.Extensions" />
<Reference Include="System.Threading" />
</ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs
index 094e95c20d..0285415ba3 100644
--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs
+++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.ManagedDecode.cs
@@ -127,7 +127,7 @@ namespace Internal.Cryptography.Pal
}
}
- if (addTrailingDelimiter)
+ if (addTrailingDelimiter && decodedName.Length > 0)
{
decodedName.Append(dnSeparator);
}
@@ -150,7 +150,7 @@ namespace Internal.Cryptography.Pal
case DerSequenceReader.DerTag.UTF8String:
return tavReader.ReadUtf8String();
case DerSequenceReader.DerTag.T61String:
- return "";
+ return tavReader.ReadT61String();
default:
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}
diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.OpenSslDecode.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.OpenSslDecode.cs
deleted file mode 100644
index 0c03283475..0000000000
--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.OpenSslDecode.cs
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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.Text;
-
-using Microsoft.Win32.SafeHandles;
-
-namespace Internal.Cryptography.Pal
-{
- internal static partial class X500NameEncoder
- {
- private static string X500DistinguishedNameDecode(
- byte[] encodedName,
- bool printOid,
- bool reverse,
- bool quoteIfNeeded,
- string dnSeparator,
- string multiValueSeparator,
- bool addTrailingDelimiter)
- {
- using (SafeX509NameHandle x509Name = Interop.Crypto.DecodeX509Name(encodedName, encodedName.Length))
- {
- if (x509Name.IsInvalid)
- {
- Interop.Crypto.ErrClearError();
- return "";
- }
-
- // We need to allocate a StringBuilder to hold the data as we're building it, and there's the usual
- // arbitrary process of choosing a number that's "big enough" to minimize reallocations without wasting
- // too much space in the average case.
- //
- // So, let's look at an example of what our output might be.
- //
- // GitHub.com's SSL cert has a "pretty long" subject (partially due to the unknown OIDs):
- // businessCategory=Private Organization
- // 1.3.6.1.4.1.311.60.2.1.3=US
- // 1.3.6.1.4.1.311.60.2.1.2=Delaware
- // serialNumber=5157550
- // street=548 4th Street
- // postalCode=94107
- // C=US
- // ST=California
- // L=San Francisco
- // O=GitHub, Inc.
- // CN=github.com
- //
- // Which comes out to 228 characters using OpenSSL's default pretty-print
- // (openssl x509 -in github.cer -text -noout)
- // Throw in some "maybe-I-need-to-quote-this" quotes, and a couple of extra/extra-long O/OU values
- // and round that up to the next programmer number, and you get that 512 should avoid reallocations
- // in all but the most dire of cases.
- StringBuilder decodedName = new StringBuilder(512);
- int entryCount = Interop.Crypto.GetX509NameEntryCount(x509Name);
- bool printSpacing = false;
-
- for (int i = 0; i < entryCount; i++)
- {
- int loc = reverse ? entryCount - i - 1 : i;
-
- using (SafeSharedX509NameEntryHandle nameEntry = Interop.Crypto.GetX509NameEntry(x509Name, loc))
- {
- Interop.Crypto.CheckValidOpenSslHandle(nameEntry);
-
- string thisOidValue;
-
- using (SafeSharedAsn1ObjectHandle oidHandle = Interop.Crypto.GetX509NameEntryOid(nameEntry))
- {
- thisOidValue = Interop.Crypto.GetOidValue(oidHandle);
- }
-
- if (printSpacing)
- {
- decodedName.Append(dnSeparator);
- }
- else
- {
- printSpacing = true;
- }
-
- if (printOid)
- {
- AppendOid(decodedName, thisOidValue);
- }
-
- string rdnValue;
-
- using (SafeSharedAsn1StringHandle valueHandle = Interop.Crypto.GetX509NameEntryData(nameEntry))
- {
- rdnValue = Interop.Crypto.Asn1StringToManagedString(valueHandle);
- }
-
- bool quote = quoteIfNeeded && NeedsQuoting(rdnValue);
-
- if (quote)
- {
- decodedName.Append('"');
-
- // If the RDN itself had a quote within it, that quote needs to be escaped
- // with another quote.
- rdnValue = rdnValue.Replace("\"", "\"\"");
- }
-
- decodedName.Append(rdnValue);
-
- if (quote)
- {
- decodedName.Append('"');
- }
- }
- }
-
- if (addTrailingDelimiter)
- {
- decodedName.Append(dnSeparator);
- }
-
- return decodedName.ToString();
- }
- }
- }
-}
diff --git a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs
index 56da9ae40c..005e09abe3 100644
--- a/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs
+++ b/src/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs
@@ -40,7 +40,7 @@ namespace Internal.Cryptography.Pal
byte[] encodedName,
bool printOid,
X500DistinguishedNameFlags flags,
- bool addTrailingDelimieter=false)
+ bool addTrailingDelimiter = false)
{
bool reverse = (flags & X500DistinguishedNameFlags.Reversed) == X500DistinguishedNameFlags.Reversed;
bool quoteIfNeeded = (flags & X500DistinguishedNameFlags.DoNotUseQuotes) != X500DistinguishedNameFlags.DoNotUseQuotes;
@@ -51,7 +51,8 @@ namespace Internal.Cryptography.Pal
{
dnSeparator = "; ";
}
- else if ((flags & X500DistinguishedNameFlags.UseNewLines) == X500DistinguishedNameFlags.UseNewLines)
+ // Explicit UseCommas has preference over explicit UseNewLines.
+ else if ((flags & (X500DistinguishedNameFlags.UseNewLines | X500DistinguishedNameFlags.UseCommas)) == X500DistinguishedNameFlags.UseNewLines)
{
dnSeparator = Environment.NewLine;
}
@@ -73,7 +74,7 @@ namespace Internal.Cryptography.Pal
quoteIfNeeded,
dnSeparator,
multiValueSparator,
- addTrailingDelimieter);
+ addTrailingDelimiter);
}
catch (CryptographicException)
{
diff --git a/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj b/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj
index 510a792488..061c2729a1 100644
--- a/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj
+++ b/src/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj
@@ -169,7 +169,6 @@
<Compile Include="Internal\Cryptography\Pal.Unix\PkcsFormatReader.cs" />
<Compile Include="Internal\Cryptography\Pal.Unix\SingleCertLoader.cs" />
<Compile Include="Internal\Cryptography\Pal.Unix\StorePal.cs" />
- <Compile Include="Internal\Cryptography\Pal.Unix\X500NameEncoder.OpenSslDecode.cs" />
<Compile Include="Internal\Cryptography\Pal.Unix\X509Pal.cs" />
<Compile Include="Internal\Cryptography\Pal.Unix\X509Persistence.cs" />
<Compile Include="$(CommonPath)\Interop\Unix\Interop.Libraries.cs">
@@ -229,9 +228,6 @@
<Compile Include="$(CommonPath)\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Name.cs">
<Link>Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Name.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Interop\Unix\System.Security.Cryptography.Native\Interop.X509NameEntry.cs">
- <Link>Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509NameEntry.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Stack.cs">
<Link>Common\Interop\Unix\System.Security.Cryptography.Native\Interop.X509Stack.cs</Link>
</Compile>
@@ -286,9 +282,6 @@
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs">
<Link>Common\Microsoft\Win32\SafeHandles\SafeX509Handles.Unix.cs</Link>
</Compile>
- <Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs">
- <Link>Common\Microsoft\Win32\SafeHandles\SafeX509NameHandle.Unix.cs</Link>
- </Compile>
<Compile Include="$(CommonPath)\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs">
<Link>Common\Microsoft\Win32\SafeHandles\X509ExtensionSafeHandles.Unix.cs</Link>
</Compile>
@@ -402,7 +395,6 @@
<Compile Include="Internal\Cryptography\Pal.OSX\StorePal.ExportPal.cs" />
<Compile Include="Internal\Cryptography\Pal.OSX\StorePal.LoaderPal.cs" />
<Compile Include="Internal\Cryptography\Pal.OSX\X509Pal.cs" />
- <Compile Include="Internal\Cryptography\Pal.Unix\X500NameEncoder.ManagedDecode.cs" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetsUnix)' == 'true'">
<Compile Include="Internal\Cryptography\Pal.Unix\CertificatePolicy.cs" />
@@ -410,6 +402,7 @@
<Compile Include="Internal\Cryptography\Pal.Unix\ManagedCertificateFinder.cs" />
<Compile Include="Internal\Cryptography\Pal.Unix\ManagedX509ExtensionProcessor.cs" />
<Compile Include="Internal\Cryptography\Pal.Unix\X500NameEncoder.cs" />
+ <Compile Include="Internal\Cryptography\Pal.Unix\X500NameEncoder.ManagedDecode.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.Buffers" />
@@ -429,6 +422,7 @@
<Reference Include="System.Security.Cryptography.Algorithms" />
<Reference Include="System.Security.Cryptography.Encoding" />
<Reference Include="System.Security.Cryptography.Primitives" />
+ <Reference Include="System.Text.Encoding.Extensions" />
<Reference Include="System.Threading" />
</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
diff --git a/src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs b/src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs
index 027823ffbd..95ac1ed519 100644
--- a/src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs
+++ b/src/System.Security.Cryptography.X509Certificates/tests/X500DistinguishedNameTests.cs
@@ -126,6 +126,16 @@ namespace System.Security.Cryptography.X509Certificates.Tests
Assert.Equal(notQuoted, dn.Decode(X500DistinguishedNameFlags.DoNotUseQuotes));
}
+
+ [Theory]
+ [MemberData(nameof(T61Cases))]
+ public static void T61Strings(string expected, string hexEncoded)
+ {
+ byte[] encoded = hexEncoded.HexToByteArray();
+ X500DistinguishedName dn = new X500DistinguishedName(encoded);
+
+ Assert.Equal(expected, dn.Name);
+ }
[Fact]
public static void PrintComplexReversed()
@@ -158,6 +168,22 @@ namespace System.Security.Cryptography.X509Certificates.Tests
Assert.EndsWith(expected, dn.Decode(X500DistinguishedNameFlags.None), StringComparison.Ordinal);
}
+ [Fact]
+ public static void EdgeCaseEmptyFormat()
+ {
+ X500DistinguishedName dn = new X500DistinguishedName("");
+ Assert.Equal(String.Empty, dn.Format(true));
+ Assert.Equal(String.Empty, dn.Format(false));
+ }
+
+ [Fact]
+ public static void EdgeCaseUseCommaAndNewLines()
+ {
+ const string rname = "C=US, O=\"RSA Data Security, Inc.\", OU=Secure Server Certification Authority";
+ X500DistinguishedName dn = new X500DistinguishedName(rname, X500DistinguishedNameFlags.None);
+ Assert.Equal(rname, dn.Decode(X500DistinguishedNameFlags.UseCommas | X500DistinguishedNameFlags.UseNewLines));
+ }
+
public static readonly object[][] WhitespaceBeforeCases =
{
// Regular space.
@@ -386,6 +412,49 @@ namespace System.Security.Cryptography.X509Certificates.Tests
},
};
+ public static readonly object[][] T61Cases =
+ {
+ // https://github.com/dotnet/corefx/issues/27466
+ new object[]
+ {
+ "CN=GrapeCity inc., OU=Tools Development, O=GrapeCity inc., " +
+ "L=Sendai Izumi-ku, S=Miyagi, C=JP",
+ "308186310b3009060355040613024a50310f300d060355040813064d69796167" +
+ "69311830160603550407130f53656e64616920497a756d692d6b753117301506" +
+ "0355040a140e47726170654369747920696e632e311a3018060355040b141154" +
+ "6f6f6c7320446576656c6f706d656e74311730150603550403140e4772617065" +
+ "4369747920696e632e"
+ },
+
+ // Mono test case taken from old bug report
+ new object[]
+ {
+ "SERIALNUMBER=CVR:13471967-UID:121212121212, E=vhm@use.test.dk, " +
+ "CN=Hedeby's M\u00f8belhandel - Salgsafdelingen, " +
+ "O=Hedeby's M\u00f8belhandel // CVR:13471967, C=DK",
+ "3081B5310B300906035504061302444B312D302B060355040A14244865646562" +
+ "792773204DF862656C68616E64656C202F2F204356523A313334373139363731" +
+ "2F302D060355040314264865646562792773204DF862656C68616E64656C202D" +
+ "2053616C6773616664656C696E67656E311E301C06092A864886F70D01090116" +
+ "0F76686D407573652E746573742E646B312630240603550405131D4356523A31" +
+ "333437313936372D5549443A313231323132313231323132"
+ },
+
+ // Valid UTF-8 string is interpreted as UTF-8
+ new object[]
+ {
+ "C=\u00a2",
+ "300D310B300906035504061402C2A2"
+ },
+
+ // Invalid UTF-8 string with valid UTF-8 sequence is interpreted as ISO 8859-1
+ new object[]
+ {
+ "L=\u00c2\u00a2\u00f8",
+ "300E310C300A06035504071403C2A2F8"
+ },
+ };
+
private const string MicrosoftDotComSubject =
"3082010F31133011060B2B0601040182373C02010313025553311B3019060B2B" +
"0601040182373C0201020C0A57617368696E67746F6E311D301B060355040F13" +