diff --git a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildItem.cs b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildItem.cs index f663120bf7..82af83b152 100644 --- a/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildItem.cs +++ b/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildItem.cs @@ -226,6 +226,14 @@ namespace Microsoft.Build.BuildEngine { public void SetMetadata (string metadataName, string metadataValue, bool treatMetadataValueAsLiteral) + { + SetMetadata (metadataName, metadataValue, treatMetadataValueAsLiteral, false); + } + + void SetMetadata (string metadataName, + string metadataValue, + bool treatMetadataValueAsLiteral, + bool fromDynamicItem) { if (metadataName == null) throw new ArgumentNullException ("metadataName"); @@ -251,9 +259,11 @@ namespace Microsoft.Build.BuildEngine { } else if (HasParentItem) { if (parent_item.child_items.Count > 1) SplitParentItem (); - parent_item.SetMetadata (metadataName, metadataValue, treatMetadataValueAsLiteral); + parent_item.SetMetadata (metadataName, metadataValue, treatMetadataValueAsLiteral, fromDynamicItem); } - if (FromXml || HasParentItem) { + + // We don't want to reevalute the project for dynamic items + if (!fromDynamicItem && !IsDynamic && (FromXml || HasParentItem)) { parent_item_group.ParentProject.MarkProjectAsDirty (); parent_item_group.ParentProject.NeedToReevaluate (); } @@ -374,7 +384,7 @@ namespace Microsoft.Build.BuildEngine { continue; foreach (string name in evaluatedMetadata.Keys) { - item.SetMetadata (name, (string)evaluatedMetadata [name]); + item.SetMetadata (name, (string)evaluatedMetadata [name], false, IsDynamic); } AddAndRemoveMetadata (project, item); diff --git a/mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs b/mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs index 6c7919e6ae..c709615d25 100644 --- a/mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs +++ b/mcs/class/Microsoft.Build.Engine/Test/Microsoft.Build.BuildEngine/TargetTest.cs @@ -697,6 +697,33 @@ namespace MonoTests.Microsoft.Build.BuildEngine { ", "D"); } + [Test] + public void ItemGroupInsideTarget_UpdateMetadata () + { + ItemGroupInsideTarget ( + @" + + + + + + + + + A=b + + + + + + + + Bar01 + + + ", 2, "Before: Bar01", "After: Bar01"); + } + [Test] public void ItemGroupInsideTarget_Batching () { diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs index cc2ab66960..e4817ee4be 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs @@ -430,6 +430,7 @@ public class Tests : TestsBase, ITest2 ss_recursive2 (1); ss_recursive_chaotic (); ss_fp_clobber (); + ss_no_frames (); } [MethodImplAttribute (MethodImplOptions.NoInlining)] @@ -679,6 +680,25 @@ public class Tests : TestsBase, ITest2 public static void ss_fp_clobber_2 (double d) { } + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_no_frames () { + Action a = ss_no_frames_2; + var ar = a.BeginInvoke (null, null); + ar.AsyncWaitHandle.WaitOne (); + // Avoid waiting every time this runs + if (static_i == 56) + Thread.Sleep (200); + ss_no_frames_3 (); + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_no_frames_2 () { + } + + [MethodImplAttribute (MethodImplOptions.NoInlining)] + public static void ss_no_frames_3 () { + } + [MethodImplAttribute (MethodImplOptions.NoInlining)] public static bool is_even (int i) { return i % 2 == 0; diff --git a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs.REMOVED.git-id b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs.REMOVED.git-id index 61183f89b1..8fe451930e 100644 --- a/mcs/class/Mono.Debugger.Soft/Test/dtest.cs.REMOVED.git-id +++ b/mcs/class/Mono.Debugger.Soft/Test/dtest.cs.REMOVED.git-id @@ -1 +1 @@ -1933fc5e827372129731655297986401622ff064 \ No newline at end of file +8f929048d1b17809b27dc30940c81b379f1ec129 \ No newline at end of file diff --git a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageFault.cs b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageFault.cs index e8e1053358..8527e5c313 100644 --- a/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageFault.cs +++ b/mcs/class/System.ServiceModel/System.ServiceModel.Channels/MessageFault.cs @@ -53,7 +53,7 @@ namespace System.ServiceModel.Channels { FaultCode fc = null; FaultReason fr = null; - object details = null; + string actor = null; XmlDictionaryReader r = message.GetReaderAtBodyContents (); r.ReadStartElement ("Fault", message.Version.Envelope.Namespace); r.MoveToContent (); @@ -66,11 +66,13 @@ namespace System.ServiceModel.Channels case "faultstring": fr = new FaultReason (r.ReadElementContentAsString()); break; - case "detail": - return new XmlReaderDetailMessageFault (message, r, fc, fr, null, null); case "faultactor": + actor = r.ReadElementContentAsString(); + break; + case "detail": + return new XmlReaderDetailMessageFault (message, r, fc, fr, actor, null); default: - throw new NotImplementedException (); + throw new XmlException (String.Format ("Unexpected node {0} name {1}", r.NodeType, r.Name)); } r.MoveToContent (); } @@ -79,9 +81,7 @@ namespace System.ServiceModel.Channels if (fr == null) throw new XmlException ("Reason is missing in the Fault message"); - if (details == null) - return CreateFault (fc, fr); - return CreateFault (fc, fr, details); + return new SimpleMessageFault (fc, fr, false, null, null, actor, null); } static MessageFault CreateFault12 (Message message, int maxBufferSize) diff --git a/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/MessageFaultTest.cs b/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/MessageFaultTest.cs index eae3d7ca74..5c73c05932 100644 --- a/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/MessageFaultTest.cs +++ b/mcs/class/System.ServiceModel/Test/System.ServiceModel.Channels/MessageFaultTest.cs @@ -71,6 +71,7 @@ namespace MonoTests.System.ServiceModel.Channels a:ActionNotSupported some error + Random "; diff --git a/mcs/class/System.XML/System.Xml.Serialization/TypeData.cs b/mcs/class/System.XML/System.Xml.Serialization/TypeData.cs index f32bb39e09..55de52a778 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/TypeData.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/TypeData.cs @@ -135,10 +135,16 @@ namespace System.Xml.Serialization void LookupTypeConvertor () { - // We only need this for System.Xml.Linq. - var convertor = type.GetCustomAttribute (); - if (convertor != null) - typeConvertor = type.GetMethod (convertor.Method, BindingFlags.Static | BindingFlags.NonPublic); + // We only need this for System.Xml.Linq + var t = type; + // HACK: because interpreter array handling is so bad + if (t.IsArray) + t = t.GetElementType (); + + var convertor = t.GetCustomAttribute (); + if (convertor != null) { + typeConvertor = t.GetMethod (convertor.Method, BindingFlags.Static | BindingFlags.NonPublic); + } } internal void ConvertForAssignment (ref object value) diff --git a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs index 5d9e4b24f3..d03dea1ff0 100644 --- a/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs +++ b/mcs/class/System.XML/System.Xml.Serialization/XmlSerializationReaderInterpreter.cs @@ -737,7 +737,8 @@ namespace System.Xml.Serialization Type type = listType.Type; if (type.IsArray) { - list = EnsureArrayIndex ((Array)list, index, type.GetElementType()); + list = EnsureArrayIndex ((Array)list, index, type.GetElementType ()); + listType.ConvertForAssignment (ref value); ((Array)list).SetValue (value, index); } else // Must be IEnumerable diff --git a/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs.REMOVED.git-id b/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs.REMOVED.git-id index 2d558c5525..335c9b0a25 100644 --- a/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs.REMOVED.git-id +++ b/mcs/class/System.Xml.Linq/Test/System.Xml.Linq/XElementTest.cs.REMOVED.git-id @@ -1 +1 @@ -5415ff8e50a4beb760cc5825406fd6e49e7a3989 \ No newline at end of file +f93bbabc3d88e21bca92fc48e741c150f261a945 \ No newline at end of file diff --git a/mcs/class/System/Mono.Btls/MonoBtlsContext.cs b/mcs/class/System/Mono.Btls/MonoBtlsContext.cs index 2df24d9793..a926124bb5 100644 --- a/mcs/class/System/Mono.Btls/MonoBtlsContext.cs +++ b/mcs/class/System/Mono.Btls/MonoBtlsContext.cs @@ -135,7 +135,7 @@ namespace Mono.Btls if (IsServer) { SetPrivateCertificate (nativeServerCertificate); } else { - ssl.SetServerName (TargetHost); + ssl.SetServerName (ServerName); } } @@ -236,14 +236,7 @@ namespace Mono.Btls if (!IsServer) ctx.SetSelectCallback (SelectCallback); - var host = TargetHost; - if (!string.IsNullOrEmpty (host)) { - var pos = TargetHost.IndexOf (':'); - if (pos > 0) - host = host.Substring (0, pos); - } - - ctx.SetVerifyParam (MonoBtlsProvider.GetVerifyParam (host, IsServer)); + ctx.SetVerifyParam (MonoBtlsProvider.GetVerifyParam (ServerName, IsServer)); TlsProtocolCode minProtocol, maxProtocol; GetProtocolVersions (out minProtocol, out maxProtocol); diff --git a/mcs/class/System/Mono.Net.Security/MobileTlsContext.cs b/mcs/class/System/Mono.Net.Security/MobileTlsContext.cs index f051a5fcbc..79f0468d46 100644 --- a/mcs/class/System/Mono.Net.Security/MobileTlsContext.cs +++ b/mcs/class/System/Mono.Net.Security/MobileTlsContext.cs @@ -35,6 +35,7 @@ namespace Mono.Net.Security MobileAuthenticatedStream parent; bool serverMode; string targetHost; + string serverName; SslProtocols enabledProtocols; X509Certificate serverCertificate; X509CertificateCollection clientCertificates; @@ -54,6 +55,13 @@ namespace Mono.Net.Security this.clientCertificates = clientCertificates; this.askForClientCert = askForClientCert; + serverName = targetHost; + if (!string.IsNullOrEmpty (serverName)) { + var pos = serverName.IndexOf (':'); + if (pos > 0) + serverName = serverName.Substring (0, pos); + } + certificateValidator = CertificateValidationHelper.GetInternalValidator ( parent.Settings, parent.Provider); } @@ -92,6 +100,10 @@ namespace Mono.Net.Security get { return targetHost; } } + protected string ServerName { + get { return serverName; } + } + protected bool AskForClientCertificate { get { return askForClientCert; } } diff --git a/mcs/class/System/System.Net.Sockets/TcpListener.platformnotsupported.cs b/mcs/class/System/System.Net.Sockets/TcpListener.platformnotsupported.cs index 7b64967345..76941fc7ce 100644 --- a/mcs/class/System/System.Net.Sockets/TcpListener.platformnotsupported.cs +++ b/mcs/class/System/System.Net.Sockets/TcpListener.platformnotsupported.cs @@ -78,6 +78,16 @@ namespace System.Net.Sockets throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + public void AllowNatTraversal (bool allowed) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + + public static TcpListener Create (int port) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + ~TcpListener () { } diff --git a/mcs/class/System/System.Net.Sockets/UdpClient.platformnotsupported.cs b/mcs/class/System/System.Net.Sockets/UdpClient.platformnotsupported.cs index 953350146d..7a5e2dd740 100644 --- a/mcs/class/System/System.Net.Sockets/UdpClient.platformnotsupported.cs +++ b/mcs/class/System/System.Net.Sockets/UdpClient.platformnotsupported.cs @@ -204,6 +204,11 @@ namespace System.Net.Sockets set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } } + public void AllowNatTraversal (bool allowed) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + public void Dispose () { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); diff --git a/mcs/class/System/System.Net/HttpListener.platformnotsupported.cs b/mcs/class/System/System.Net/HttpListener.platformnotsupported.cs index bffdfbc701..88ae1d361e 100644 --- a/mcs/class/System/System.Net/HttpListener.platformnotsupported.cs +++ b/mcs/class/System/System.Net/HttpListener.platformnotsupported.cs @@ -26,6 +26,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +using System.Security.Authentication.ExtendedProtection; using System.Threading.Tasks; namespace System.Net { @@ -33,6 +34,8 @@ namespace System.Net { { internal const string EXCEPTION_MESSAGE = "System.Net.HttpListener is not supported on the current platform."; + public delegate ExtendedProtectionPolicy ExtendedProtectionSelector (HttpListenerRequest request); + public HttpListener () { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); @@ -75,6 +78,27 @@ namespace System.Net { set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } } + public HttpListenerTimeoutManager TimeoutManager { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ExtendedProtectionPolicy ExtendedProtectionPolicy + { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ExtendedProtectionSelector ExtendedProtectionSelectorDelegate + { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + + public ServiceNameCollection DefaultServiceNames + { + get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + } + public void Abort () { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); diff --git a/mcs/class/System/System.Net/HttpListenerContext.platformnotsupported.cs b/mcs/class/System/System.Net/HttpListenerContext.platformnotsupported.cs index 4c729de26c..275d6d4ad1 100644 --- a/mcs/class/System/System.Net/HttpListenerContext.platformnotsupported.cs +++ b/mcs/class/System/System.Net/HttpListenerContext.platformnotsupported.cs @@ -55,6 +55,11 @@ namespace System.Net { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + public Task AcceptWebSocketAsync (string subProtocol, TimeSpan keepAliveInterval) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + public Task AcceptWebSocketAsync (string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval) { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); diff --git a/mcs/class/System/System.Net/HttpWebRequest.platformnotsupported.cs b/mcs/class/System/System.Net/HttpWebRequest.platformnotsupported.cs index 3977c7bad9..590c82b0bd 100644 --- a/mcs/class/System/System.Net/HttpWebRequest.platformnotsupported.cs +++ b/mcs/class/System/System.Net/HttpWebRequest.platformnotsupported.cs @@ -67,12 +67,12 @@ namespace System.Net get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } } - public bool AllowAutoRedirect { + public virtual bool AllowAutoRedirect { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } } - public bool AllowWriteStreamBuffering { + public virtual bool AllowWriteStreamBuffering { get { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } set { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } } @@ -360,6 +360,11 @@ namespace System.Net throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); } + public System.IO.Stream GetRequestStream (out TransportContext context) + { + throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); + } + public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state) { throw new PlatformNotSupportedException (EXCEPTION_MESSAGE); diff --git a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs index d7128abc33..453735cf84 100644 --- a/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs +++ b/mcs/class/corlib/System.Runtime.InteropServices/Marshal.cs @@ -74,6 +74,13 @@ namespace System.Runtime.InteropServices return false; } + [MonoTODO] + public static void CleanupUnusedObjectsInCurrentContext () + { + if (Environment.IsRunningOnWindows) + throw new PlatformNotSupportedException (); + } + [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern static IntPtr AllocCoTaskMem (int cb); @@ -769,15 +776,8 @@ namespace System.Runtime.InteropServices [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern static string PtrToStringUni (IntPtr ptr, int len); -#if !MOBILE [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern static string PtrToStringBSTR (IntPtr ptr); -#else - public static string PtrToStringBSTR (IntPtr ptr) - { - throw new NotImplementedException (); - } -#endif [MethodImplAttribute(MethodImplOptions.InternalCall)] [ComVisible (true)] diff --git a/mcs/class/corlib/Test/System/TypeTest.cs.REMOVED.git-id b/mcs/class/corlib/Test/System/TypeTest.cs.REMOVED.git-id index cfabe9c21a..83cb6c2631 100644 --- a/mcs/class/corlib/Test/System/TypeTest.cs.REMOVED.git-id +++ b/mcs/class/corlib/Test/System/TypeTest.cs.REMOVED.git-id @@ -1 +1 @@ -d9eea5672d519baa2abbb431cd364b9620888b26 \ No newline at end of file +e275634bc2c909abbe355a3fe2f75b1a08b25558 \ No newline at end of file diff --git a/mcs/class/lib/monolite/System.dll.REMOVED.git-id b/mcs/class/lib/monolite/System.dll.REMOVED.git-id index 386249ad7e..1e783ef089 100644 --- a/mcs/class/lib/monolite/System.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/System.dll.REMOVED.git-id @@ -1 +1 @@ -4300ee601c5a3c592bf6808619b626189da4347f \ No newline at end of file +8fb76ec050d22e5bb67a5dab3635c1998608ec6a \ No newline at end of file diff --git a/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id b/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id index c75cc51845..796f6abff3 100644 --- a/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id +++ b/mcs/class/lib/monolite/mscorlib.dll.REMOVED.git-id @@ -1 +1 @@ -4a5d937cf3124b7461317b6d951a881da4f0a453 \ No newline at end of file +1035eebc45f582696603f7c18625e71de46627a7 \ No newline at end of file diff --git a/mono/btls/CMakeLists.txt b/mono/btls/CMakeLists.txt new file mode 100644 index 0000000000..133f5e3272 --- /dev/null +++ b/mono/btls/CMakeLists.txt @@ -0,0 +1,94 @@ +cmake_minimum_required (VERSION 2.8.10) + +project (mono-btls) + +if(POLICY CMP0026) +cmake_policy(SET CMP0026 NEW) +endif() +if(POLICY CMP0042) +cmake_policy(SET CMP0042 NEW) +endif() + +enable_language(C) +enable_language(CXX) + +# FIXME: cmake's asm detection is broken when using xcrun. +set (CMAKE_ASM_COMPILER "${CMAKE_C_COMPILER}") +set (CMAKE_ASM_COMPILER_ARG1 "${CMAKE_C_COMPILER_ARG1}") +set (CMAKE_ASM_COMPILER_ID "${CMAKE_C_COMPILER_ID}") +enable_language(ASM) + +if (NOT "${BTLS_ARCH}" STREQUAL "") + message (WARNING "SET ARCH: ${BTLS_ARCH}") + set (CMAKE_SYSTEM_PROCESSOR "${BTLS_ARCH}") +endif () +set (C_CXX_FLAGS "-Wall -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} ${BTLS_CFLAGS}") +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_CXX_FLAGS} ${BTLS_CFLAGS}") +set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${BTLS_CFLAGS}") +set (CMAKE_MACOSX_RPATH 1) +set (MONO_BTLS 1) + +add_subdirectory (${BTLS_ROOT} boringssl) + +include_directories ( + ${SRC_DIR} + ${BTLS_ROOT}/include +) + +set ( + MONO_BTLS_SOURCES + + btls-bio.c + btls-bio.h + btls-error.c + btls-error.h + btls-key.c + btls-key.h + btls-pkcs12.c + btls-pkcs12.h + btls-ssl-ctx.c + btls-ssl-ctx.h + btls-ssl.c + btls-ssl.h + btls-time64.c + btls-util.c + btls-util.h + btls-x509-chain.c + btls-x509-chain.h + btls-x509-crl.c + btls-x509-crl.h + btls-x509-lookup.c + btls-x509-lookup.h + btls-x509-lookup-mono.c + btls-x509-lookup-mono.h + btls-x509-name.c + btls-x509-name.h + btls-x509-revoked.c + btls-x509-revoked.h + btls-x509-store-ctx.c + btls-x509-store-ctx.h + btls-x509-store.c + btls-x509-store.h + btls-x509-verify-param.c + btls-x509-verify-param.h + btls-x509.c + btls-x509.h + + ${BORINGSSL_OBJECTS} +) + +if (BUILD_DYNAMIC_BTLS) + add_library (mono-btls-shared SHARED ${MONO_BTLS_SOURCES}) +elseif (BUILD_SHARED_LIBS) + add_library (mono-btls-shared SHARED ${MONO_BTLS_SOURCES}) + set_target_properties (mono-btls-shared PROPERTIES RULE_LAUNCH_LINK + "${PROJECT_SOURCE_DIR}/create-object-library.sh ${CMAKE_BINARY_DIR} mono-btls-shared.txt mono-btls-shared-lo.txt libmono-btls-shared.a shared ${CMAKE_AR} ${CMAKE_RANLIB} --" + ) +else () + add_library (mono-btls-static STATIC ${MONO_BTLS_SOURCES}) + set_target_properties (mono-btls-static PROPERTIES RULE_LAUNCH_LINK + "${PROJECT_SOURCE_DIR}/create-object-library.sh ${CMAKE_BINARY_DIR} mono-btls-static.txt mono-btls-static-lo.txt libmono-btls-static.a static ${CMAKE_AR} ${CMAKE_RANLIB} --" + ) +endif () + diff --git a/mono/btls/Makefile.am b/mono/btls/Makefile.am index fa4a949b5f..6a5b106132 100644 --- a/mono/btls/Makefile.am +++ b/mono/btls/Makefile.am @@ -1,7 +1,44 @@ BTLS_STATIC_LIST = build-static/mono-btls-static-lo.txt BTLS_SHARED_LIST = build-shared/mono-btls-shared-lo.txt -BTLS_DEPS = $(BTLS_LIBS) build-shared/Makefile build-static/Makefile +EXTRA_DIST = \ + btls-bio.c \ + btls-bio.h \ + btls-error.c \ + btls-error.h \ + btls-key.c \ + btls-key.h \ + btls-pkcs12.c \ + btls-pkcs12.h \ + btls-ssl.c \ + btls-ssl-ctx.c \ + btls-ssl-ctx.h \ + btls-ssl.h \ + btls-time64.c \ + btls-util.c \ + btls-util.h \ + btls-x509.c \ + btls-x509-chain.c \ + btls-x509-chain.h \ + btls-x509-crl.c \ + btls-x509-crl.h \ + btls-x509.h \ + btls-x509-lookup.c \ + btls-x509-lookup.h \ + btls-x509-lookup-mono.c \ + btls-x509-lookup-mono.h \ + btls-x509-name.c \ + btls-x509-name.h \ + btls-x509-revoked.c \ + btls-x509-revoked.h \ + btls-x509-store.c \ + btls-x509-store-ctx.c \ + btls-x509-store-ctx.h \ + btls-x509-store.h \ + btls-x509-verify-param.c \ + btls-x509-verify-param.h \ + CMakeLists.txt \ + create-object-library.sh CMAKE_VERBOSE=$(if $(V),VERBOSE=1,) diff --git a/mono/btls/Makefile.in b/mono/btls/Makefile.in index 72ffa1eaea..b070c75002 100644 --- a/mono/btls/Makefile.in +++ b/mono/btls/Makefile.in @@ -332,7 +332,45 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ BTLS_STATIC_LIST = build-static/mono-btls-static-lo.txt BTLS_SHARED_LIST = build-shared/mono-btls-shared-lo.txt -BTLS_DEPS = $(BTLS_LIBS) build-shared/Makefile build-static/Makefile +EXTRA_DIST = \ + btls-bio.c \ + btls-bio.h \ + btls-error.c \ + btls-error.h \ + btls-key.c \ + btls-key.h \ + btls-pkcs12.c \ + btls-pkcs12.h \ + btls-ssl.c \ + btls-ssl-ctx.c \ + btls-ssl-ctx.h \ + btls-ssl.h \ + btls-time64.c \ + btls-util.c \ + btls-util.h \ + btls-x509.c \ + btls-x509-chain.c \ + btls-x509-chain.h \ + btls-x509-crl.c \ + btls-x509-crl.h \ + btls-x509.h \ + btls-x509-lookup.c \ + btls-x509-lookup.h \ + btls-x509-lookup-mono.c \ + btls-x509-lookup-mono.h \ + btls-x509-name.c \ + btls-x509-name.h \ + btls-x509-revoked.c \ + btls-x509-revoked.h \ + btls-x509-store.c \ + btls-x509-store-ctx.c \ + btls-x509-store-ctx.h \ + btls-x509-store.h \ + btls-x509-verify-param.c \ + btls-x509-verify-param.h \ + CMakeLists.txt \ + create-object-library.sh + CMAKE_VERBOSE = $(if $(V),VERBOSE=1,) CMAKE_ARGS = -D CMAKE_INSTALL_PREFIX:PATH=$(prefix) -D BTLS_ROOT:PATH=$(BTLS_ROOT) \ -D SRC_DIR:PATH=$(abs_top_srcdir)/mono/btls -D BTLS_CFLAGS:STRING="$(BTLS_CFLAGS)" diff --git a/mono/btls/btls-bio.c b/mono/btls/btls-bio.c new file mode 100644 index 0000000000..a35582a3b5 --- /dev/null +++ b/mono/btls/btls-bio.c @@ -0,0 +1,206 @@ +// +// btls-bio.c +// MonoBtls +// +// Created by Martin Baulig on 14/11/15. +// Copyright (c) 2015 Xamarin. All rights reserved. +// + +#include +#include +#include + +struct MonoBtlsBio { + const void *instance; + MonoBtlsReadFunc read_func; + MonoBtlsWriteFunc write_func; + MonoBtlsControlFunc control_func; +}; + +#if 0 +static void +mono_debug (const char *message) +{ + BIO *bio_err; + bio_err = BIO_new_fp (stderr, BIO_NOCLOSE); + fprintf (stderr, "DEBUG: %s\n", message); + ERR_print_errors (bio_err); +} +#endif + +static int +mono_read (BIO *bio, char *out, int outl) +{ + MonoBtlsBio *mono = (MonoBtlsBio *)bio->ptr; + int ret, wantMore; + + if (!mono) + return -1; + + ret = mono->read_func (mono->instance, out, outl, &wantMore); + + if (ret < 0) + return -1; + if (ret > 0) + return ret; + + if (wantMore) { + errno = EAGAIN; + BIO_set_retry_read (bio); + return -1; + } + + return 0; +} + +static int +mono_write (BIO *bio, const char *in, int inl) +{ + MonoBtlsBio *mono = (MonoBtlsBio *)bio->ptr; + + if (!mono) + return -1; + + return mono->write_func (mono->instance, in, inl); +} + +static int64_t +mono_ctrl (BIO *bio, int cmd, int64_t num, void *ptr) +{ + MonoBtlsBio *mono = (MonoBtlsBio *)bio->ptr; + + if (!mono) + return -1; + + // fprintf (stderr, "mono_ctrl: %x - %lx - %p\n", cmd, num, ptr); + switch (cmd) { + case BIO_CTRL_FLUSH: + return mono->control_func (mono->instance, MONO_BTLS_CONTROL_COMMAND_FLUSH, 0); + default: + return -1; + } + return -1; +} + +static int +mono_new (BIO *bio) +{ + // mono_debug("mono_new!\n"); + bio->init = 0; + bio->num = -1; + bio->flags = 0; + return 1; +} + +static int +mono_free (BIO *bio) +{ + // mono_debug ("mono_free!\n"); + if (bio->ptr) { + MonoBtlsBio *mono = (MonoBtlsBio *)bio->ptr; + + bio->ptr = NULL; + mono->instance = NULL; + mono->read_func = NULL; + mono->write_func = NULL; + mono->control_func = NULL; + free (mono); + } + return 1; +} + +static const BIO_METHOD mono_method = { + BIO_TYPE_NONE, "mono", mono_write, mono_read, + NULL, NULL, mono_ctrl, mono_new, mono_free, NULL +}; + +MONO_API BIO * +mono_btls_bio_mono_new (void) +{ + BIO *bio; + MonoBtlsBio *monoBio; + + bio = BIO_new (&mono_method); + if (!bio) + return NULL; + + monoBio = calloc (1, sizeof (MonoBtlsBio)); + if (!monoBio) { + BIO_free (bio); + return NULL; + } + + bio->ptr = monoBio; + bio->init = 0; + + return bio; +} + +MONO_API void +mono_btls_bio_mono_initialize (BIO *bio, const void *instance, + MonoBtlsReadFunc read_func, MonoBtlsWriteFunc write_func, + MonoBtlsControlFunc control_func) +{ + MonoBtlsBio *monoBio = bio->ptr; + + monoBio->instance = instance; + monoBio->read_func = read_func; + monoBio->write_func = write_func; + monoBio->control_func = control_func; + + bio->init = 1; +} + +MONO_API int +mono_btls_bio_read (BIO *bio, void *data, int len) +{ + return BIO_read (bio, data, len); +} + +MONO_API int +mono_btls_bio_write (BIO *bio, const void *data, int len) +{ + return BIO_write (bio, data, len); +} + +MONO_API int +mono_btls_bio_flush (BIO *bio) +{ + return BIO_flush (bio); +} + +MONO_API int +mono_btls_bio_indent (BIO *bio, unsigned indent, unsigned max_indent) +{ + return BIO_indent (bio, indent, max_indent); +} + +MONO_API int +mono_btls_bio_hexdump (BIO *bio, const uint8_t *data, int len, unsigned indent) +{ + return BIO_hexdump (bio, data, len, indent); +} + +MONO_API void +mono_btls_bio_print_errors (BIO *bio) +{ + BIO_print_errors (bio); +} + +MONO_API void +mono_btls_bio_free (BIO *bio) +{ + BIO_free (bio); +} + +MONO_API BIO * +mono_btls_bio_mem_new (void) +{ + return BIO_new (BIO_s_mem ()); +} + +MONO_API int +mono_btls_bio_mem_get_data (BIO *bio, void **data) +{ + return (int)BIO_get_mem_data (bio, (char**)data); +} diff --git a/mono/btls/btls-bio.h b/mono/btls/btls-bio.h new file mode 100644 index 0000000000..0795ef0f2b --- /dev/null +++ b/mono/btls/btls-bio.h @@ -0,0 +1,58 @@ +// +// btls-bio.h +// MonoBtls +// +// Created by Martin Baulig on 14/11/15. +// Copyright (c) 2015 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_bio__ +#define __btls__btls_bio__ + +#include +#include + +typedef enum { + MONO_BTLS_CONTROL_COMMAND_FLUSH = 1 +} MonoBtlsControlCommand; + +typedef int (* MonoBtlsReadFunc) (const void *instance, const void *buf, int size, int *wantMore); +typedef int (* MonoBtlsWriteFunc) (const void *instance, const void *buf, int size); +typedef int64_t (* MonoBtlsControlFunc) (const void *instance, MonoBtlsControlCommand command, int64_t arg); + +BIO * +mono_btls_bio_mono_new (void); + +void +mono_btls_bio_mono_initialize (BIO *bio, const void *instance, + MonoBtlsReadFunc read_func, MonoBtlsWriteFunc write_func, + MonoBtlsControlFunc control_func); + +int +mono_btls_bio_read (BIO *bio, void *data, int len); + +int +mono_btls_bio_write (BIO *bio, const void *data, int len); + +int +mono_btls_bio_flush (BIO *bio); + +int +mono_btls_bio_indent (BIO *bio, unsigned indent, unsigned max_indent); + +int +mono_btls_bio_hexdump (BIO *bio, const uint8_t *data, int len, unsigned indent); + +void +mono_btls_bio_print_errors (BIO *bio); + +void +mono_btls_bio_free (BIO *bio); + +BIO * +mono_btls_bio_mem_new (void); + +int +mono_btls_bio_mem_get_data (BIO *bio, void **data); + +#endif /* defined(__btls__btls_bio__) */ diff --git a/mono/btls/btls-error.c b/mono/btls/btls-error.c new file mode 100644 index 0000000000..75252162a2 --- /dev/null +++ b/mono/btls/btls-error.c @@ -0,0 +1,36 @@ +// +// btls-error.c +// MonoBtls +// +// Created by Martin Baulig on 6/19/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include +#include +#include + +MONO_API int +mono_btls_error_peek_error (void) +{ + return ERR_peek_error (); +} + +MONO_API int +mono_btls_error_get_error (void) +{ + return ERR_get_error (); +} + +MONO_API void +mono_btls_error_clear_error (void) +{ + ERR_clear_error (); +} + +MONO_API void +mono_btls_error_get_error_string_n (int error, char *buf, int len) +{ + ERR_error_string_n (error, buf, len); +} + diff --git a/mono/btls/btls-error.h b/mono/btls/btls-error.h new file mode 100644 index 0000000000..6f791c372a --- /dev/null +++ b/mono/btls/btls-error.h @@ -0,0 +1,29 @@ +// +// btls-util.h +// MonoBtls +// +// Created by Martin Baulig on 3/23/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_error__ +#define __btls__btls_error__ + +#include +#include +#include +#include + +int +mono_btls_error_peek_error (void); + +int +mono_btls_error_get_error (void); + +void +mono_btls_error_clear_error (void); + +void +mono_btls_error_get_error_string_n (int error, char *buf, int len); + +#endif /* __btls__btls_error__ */ diff --git a/mono/btls/btls-key.c b/mono/btls/btls-key.c new file mode 100644 index 0000000000..65909a527d --- /dev/null +++ b/mono/btls/btls-key.c @@ -0,0 +1,62 @@ +// +// btls-key.c +// MonoBtls +// +// Created by Martin Baulig on 3/7/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include + +MONO_API void +mono_btls_key_free (EVP_PKEY *pkey) +{ + EVP_PKEY_free (pkey); +} + +MONO_API EVP_PKEY * +mono_btls_key_up_ref (EVP_PKEY *pkey) +{ + return EVP_PKEY_up_ref (pkey); +} + +MONO_API int +mono_btls_key_get_bits (EVP_PKEY *pkey) +{ + return EVP_PKEY_bits (pkey); +} + +MONO_API int +mono_btls_key_is_rsa (EVP_PKEY *pkey) +{ + return pkey->type == EVP_PKEY_RSA; +} + +MONO_API int +mono_btls_key_get_bytes (EVP_PKEY *pkey, uint8_t **buffer, int *size, int include_private_bits) +{ + size_t len; + RSA *rsa; + int ret; + + *size = 0; + *buffer = NULL; + + if (pkey->type != EVP_PKEY_RSA) + return 0; + + rsa = EVP_PKEY_get1_RSA (pkey); + if (!rsa) + return 0; + + if (include_private_bits) + ret = RSA_private_key_to_bytes (buffer, &len, rsa); + else + ret = RSA_public_key_to_bytes (buffer, &len, rsa); + + if (ret != 1) + return 0; + + *size = (int)len; + return 1; +} diff --git a/mono/btls/btls-key.h b/mono/btls/btls-key.h new file mode 100644 index 0000000000..85ee5b2f58 --- /dev/null +++ b/mono/btls/btls-key.h @@ -0,0 +1,32 @@ +// +// btls-key.h +// MonoBtls +// +// Created by Martin Baulig on 3/7/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_key__ +#define __btls__btls_key__ + +#include +#include +#include + +void +mono_btls_key_free (EVP_PKEY *pkey); + +EVP_PKEY * +mono_btls_key_up_ref (EVP_PKEY *pkey); + +int +mono_btls_key_get_bits (EVP_PKEY *pkey); + +int +mono_btls_key_is_rsa (EVP_PKEY *pkey); + +int +mono_btls_key_get_bytes (EVP_PKEY *pkey, uint8_t **buffer, int *size, int include_private_bits); + +#endif /* __btls__btls_key__ */ + diff --git a/mono/btls/btls-pkcs12.c b/mono/btls/btls-pkcs12.c new file mode 100644 index 0000000000..6e1a79e60b --- /dev/null +++ b/mono/btls/btls-pkcs12.c @@ -0,0 +1,101 @@ +// +// btls-pkcs12.c +// MonoBtls +// +// Created by Martin Baulig on 3/8/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include +#include + +struct MonoBtlsPkcs12 { + STACK_OF(X509) *certs; + EVP_PKEY *private_key; + CRYPTO_refcount_t references; +}; + +MONO_API MonoBtlsPkcs12 * +mono_btls_pkcs12_new (void) +{ + MonoBtlsPkcs12 *pkcs12 = (MonoBtlsPkcs12 *)OPENSSL_malloc (sizeof (MonoBtlsPkcs12)); + if (pkcs12 == NULL) + return NULL; + + memset (pkcs12, 0, sizeof(MonoBtlsPkcs12)); + pkcs12->certs = sk_X509_new_null (); + pkcs12->references = 1; + return pkcs12; +} + +MONO_API int +mono_btls_pkcs12_get_count (MonoBtlsPkcs12 *pkcs12) +{ + return (int)sk_X509_num (pkcs12->certs); +} + +MONO_API X509 * +mono_btls_pkcs12_get_cert (MonoBtlsPkcs12 *pkcs12, int index) +{ + X509 *cert; + + if ((size_t)index >= sk_X509_num (pkcs12->certs)) + return NULL; + cert = sk_X509_value (pkcs12->certs, index); + if (cert) + X509_up_ref (cert); + return cert; +} + +MONO_API STACK_OF(X509) * +mono_btls_pkcs12_get_certs (MonoBtlsPkcs12 *pkcs12) +{ + return pkcs12->certs; +} + +MONO_API int +mono_btls_pkcs12_free (MonoBtlsPkcs12 *pkcs12) +{ + if (!CRYPTO_refcount_dec_and_test_zero (&pkcs12->references)) + return 0; + + sk_X509_pop_free (pkcs12->certs, X509_free); + OPENSSL_free (pkcs12); + return 1; +} + +MONO_API MonoBtlsPkcs12 * +mono_btls_pkcs12_up_ref (MonoBtlsPkcs12 *pkcs12) +{ + CRYPTO_refcount_inc (&pkcs12->references); + return pkcs12; +} + +MONO_API void +mono_btls_pkcs12_add_cert (MonoBtlsPkcs12 *pkcs12, X509 *x509) +{ + X509_up_ref (x509); + sk_X509_push (pkcs12->certs, x509); +} + +MONO_API int +mono_btls_pkcs12_import (MonoBtlsPkcs12 *pkcs12, const void *data, int len, const void *password) +{ + CBS cbs; + CBS_init (&cbs, data, len); + return PKCS12_get_key_and_certs (&pkcs12->private_key, pkcs12->certs, &cbs, password); +} + +MONO_API int +mono_btls_pkcs12_has_private_key (MonoBtlsPkcs12 *pkcs12) +{ + return pkcs12->private_key != NULL; +} + +MONO_API EVP_PKEY * +mono_btls_pkcs12_get_private_key (MonoBtlsPkcs12 *pkcs12) +{ + if (!pkcs12->private_key) + return NULL; + return EVP_PKEY_up_ref (pkcs12->private_key); +} diff --git a/mono/btls/btls-pkcs12.h b/mono/btls/btls-pkcs12.h new file mode 100644 index 0000000000..20c4fd9c4e --- /dev/null +++ b/mono/btls/btls-pkcs12.h @@ -0,0 +1,46 @@ +// +// btls-pkcs12.h +// MonoBtls +// +// Created by Martin Baulig on 3/8/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_pkcs12__ +#define __btls__btls_pkcs12__ + +#include +#include +#include + +MonoBtlsPkcs12 * +mono_btls_pkcs12_new (void); + +int +mono_btls_pkcs12_get_count (MonoBtlsPkcs12 *pkcs12); + +X509 * +mono_btls_pkcs12_get_cert (MonoBtlsPkcs12 *pkcs12, int index); + +STACK_OF(X509) * +mono_btls_pkcs12_get_certs (MonoBtlsPkcs12 *pkcs12); + +int +mono_btls_pkcs12_free (MonoBtlsPkcs12 *pkcs12); + +MonoBtlsPkcs12 * +mono_btls_pkcs12_up_ref (MonoBtlsPkcs12 *pkcs12); + +void +mono_btls_pkcs12_add_cert (MonoBtlsPkcs12 *pkcs12, X509 *x509); + +int +mono_btls_pkcs12_import (MonoBtlsPkcs12 *pkcs12, const void *data, int len, const void *password); + +int +mono_btls_pkcs12_has_private_key (MonoBtlsPkcs12 *pkcs12); + +EVP_PKEY * +mono_btls_pkcs12_get_private_key (MonoBtlsPkcs12 *pkcs12); + +#endif /* __btls__btls_pkcs12__ */ diff --git a/mono/btls/btls-ssl-ctx.c b/mono/btls/btls-ssl-ctx.c new file mode 100644 index 0000000000..1f9d43c536 --- /dev/null +++ b/mono/btls/btls-ssl-ctx.c @@ -0,0 +1,255 @@ +// +// btls-ssl-ctx.c +// MonoBtls +// +// Created by Martin Baulig on 4/11/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include +#include + +struct MonoBtlsSslCtx { + CRYPTO_refcount_t references; + SSL_CTX *ctx; + BIO *bio; + BIO *debug_bio; + void *instance; + MonoBtlsVerifyFunc verify_func; + MonoBtlsSelectFunc select_func; +}; + +#define debug_print(ptr,message) \ +do { if (mono_btls_ssl_ctx_is_debug_enabled(ptr)) \ +mono_btls_ssl_ctx_debug_printf (ptr, "%s:%d:%s(): " message, __FILE__, __LINE__, \ + __func__); } while (0) + +#define debug_printf(ptr,fmt, ...) \ +do { if (mono_btls_ssl_ctx_is_debug_enabled(ptr)) \ +mono_btls_ssl_ctx_debug_printf (ptr, "%s:%d:%s(): " fmt, __FILE__, __LINE__, \ + __func__, __VA_ARGS__); } while (0) + +void ssl_cipher_preference_list_free (struct ssl_cipher_preference_list_st *cipher_list); + +MONO_API int +mono_btls_ssl_ctx_is_debug_enabled (MonoBtlsSslCtx *ctx) +{ + return ctx->debug_bio != NULL; +} + +MONO_API int +mono_btls_ssl_ctx_debug_printf (MonoBtlsSslCtx *ctx, const char *format, ...) +{ + va_list args; + int ret; + + if (!ctx->debug_bio) + return 0; + + va_start (args, format); + ret = mono_btls_debug_printf (ctx->debug_bio, format, args); + va_end (args); + return ret; +} + +MONO_API MonoBtlsSslCtx * +mono_btls_ssl_ctx_new (void) +{ + MonoBtlsSslCtx *ctx; + + ctx = OPENSSL_malloc (sizeof (MonoBtlsSslCtx)); + if (!ctx) + return NULL; + + memset (ctx, 0, sizeof (MonoBtlsSslCtx)); + ctx->references = 1; + ctx->ctx = SSL_CTX_new (TLS_method ()); + return ctx; +} + +MONO_API MonoBtlsSslCtx * +mono_btls_ssl_ctx_up_ref (MonoBtlsSslCtx *ctx) +{ + CRYPTO_refcount_inc (&ctx->references); + return ctx; +} + +MONO_API int +mono_btls_ssl_ctx_free (MonoBtlsSslCtx *ctx) +{ + if (!CRYPTO_refcount_dec_and_test_zero (&ctx->references)) + return 0; + SSL_CTX_free (ctx->ctx); + ctx->instance = NULL; + OPENSSL_free (ctx); + return 1; +} + +MONO_API SSL_CTX * +mono_btls_ssl_ctx_get_ctx (MonoBtlsSslCtx *ctx) +{ + return ctx->ctx; +} + +MONO_API void +mono_btls_ssl_ctx_set_debug_bio (MonoBtlsSslCtx *ctx, BIO *debug_bio) +{ + if (debug_bio) + ctx->debug_bio = BIO_up_ref(debug_bio); + else + ctx->debug_bio = NULL; +} + +MONO_API void +mono_btls_ssl_ctx_initialize (MonoBtlsSslCtx *ctx, void *instance) +{ + ctx->instance = instance; +} + +static int +cert_verify_callback (X509_STORE_CTX *storeCtx, void *arg) +{ + MonoBtlsSslCtx *ptr = (MonoBtlsSslCtx*)arg; + int ret; + + debug_printf (ptr, "cert_verify_callback(): %p\n", ptr->verify_func); + ret = X509_verify_cert (storeCtx); + debug_printf (ptr, "cert_verify_callback() #1: %d\n", ret); + + if (ptr->verify_func) + ret = ptr->verify_func (ptr->instance, ret, storeCtx); + + return ret; +} + +MONO_API void +mono_btls_ssl_ctx_set_cert_verify_callback (MonoBtlsSslCtx *ptr, MonoBtlsVerifyFunc func, int cert_required) +{ + int mode; + + ptr->verify_func = func; + SSL_CTX_set_cert_verify_callback (ptr->ctx, cert_verify_callback, ptr); + + mode = SSL_VERIFY_PEER; + if (cert_required) + mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + + SSL_CTX_set_verify (ptr->ctx, mode, NULL); +} + +static int +cert_select_callback (SSL *ssl, void *arg) +{ + MonoBtlsSslCtx *ptr = (MonoBtlsSslCtx*)arg; + int ret = 1; + + debug_printf (ptr, "cert_select_callback(): %p\n", ptr->select_func); + if (ptr->select_func) + ret = ptr->select_func (ptr->instance); + debug_printf (ptr, "cert_select_callback() #1: %d\n", ret); + + return ret; +} + +MONO_API void +mono_btls_ssl_ctx_set_cert_select_callback (MonoBtlsSslCtx *ptr, MonoBtlsSelectFunc func) +{ + ptr->select_func = func; + SSL_CTX_set_cert_cb (ptr->ctx, cert_select_callback, ptr); +} + +MONO_API X509_STORE * +mono_btls_ssl_ctx_peek_store (MonoBtlsSslCtx *ctx) +{ + return SSL_CTX_get_cert_store (ctx->ctx); +} + +MONO_API void +mono_btls_ssl_ctx_set_min_version (MonoBtlsSslCtx *ctx, int version) +{ + SSL_CTX_set_min_version (ctx->ctx, version); +} + +MONO_API void +mono_btls_ssl_ctx_set_max_version (MonoBtlsSslCtx *ctx, int version) +{ + SSL_CTX_set_max_version (ctx->ctx, version); +} + +MONO_API int +mono_btls_ssl_ctx_is_cipher_supported (MonoBtlsSslCtx *ctx, uint16_t value) +{ + const SSL_CIPHER *cipher; + + cipher = SSL_get_cipher_by_value (value); + return cipher != NULL; +} + +MONO_API int +mono_btls_ssl_ctx_set_ciphers (MonoBtlsSslCtx *ctx, int count, const uint16_t *data, + int allow_unsupported) +{ + STACK_OF(SSL_CIPHER) *ciphers = NULL; + struct ssl_cipher_preference_list_st *pref_list = NULL; + uint8_t *in_group_flags = NULL; + int i; + + ciphers = sk_SSL_CIPHER_new_null (); + if (!ciphers) + goto err; + + for (i = 0; i < count; i++) { + const SSL_CIPHER *cipher = SSL_get_cipher_by_value (data [i]); + if (!cipher) { + debug_printf (ctx, "mono_btls_ssl_ctx_set_ciphers(): unknown cipher %02x", data [i]); + if (!allow_unsupported) + goto err; + continue; + } + if (!sk_SSL_CIPHER_push (ciphers, cipher)) + goto err; + } + + pref_list = OPENSSL_malloc (sizeof (struct ssl_cipher_preference_list_st)); + if (!pref_list) + goto err; + + memset (pref_list, 0, sizeof (struct ssl_cipher_preference_list_st)); + pref_list->ciphers = sk_SSL_CIPHER_dup (ciphers); + if (!pref_list->ciphers) + goto err; + pref_list->in_group_flags = OPENSSL_malloc (sk_SSL_CIPHER_num (ciphers)); + if (!pref_list->in_group_flags) + goto err; + + if (ctx->ctx->cipher_list) + ssl_cipher_preference_list_free (ctx->ctx->cipher_list); + if (ctx->ctx->cipher_list_by_id) + sk_SSL_CIPHER_free (ctx->ctx->cipher_list_by_id); + if (ctx->ctx->cipher_list_tls10) { + ssl_cipher_preference_list_free (ctx->ctx->cipher_list_tls10); + ctx->ctx->cipher_list_tls10 = NULL; + } + if (ctx->ctx->cipher_list_tls11) { + ssl_cipher_preference_list_free (ctx->ctx->cipher_list_tls11); + ctx->ctx->cipher_list_tls11 = NULL; + } + + ctx->ctx->cipher_list = pref_list; + ctx->ctx->cipher_list_by_id = ciphers; + + return (int)sk_SSL_CIPHER_num (ciphers); + +err: + sk_SSL_CIPHER_free (ciphers); + OPENSSL_free (pref_list); + OPENSSL_free (in_group_flags); + return 0; +} + +MONO_API int +mono_btls_ssl_ctx_set_verify_param (MonoBtlsSslCtx *ctx, const MonoBtlsX509VerifyParam *param) +{ + return SSL_CTX_set1_param (ctx->ctx, mono_btls_x509_verify_param_peek_param (param)); +} + diff --git a/mono/btls/btls-ssl-ctx.h b/mono/btls/btls-ssl-ctx.h new file mode 100644 index 0000000000..0954192709 --- /dev/null +++ b/mono/btls/btls-ssl-ctx.h @@ -0,0 +1,84 @@ +// +// btls-ssl-ctx.h +// MonoBtls +// +// Created by Martin Baulig on 4/11/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls_ssl_ctx__btls_ssl_ctx__ +#define __btls_ssl_ctx__btls_ssl_ctx__ + +#include +#include +#include +#include +#include + +typedef struct MonoBtlsBio MonoBtlsBio; +typedef struct MonoBtlsX509Chain MonoBtlsX509Chain; +typedef struct MonoBtlsX509Crl MonoBtlsX509Crl; +typedef struct MonoBtlsX509Lookup MonoBtlsX509Lookup; +typedef struct MonoBtlsX509LookupMono MonoBtlsX509LookupMono; +typedef struct MonoBtlsX509Name MonoBtlsX509Name; +typedef struct MonoBtlsX509Store MonoBtlsX509Store; +typedef struct MonoBtlsX509StoreCtx MonoBtlsX509StoreCtx; +typedef struct MonoBtlsX509Revoked MonoBtlsX509Revoked; +typedef struct MonoBtlsX509VerifyParam MonoBtlsX509VerifyParam; +typedef struct MonoBtlsPkcs12 MonoBtlsPkcs12; +typedef struct MonoBtlsSsl MonoBtlsSsl; +typedef struct MonoBtlsSslCtx MonoBtlsSslCtx; + +typedef int (* MonoBtlsVerifyFunc) (void *instance, int preverify_ok, X509_STORE_CTX *ctx); +typedef int (* MonoBtlsSelectFunc) (void *instance); + +MonoBtlsSslCtx * +mono_btls_ssl_ctx_new (void); + +MonoBtlsSslCtx * +mono_btls_ssl_ctx_up_ref (MonoBtlsSslCtx *ctx); + +int +mono_btls_ssl_ctx_free (MonoBtlsSslCtx *ctx); + +void +mono_btls_ssl_ctx_initialize (MonoBtlsSslCtx *ctx, void *instance); + +SSL_CTX * +mono_btls_ssl_ctx_get_ctx (MonoBtlsSslCtx *ctx); + +int +mono_btls_ssl_ctx_debug_printf (MonoBtlsSslCtx *ctx, const char *format, ...); + +int +mono_btls_ssl_ctx_is_debug_enabled (MonoBtlsSslCtx *ctx); + +void +mono_btls_ssl_ctx_set_cert_verify_callback (MonoBtlsSslCtx *ptr, MonoBtlsVerifyFunc func, int cert_required); + +void +mono_btls_ssl_ctx_set_cert_select_callback (MonoBtlsSslCtx *ptr, MonoBtlsSelectFunc func); + +void +mono_btls_ssl_ctx_set_debug_bio (MonoBtlsSslCtx *ctx, BIO *debug_bio); + +X509_STORE * +mono_btls_ssl_ctx_peek_store (MonoBtlsSslCtx *ctx); + +void +mono_btls_ssl_ctx_set_min_version (MonoBtlsSslCtx *ctx, int version); + +void +mono_btls_ssl_ctx_set_max_version (MonoBtlsSslCtx *ctx, int version); + +int +mono_btls_ssl_ctx_is_cipher_supported (MonoBtlsSslCtx *ctx, uint16_t value); + +int +mono_btls_ssl_ctx_set_ciphers (MonoBtlsSslCtx *ctx, int count, const uint16_t *data, + int allow_unsupported); + +int +mono_btls_ssl_ctx_set_verify_param (MonoBtlsSslCtx *ctx, const MonoBtlsX509VerifyParam *param); + +#endif /* __btls_ssl_ctx__btls_ssl_ctx__ */ diff --git a/mono/btls/btls-ssl.c b/mono/btls/btls-ssl.c new file mode 100644 index 0000000000..f18d6c1924 --- /dev/null +++ b/mono/btls/btls-ssl.c @@ -0,0 +1,209 @@ +// +// btls-ssl.c +// MonoBtls +// +// Created by Martin Baulig on 14/11/15. +// Copyright (c) 2015 Xamarin. All rights reserved. +// + +#include +#include + +struct MonoBtlsSsl { + MonoBtlsSslCtx *ctx; + SSL *ssl; +}; + +#define debug_print(ptr,message) \ +do { if (mono_btls_ssl_ctx_is_debug_enabled(ptr->ctx)) \ +mono_btls_ssl_ctx_debug_printf (ptr->ctx, "%s:%d:%s(): " message, __FILE__, __LINE__, \ +__func__); } while (0) + +#define debug_printf(ptr,fmt, ...) \ +do { if (mono_btls_ssl_ctx_is_debug_enabled(ptr->ctx)) \ +mono_btls_ssl_ctx_debug_printf (ptr->ctx, "%s:%d:%s(): " fmt, __FILE__, __LINE__, \ +__func__, __VA_ARGS__); } while (0) + +STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list (SSL *s, const CBS *cbs); + +MONO_API MonoBtlsSsl * +mono_btls_ssl_new (MonoBtlsSslCtx *ctx) +{ + MonoBtlsSsl *ptr; + + ptr = calloc (1, sizeof (MonoBtlsSsl)); + + ptr->ctx = mono_btls_ssl_ctx_up_ref (ctx); + ptr->ssl = SSL_new (mono_btls_ssl_ctx_get_ctx (ptr->ctx)); + + SSL_set_options (ptr->ssl, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); + + return ptr; +} + +MONO_API void +mono_btls_ssl_destroy (MonoBtlsSsl *ptr) +{ + mono_btls_ssl_close (ptr); + if (ptr->ssl) { + SSL_free (ptr->ssl); + ptr->ssl = NULL; + } + if (ptr->ctx) { + mono_btls_ssl_ctx_free (ptr->ctx); + ptr->ctx = NULL; + } + free (ptr); +} + +MONO_API void +mono_btls_ssl_close (MonoBtlsSsl *ptr) +{ + ; +} + +MONO_API void +mono_btls_ssl_set_bio (MonoBtlsSsl *ptr, BIO *bio) +{ + BIO_up_ref (bio); + SSL_set_bio (ptr->ssl, bio, bio); +} + +MONO_API void +mono_btls_ssl_print_errors_cb (ERR_print_errors_callback_t callback, void *ctx) +{ + ERR_print_errors_cb (callback, ctx); +} + +MONO_API int +mono_btls_ssl_use_certificate (MonoBtlsSsl *ptr, X509 *x509) +{ + return SSL_use_certificate (ptr->ssl, x509); +} + +MONO_API int +mono_btls_ssl_use_private_key (MonoBtlsSsl *ptr, EVP_PKEY *key) +{ + return SSL_use_PrivateKey (ptr->ssl, key); +} + +MONO_API int +mono_btls_ssl_add_chain_certificate (MonoBtlsSsl *ptr, X509 *x509) +{ + return SSL_add1_chain_cert (ptr->ssl, x509); +} + +MONO_API int +mono_btls_ssl_accept (MonoBtlsSsl *ptr) +{ + return SSL_accept (ptr->ssl); +} + +MONO_API int +mono_btls_ssl_connect (MonoBtlsSsl *ptr) +{ + return SSL_connect (ptr->ssl); +} + +MONO_API int +mono_btls_ssl_handshake (MonoBtlsSsl *ptr) +{ + return SSL_do_handshake (ptr->ssl); +} + +MONO_API int +mono_btls_ssl_read (MonoBtlsSsl *ptr, void *buf, int count) +{ + return SSL_read (ptr->ssl, buf, count); +} + +MONO_API int +mono_btls_ssl_write (MonoBtlsSsl *ptr, void *buf, int count) +{ + return SSL_write (ptr->ssl, buf, count); +} + +MONO_API int +mono_btls_ssl_get_version (MonoBtlsSsl *ptr) +{ + return SSL_version (ptr->ssl); +} + +MONO_API void +mono_btls_ssl_set_min_version (MonoBtlsSsl *ptr, int version) +{ + SSL_set_min_version (ptr->ssl, version); +} + +MONO_API void +mono_btls_ssl_set_max_version (MonoBtlsSsl *ptr, int version) +{ + SSL_set_max_version (ptr->ssl, version); +} + +MONO_API int +mono_btls_ssl_get_cipher (MonoBtlsSsl *ptr) +{ + const SSL_CIPHER *cipher; + + cipher = SSL_get_current_cipher (ptr->ssl); + if (!cipher) + return 0; + return (uint16_t)SSL_CIPHER_get_id (cipher); +} + +MONO_API int +mono_btls_ssl_set_cipher_list (MonoBtlsSsl *ptr, const char *str) +{ + return SSL_set_cipher_list(ptr->ssl, str); +} + +MONO_API int +mono_btls_ssl_get_ciphers (MonoBtlsSsl *ptr, uint16_t **data) +{ + STACK_OF(SSL_CIPHER) *ciphers; + int count, i; + + *data = NULL; + + ciphers = SSL_get_ciphers (ptr->ssl); + if (!ciphers) + return 0; + + count = (int)sk_SSL_CIPHER_num (ciphers); + + *data = OPENSSL_malloc (2 * count); + if (!*data) + return 0; + + for (i = 0; i < count; i++) { + const SSL_CIPHER *cipher = sk_SSL_CIPHER_value (ciphers, i); + (*data) [i] = (uint16_t) SSL_CIPHER_get_id (cipher); + } + + return count; +} + +MONO_API X509 * +mono_btls_ssl_get_peer_certificate (MonoBtlsSsl *ptr) +{ + return SSL_get_peer_certificate (ptr->ssl); +} + +MONO_API int +mono_btls_ssl_get_error (MonoBtlsSsl *ptr, int ret_code) +{ + return SSL_get_error (ptr->ssl, ret_code); +} + +MONO_API int +mono_btls_ssl_set_verify_param (MonoBtlsSsl *ptr, const MonoBtlsX509VerifyParam *param) +{ + return SSL_set1_param (ptr->ssl, mono_btls_x509_verify_param_peek_param (param)); +} + +MONO_API int +mono_btls_ssl_set_server_name (MonoBtlsSsl *ptr, const char *name) +{ + return SSL_set_tlsext_host_name (ptr->ssl, name); +} diff --git a/mono/btls/btls-ssl.h b/mono/btls/btls-ssl.h new file mode 100644 index 0000000000..10da436488 --- /dev/null +++ b/mono/btls/btls-ssl.h @@ -0,0 +1,83 @@ +// +// btls-ssl.h +// MonoBtls +// +// Created by Martin Baulig on 14/11/15. +// Copyright (c) 2015 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_ssl__ +#define __btls__btls_ssl__ + +#include + +MonoBtlsSsl * +mono_btls_ssl_new (MonoBtlsSslCtx *ctx); + +int +mono_btls_ssl_use_certificate (MonoBtlsSsl *ptr, X509 *x509); + +int +mono_btls_ssl_use_private_key (MonoBtlsSsl *ptr, EVP_PKEY *key); + +int +mono_btls_ssl_add_chain_certificate (MonoBtlsSsl *ptr, X509 *x509); + +int +mono_btls_ssl_accept (MonoBtlsSsl *ptr); + +int +mono_btls_ssl_connect (MonoBtlsSsl *ptr); + +int +mono_btls_ssl_handshake (MonoBtlsSsl *ptr); + +void +mono_btls_ssl_print_errors_cb (ERR_print_errors_callback_t callback, void *ctx); + +void +mono_btls_ssl_set_bio (MonoBtlsSsl *ptr, BIO *bio); + +int +mono_btls_ssl_read (MonoBtlsSsl *ptr, void *buf, int count); + +int +mono_btls_ssl_write (MonoBtlsSsl *ptr, void *buf, int count); + +int +mono_btls_ssl_get_version (MonoBtlsSsl *ptr); + +void +mono_btls_ssl_set_min_version (MonoBtlsSsl *ptr, int version); + +void +mono_btls_ssl_set_max_version (MonoBtlsSsl *ptr, int version); + +int +mono_btls_ssl_get_cipher (MonoBtlsSsl *ptr); + +int +mono_btls_ssl_set_cipher_list (MonoBtlsSsl *ptr, const char *str); + +int +mono_btls_ssl_get_ciphers (MonoBtlsSsl *ptr, uint16_t **data); + +X509 * +mono_btls_ssl_get_peer_certificate (MonoBtlsSsl *ptr); + +void +mono_btls_ssl_close (MonoBtlsSsl *ptr); + +int +mono_btls_ssl_get_error (MonoBtlsSsl *ptr, int ret_code); + +int +mono_btls_ssl_set_verify_param (MonoBtlsSsl *ptr, const MonoBtlsX509VerifyParam *param); + +int +mono_btls_ssl_set_server_name (MonoBtlsSsl *ptr, const char *name); + +void +mono_btls_ssl_destroy (MonoBtlsSsl *ptr); + +#endif /* defined(__btls__btls_ssl__) */ diff --git a/mono/btls/btls-time64.c b/mono/btls/btls-time64.c new file mode 100644 index 0000000000..5c67546911 --- /dev/null +++ b/mono/btls/btls-time64.c @@ -0,0 +1,158 @@ +/* + +Copyright (c) 2007-2008 Michael G Schwern + +This software originally derived from Paul Sheer's pivotal_gmtime_r.c. + +The MIT License: + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ + +/* See http://code.google.com/p/y2038 for this code's origin */ + +#include +#include +#include +#include +#include +#include +#include + +/* Spec says except for stftime() and the _r() functions, these + all return static memory. Stabbings! */ +static struct tm Static_Return_Date; +static char Static_Return_String[35]; + +static const int days_in_month[2][12] = { + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, +}; + +static const int julian_days_by_month[2][12] = { + {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, + {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}, +}; + +static char const wday_name[7][3] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static char const mon_name[12][3] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static const int length_of_year[2] = { 365, 366 }; + +/* Some numbers relating to the gregorian cycle */ +static const int64_t years_in_gregorian_cycle = 400; +#define days_in_gregorian_cycle ((365 * 400) + 100 - 4 + 1) +static const int64_t seconds_in_gregorian_cycle = days_in_gregorian_cycle * 60LL * 60LL * 24LL; + +/* Year range we can trust the time funcitons with */ +#define MAX_SAFE_YEAR 2037 +#define MIN_SAFE_YEAR 1971 + +/* 28 year Julian calendar cycle */ +#define SOLAR_CYCLE_LENGTH 28 + +/* Year cycle from MAX_SAFE_YEAR down. */ +static const int safe_years_high[SOLAR_CYCLE_LENGTH] = { + 2016, 2017, 2018, 2019, + 2020, 2021, 2022, 2023, + 2024, 2025, 2026, 2027, + 2028, 2029, 2030, 2031, + 2032, 2033, 2034, 2035, + 2036, 2037, 2010, 2011, + 2012, 2013, 2014, 2015 +}; + +/* Year cycle from MIN_SAFE_YEAR up */ +static const int safe_years_low[SOLAR_CYCLE_LENGTH] = { + 1996, 1997, 1998, 1971, + 1972, 1973, 1974, 1975, + 1976, 1977, 1978, 1979, + 1980, 1981, 1982, 1983, + 1984, 1985, 1986, 1987, + 1988, 1989, 1990, 1991, + 1992, 1993, 1994, 1995, +}; + +/* Let's assume people are going to be looking for dates in the future. + Let's provide some cheats so you can skip ahead. + This has a 4x speed boost when near 2008. +*/ +/* Number of days since epoch on Jan 1st, 2008 GMT */ +#define CHEAT_DAYS (1199145600 / 24 / 60 / 60) +#define CHEAT_YEARS 108 + +#define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0) +#define WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a)) + +/* timegm() is not in the C or POSIX spec, but it is such a useful + extension I would be remiss in leaving it out. Also I need it + for localtime64() +*/ +int64_t btls_timegm64(const struct tm *date) { + int64_t days = 0; + int64_t seconds = 0; + int64_t year; + int64_t orig_year = (int64_t)date->tm_year; + int cycles = 0; + + if( orig_year > 100 ) { + cycles = (orig_year - 100) / 400; + orig_year -= cycles * 400; + days += (int64_t)cycles * days_in_gregorian_cycle; + } + else if( orig_year < -300 ) { + cycles = (orig_year - 100) / 400; + orig_year -= cycles * 400; + days += (int64_t)cycles * days_in_gregorian_cycle; + } + + if( orig_year > 70 ) { + year = 70; + while( year < orig_year ) { + days += length_of_year[IS_LEAP(year)]; + year++; + } + } + else if ( orig_year < 70 ) { + year = 69; + do { + days -= length_of_year[IS_LEAP(year)]; + year--; + } while( year >= orig_year ); + } + + + days += julian_days_by_month[IS_LEAP(orig_year)][date->tm_mon]; + days += date->tm_mday - 1; + + seconds = days * 60 * 60 * 24; + + seconds += date->tm_hour * 60 * 60; + seconds += date->tm_min * 60; + seconds += date->tm_sec; + + return(seconds); +} diff --git a/mono/btls/btls-util.c b/mono/btls/btls-util.c new file mode 100644 index 0000000000..7c7f4ca5b4 --- /dev/null +++ b/mono/btls/btls-util.c @@ -0,0 +1,77 @@ +// +// btls-util.c +// MonoBtls +// +// Created by Martin Baulig on 3/23/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include +#include +// #include + +extern int asn1_generalizedtime_to_tm (struct tm *tm, const ASN1_GENERALIZEDTIME *d); + +extern int64_t btls_timegm64 (const struct tm *date); + + +MONO_API void +mono_btls_free (void *data) +{ + OPENSSL_free (data); +} + +int64_t +mono_btls_util_asn1_time_to_ticks (ASN1_TIME *time) +{ + ASN1_GENERALIZEDTIME *gtime; + struct tm tm; + int64_t epoch; + int ret; + + memset (&tm, 0, sizeof (tm)); + + gtime = ASN1_TIME_to_generalizedtime (time, NULL); + ret = asn1_generalizedtime_to_tm (&tm, gtime); + ASN1_GENERALIZEDTIME_free (gtime); + epoch = btls_timegm64 (&tm); + + return epoch; +} + +// Copied from crypto/bio/printf.c, takes va_list +int +mono_btls_debug_printf (BIO *bio, const char *format, va_list args) +{ + char buf[256], *out, out_malloced = 0; + int out_len, ret; + + out_len = vsnprintf (buf, sizeof(buf), format, args); + if (out_len < 0) { + return -1; + } + + if ((size_t) out_len >= sizeof(buf)) { + const int requested_len = out_len; + /* The output was truncated. Note that vsnprintf's return value + * does not include a trailing NUL, but the buffer must be sized + * for it. */ + out = OPENSSL_malloc (requested_len + 1); + out_malloced = 1; + if (out == NULL) { + OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE); + return -1; + } + out_len = vsnprintf (out, requested_len + 1, format, args); + assert(out_len == requested_len); + } else { + out = buf; + } + + ret = BIO_write(bio, out, out_len); + if (out_malloced) { + OPENSSL_free(out); + } + + return ret; +} diff --git a/mono/btls/btls-util.h b/mono/btls/btls-util.h new file mode 100644 index 0000000000..a1b165235b --- /dev/null +++ b/mono/btls/btls-util.h @@ -0,0 +1,45 @@ +// +// btls-util.h +// MonoBtls +// +// Created by Martin Baulig on 3/23/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_util__ +#define __btls__btls_util__ + +#include +#include +#include +#include + +#ifndef MONO_API +#if defined(_MSC_VER) + +#define MONO_API __declspec(dllexport) + +#else + +#ifdef __GNUC__ +#define MONO_API __attribute__ ((visibility ("default"))) +#else +#define MONO_API +#endif + +#endif +#endif + +void +mono_btls_free (void *data); + +int64_t +mono_btls_util_asn1_time_to_ticks (ASN1_TIME *time); + +int +mono_btls_debug_printf (BIO *bio, const char *format, va_list args); + +OPENSSL_EXPORT void CRYPTO_refcount_inc(CRYPTO_refcount_t *count); +OPENSSL_EXPORT int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count); + +#endif /* __btls__btls_util__ */ diff --git a/mono/btls/btls-x509-chain.c b/mono/btls/btls-x509-chain.c new file mode 100644 index 0000000000..5b7082ddb1 --- /dev/null +++ b/mono/btls/btls-x509-chain.c @@ -0,0 +1,96 @@ +// +// btls-x509-chain.c +// MonoBtls +// +// Created by Martin Baulig on 3/3/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include + +struct MonoBtlsX509Chain { + STACK_OF(X509) *certs; + CRYPTO_refcount_t references; +}; + +MONO_API MonoBtlsX509Chain * +mono_btls_x509_chain_new (void) +{ + MonoBtlsX509Chain *chain = (MonoBtlsX509Chain *)OPENSSL_malloc (sizeof (MonoBtlsX509Chain)); + if (chain == NULL) + return NULL; + + memset(chain, 0, sizeof(MonoBtlsX509Chain)); + chain->certs = sk_X509_new_null (); + chain->references = 1; + return chain; +} + +MONO_API MonoBtlsX509Chain * +mono_btls_x509_chain_from_certs (STACK_OF(X509) *certs) +{ + MonoBtlsX509Chain *chain = (MonoBtlsX509Chain *)OPENSSL_malloc (sizeof (MonoBtlsX509Chain)); + if (chain == NULL) + return NULL; + + memset(chain, 0, sizeof(MonoBtlsX509Chain)); + chain->certs = X509_chain_up_ref(certs); + chain->references = 1; + return chain; +} + +MONO_API STACK_OF(X509) * +mono_btls_x509_chain_peek_certs (MonoBtlsX509Chain *chain) +{ + return chain->certs; +} + +MONO_API int +mono_btls_x509_chain_get_count (MonoBtlsX509Chain *chain) +{ + return (int)sk_X509_num(chain->certs); +} + +MONO_API X509 * +mono_btls_x509_chain_get_cert (MonoBtlsX509Chain *chain, int index) +{ + X509 *cert; + + if ((size_t)index >= sk_X509_num(chain->certs)) + return NULL; + cert = sk_X509_value(chain->certs, index); + if (cert) + X509_up_ref(cert); + return cert; +} + +MONO_API STACK_OF(X509) * +mono_btls_x509_chain_get_certs (MonoBtlsX509Chain *chain) +{ + return chain->certs; +} + +MONO_API int +mono_btls_x509_chain_free (MonoBtlsX509Chain *chain) +{ + if (!CRYPTO_refcount_dec_and_test_zero(&chain->references)) + return 0; + + sk_X509_pop_free(chain->certs, X509_free); + OPENSSL_free (chain); + return 1; +} + +MONO_API MonoBtlsX509Chain * +mono_btls_x509_chain_up_ref (MonoBtlsX509Chain *chain) +{ + CRYPTO_refcount_inc(&chain->references); + return chain; +} + +MONO_API void +mono_btls_x509_chain_add_cert (MonoBtlsX509Chain *chain, X509 *x509) +{ + X509_up_ref(x509); + sk_X509_push(chain->certs, x509); +} diff --git a/mono/btls/btls-x509-chain.h b/mono/btls/btls-x509-chain.h new file mode 100644 index 0000000000..68ef5773ba --- /dev/null +++ b/mono/btls/btls-x509-chain.h @@ -0,0 +1,41 @@ +// +// btls-x509-chain.h +// MonoBtls +// +// Created by Martin Baulig on 3/3/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_chain__ +#define __btls__btls_x509_chain__ + +#include +#include +#include + +MonoBtlsX509Chain * +mono_btls_x509_chain_new (void); + +MonoBtlsX509Chain * +mono_btls_x509_chain_from_certs (STACK_OF(X509) *certs); + +STACK_OF(X509) * +mono_btls_x509_chain_peek_certs (MonoBtlsX509Chain *chain); + +int +mono_btls_x509_chain_get_count (MonoBtlsX509Chain *chain); + +X509 * +mono_btls_x509_chain_get_cert (MonoBtlsX509Chain *chain, int index); + +MonoBtlsX509Chain * +mono_btls_x509_chain_up_ref (MonoBtlsX509Chain *chain); + +int +mono_btls_x509_chain_free (MonoBtlsX509Chain *chain); + +void +mono_btls_x509_chain_add_cert (MonoBtlsX509Chain *chain, X509 *x509); + +#endif /* defined(__btls__btls_x509_chain__) */ + diff --git a/mono/btls/btls-x509-crl.c b/mono/btls/btls-x509-crl.c new file mode 100644 index 0000000000..d496c072f1 --- /dev/null +++ b/mono/btls/btls-x509-crl.c @@ -0,0 +1,150 @@ +// +// btls-x509-crl.c +// MonoBtls +// +// Created by Martin Baulig on 3/23/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include +#include + +struct MonoBtlsX509Crl { + X509_CRL *crl; + CRYPTO_refcount_t references; +}; + +MONO_API MonoBtlsX509Crl * +mono_btls_x509_crl_from_data (const void *buf, int len, MonoBtlsX509Format format) +{ + MonoBtlsX509Crl *crl; + BIO *bio; + + crl = OPENSSL_malloc (sizeof (MonoBtlsX509Crl)); + memset (crl, 0, sizeof(MonoBtlsX509Crl)); + crl->references = 1; + + bio = BIO_new_mem_buf ((void *)buf, len); + switch (format) { + case MONO_BTLS_X509_FORMAT_DER: + crl->crl = d2i_X509_CRL_bio (bio, NULL); + break; + case MONO_BTLS_X509_FORMAT_PEM: + crl->crl = PEM_read_bio_X509_CRL (bio, NULL, NULL, NULL); + break; + } + BIO_free (bio); + + if (!crl->crl) { + OPENSSL_free (crl); + return NULL; + } + + return crl; +} + +MONO_API MonoBtlsX509Crl * +mono_btls_x509_crl_ref (MonoBtlsX509Crl *crl) +{ + CRYPTO_refcount_inc (&crl->references); + return crl; +} + +MONO_API int +mono_btls_x509_crl_free (MonoBtlsX509Crl *crl) +{ + if (!CRYPTO_refcount_dec_and_test_zero (&crl->references)) + return 0; + + X509_CRL_free (crl->crl); + OPENSSL_free (crl); + return 1; +} + +MONO_API MonoBtlsX509Revoked * +mono_btls_x509_crl_get_by_cert (MonoBtlsX509Crl *crl, X509 *x509) +{ + X509_REVOKED *revoked; + int ret; + + revoked = NULL; + ret = X509_CRL_get0_by_cert (crl->crl, &revoked, x509); + fprintf (stderr, "mono_btls_x509_crl_get_by_cert: %d - %p\n", ret, revoked); + + if (!ret || !revoked) + return NULL; + + return mono_btls_x509_revoked_new (crl, revoked); +} + +MONO_API MonoBtlsX509Revoked * +mono_btls_x509_crl_get_by_serial (MonoBtlsX509Crl *crl, void *serial, int len) +{ + ASN1_INTEGER si; + X509_REVOKED *revoked; + int ret; + + si.type = V_ASN1_INTEGER; + si.length = len; + si.data = serial; + + revoked = NULL; + ret = X509_CRL_get0_by_serial (crl->crl, &revoked, &si); + fprintf (stderr, "mono_btls_x509_crl_get_by_serial: %d - %p\n", ret, revoked); + + if (!ret || !revoked) + return NULL; + + return mono_btls_x509_revoked_new (crl, revoked); +} + +MONO_API int +mono_btls_x509_crl_get_revoked_count (MonoBtlsX509Crl *crl) +{ + STACK_OF(X509_REVOKED) *stack; + + stack = X509_CRL_get_REVOKED (crl->crl); + return (int)sk_X509_REVOKED_num (stack); +} + +MONO_API MonoBtlsX509Revoked * +mono_btls_x509_crl_get_revoked (MonoBtlsX509Crl *crl, int index) +{ + STACK_OF(X509_REVOKED) *stack; + X509_REVOKED *revoked; + + stack = X509_CRL_get_REVOKED (crl->crl); + if ((size_t)index >= sk_X509_REVOKED_num (stack)) + return NULL; + + revoked = sk_X509_REVOKED_value (stack, index); + if (!revoked) + return NULL; + + return mono_btls_x509_revoked_new (crl, revoked); +} + +MONO_API int64_t +mono_btls_x509_crl_get_last_update (MonoBtlsX509Crl *crl) +{ + return mono_btls_util_asn1_time_to_ticks (X509_CRL_get_lastUpdate (crl->crl)); +} + +MONO_API int64_t +mono_btls_x509_crl_get_next_update (MonoBtlsX509Crl *crl) +{ + return mono_btls_util_asn1_time_to_ticks (X509_CRL_get_nextUpdate (crl->crl)); +} + +MONO_API int64_t +mono_btls_x509_crl_get_version (MonoBtlsX509Crl *crl) +{ + return X509_CRL_get_version (crl->crl); +} + +MONO_API MonoBtlsX509Name * +mono_btls_x509_crl_get_issuer (MonoBtlsX509Crl *crl) +{ + return mono_btls_x509_name_copy (X509_CRL_get_issuer (crl->crl)); +} + diff --git a/mono/btls/btls-x509-crl.h b/mono/btls/btls-x509-crl.h new file mode 100644 index 0000000000..625037d99a --- /dev/null +++ b/mono/btls/btls-x509-crl.h @@ -0,0 +1,49 @@ +// +// btls-x509-crl.h +// MonoBtls +// +// Created by Martin Baulig on 3/23/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_crl__ +#define __btls__btls_x509_crl__ + +#include +#include +#include + +MonoBtlsX509Crl * +mono_btls_x509_crl_from_data (const void *buf, int len, MonoBtlsX509Format format); + +MonoBtlsX509Crl * +mono_btls_x509_crl_ref (MonoBtlsX509Crl *crl); + +int +mono_btls_x509_crl_free (MonoBtlsX509Crl *crl); + +MonoBtlsX509Revoked * +mono_btls_x509_crl_get_by_cert (MonoBtlsX509Crl *crl, X509 *x509); + +MonoBtlsX509Revoked * +mono_btls_x509_crl_get_by_serial (MonoBtlsX509Crl *crl, void *serial, int len); + +int +mono_btls_x509_crl_get_revoked_count (MonoBtlsX509Crl *crl); + +MonoBtlsX509Revoked * +mono_btls_x509_crl_get_revoked (MonoBtlsX509Crl *crl, int index); + +int64_t +mono_btls_x509_crl_get_last_update (MonoBtlsX509Crl *crl); + +int64_t +mono_btls_x509_crl_get_next_update (MonoBtlsX509Crl *crl); + +int64_t +mono_btls_x509_crl_get_version (MonoBtlsX509Crl *crl); + +MonoBtlsX509Name * +mono_btls_x509_crl_get_issuer (MonoBtlsX509Crl *crl); + +#endif /* __btls__btls_x509_crl__ */ diff --git a/mono/btls/btls-x509-lookup-mono.c b/mono/btls/btls-x509-lookup-mono.c new file mode 100644 index 0000000000..6d9d69a16f --- /dev/null +++ b/mono/btls/btls-x509-lookup-mono.c @@ -0,0 +1,228 @@ +// +// btls-x509-lookup-mono.c +// MonoBtls +// +// Created by Martin Baulig on 3/6/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include +#include +#include + +// random high number +#define MONO_BTLS_X509_L_MONO_ADD 36292 + +typedef struct MonoLookupNode MonoLookupNode; +struct MonoLookupNode { + MonoBtlsX509LookupMono *mono; + MonoLookupNode *next; +}; + +typedef struct { + MonoLookupNode *nodes; +} MonoLookup; + +struct MonoBtlsX509LookupMono { + const void *instance; + MonoBtlsX509LookupMono_BySubject by_subject_func; + MonoLookup *lookup; +}; + +MONO_API MonoBtlsX509LookupMono * +mono_btls_x509_lookup_mono_new (void) +{ + MonoBtlsX509LookupMono *mono; + + mono = OPENSSL_malloc (sizeof (MonoBtlsX509LookupMono)); + if (!mono) + return NULL; + + memset (mono, 0, sizeof (MonoBtlsX509LookupMono)); + return mono; +} + +MONO_API void +mono_btls_x509_lookup_mono_init (MonoBtlsX509LookupMono *mono, const void *instance, + MonoBtlsX509LookupMono_BySubject by_subject_func) +{ + mono->instance = instance; + mono->by_subject_func = by_subject_func; +} + +static int +mono_lookup_install (MonoLookup *lookup, MonoBtlsX509LookupMono *mono) +{ + MonoLookupNode *node; + + node = OPENSSL_malloc (sizeof (MonoLookupNode)); + if (!node) + return 0; + + memset (node, 0, sizeof (MonoLookupNode)); + mono->lookup = lookup; + node->mono = mono; + node->next = lookup->nodes; + lookup->nodes = node; + return 1; +} + +static int +mono_lookup_uninstall (MonoBtlsX509LookupMono *mono) +{ + MonoLookupNode **ptr; + + if (!mono->lookup) + return 0; + + for (ptr = &mono->lookup->nodes; *ptr; ptr = &(*ptr)->next) { + if ((*ptr)->mono == mono) { + *ptr = (*ptr)->next; + return 1; + } + } + + return 0; +} + +MONO_API int +mono_btls_x509_lookup_mono_free (MonoBtlsX509LookupMono *mono) +{ + mono->instance = NULL; + mono->by_subject_func = NULL; + + if (mono->lookup) { + if (!mono_lookup_uninstall (mono)) + return 0; + } + + mono->lookup = NULL; + + OPENSSL_free (mono); + return 1; +} + +static int +mono_lookup_ctrl (X509_LOOKUP *ctx, int cmd, const char *argp, int64_t argl, char **ret) +{ + MonoLookup *lookup = (MonoLookup*)ctx->method_data; + MonoBtlsX509LookupMono *mono = (MonoBtlsX509LookupMono*)argp; + + if (!lookup || cmd != MONO_BTLS_X509_L_MONO_ADD) + return 0; + if (!mono || mono->lookup) + return 0; + + return mono_lookup_install (lookup, mono); +} + +static int +mono_lookup_new (X509_LOOKUP *ctx) +{ + MonoLookup *data; + + data = OPENSSL_malloc (sizeof (MonoLookup)); + if (!data) + return 0; + + memset (data, 0, sizeof (MonoLookup)); + ctx->method_data = (void *)data; + return 1; +} + +static void +mono_lookup_free (X509_LOOKUP *ctx) +{ + MonoLookup *lookup; + MonoLookupNode *ptr; + + lookup = (MonoLookup *)ctx->method_data; + ctx->method_data = NULL; + if (!lookup) + return; + + ptr = lookup->nodes; + lookup->nodes = NULL; + + while (ptr) { + MonoLookupNode *node = ptr; + ptr = ptr->next; + + if (node->mono) + node->mono->lookup = NULL; + node->mono = NULL; + node->next = NULL; + OPENSSL_free (node); + } + + OPENSSL_free (lookup); +} + +static int +mono_lookup_get_by_subject (X509_LOOKUP *ctx, int type, X509_NAME *name, X509_OBJECT *obj_ret) +{ + MonoLookup *lookup; + MonoBtlsX509Name *name_obj; + MonoLookupNode *node; + X509 *x509 = NULL; + int ret = 0; + + lookup = (MonoLookup *)ctx->method_data; + + if (!lookup || !lookup->nodes) + return 0; + if (type != X509_LU_X509) + return 0; + + name_obj = mono_btls_x509_name_from_name (name); + x509 = NULL; + + for (node = lookup->nodes; node; node = node->next) { + if (!node->mono || !node->mono->by_subject_func) + continue; + ret = (* node->mono->by_subject_func) (node->mono->instance, name_obj, &x509); + if (ret) + break; + } + + mono_btls_x509_name_free (name_obj); + + if (!ret) { + if (x509) + X509_free(x509); + return 0; + } + + obj_ret->type = X509_LU_X509; + obj_ret->data.x509 = x509; + return 1; +} + +static X509_LOOKUP_METHOD mono_lookup_method = { + "Mono lookup method", + mono_lookup_new, /* new */ + mono_lookup_free, /* free */ + NULL, /* init */ + NULL, /* shutdown */ + mono_lookup_ctrl, /* ctrl */ + mono_lookup_get_by_subject, /* get_by_subject */ + NULL, /* get_by_issuer_serial */ + NULL, /* get_by_fingerprint */ + NULL, /* get_by_alias */ +}; + +MONO_API X509_LOOKUP_METHOD * +mono_btls_x509_lookup_mono_method (void) +{ + return &mono_lookup_method; +} + +MONO_API int +mono_btls_x509_lookup_add_mono (MonoBtlsX509Lookup *lookup, MonoBtlsX509LookupMono *mono) +{ + if (mono_btls_x509_lookup_get_type (lookup) != MONO_BTLS_X509_LOOKUP_TYPE_MONO) + return 0; + return X509_LOOKUP_ctrl (mono_btls_x509_lookup_peek_lookup (lookup), + MONO_BTLS_X509_L_MONO_ADD, + (void*)mono, 0, NULL); +} diff --git a/mono/btls/btls-x509-lookup-mono.h b/mono/btls/btls-x509-lookup-mono.h new file mode 100644 index 0000000000..06df552c0f --- /dev/null +++ b/mono/btls/btls-x509-lookup-mono.h @@ -0,0 +1,36 @@ +// +// btls-x509-lookup-mono.h +// MonoBtls +// +// Created by Martin Baulig on 3/3/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_lookup_mono__ +#define __btls__btls_x509_lookup_mono__ + +#include +#include +#include +#include + +typedef int (* MonoBtlsX509LookupMono_BySubject) (const void *instance, MonoBtlsX509Name *name, X509 **ret); + +MonoBtlsX509LookupMono * +mono_btls_x509_lookup_mono_new (void); + +int +mono_btls_x509_lookup_mono_free (MonoBtlsX509LookupMono *mono); + +void +mono_btls_x509_lookup_mono_init (MonoBtlsX509LookupMono *mono, const void *instance, + MonoBtlsX509LookupMono_BySubject by_subject_func); + +int +mono_btls_x509_lookup_add_mono (MonoBtlsX509Lookup *lookup, MonoBtlsX509LookupMono *mono); + +X509_LOOKUP_METHOD * +mono_btls_x509_lookup_mono_method (void); + +#endif /* defined(__btls__btls_x509_lookup_mono__) */ + diff --git a/mono/btls/btls-x509-lookup.c b/mono/btls/btls-x509-lookup.c new file mode 100644 index 0000000000..567d19c237 --- /dev/null +++ b/mono/btls/btls-x509-lookup.c @@ -0,0 +1,160 @@ +// +// btls-x509-lookup.c +// MonoBtls +// +// Created by Martin Baulig on 3/6/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include +#include + +struct MonoBtlsX509Lookup { + MonoBtlsX509LookupType type; + X509_LOOKUP *lookup; + int owns_lookup; + MonoBtlsX509Store *store; + CRYPTO_refcount_t references; +}; + +static X509_LOOKUP_METHOD * +get_lookup_method (MonoBtlsX509LookupType type) +{ + switch (type) { + case MONO_BTLS_X509_LOOKUP_TYPE_FILE: + return X509_LOOKUP_file (); + case MONO_BTLS_X509_LOOKUP_TYPE_HASH_DIR: + return X509_LOOKUP_hash_dir (); + case MONO_BTLS_X509_LOOKUP_TYPE_MONO: + return mono_btls_x509_lookup_mono_method (); + default: + return NULL; + } +} + +MONO_API MonoBtlsX509Lookup * +mono_btls_x509_lookup_new (MonoBtlsX509Store *store, MonoBtlsX509LookupType type) +{ + MonoBtlsX509Lookup *lookup; + X509_LOOKUP *store_lookup; + X509_LOOKUP_METHOD *method; + + method = get_lookup_method (type); + if (!method) + return NULL; + + lookup = OPENSSL_malloc (sizeof(MonoBtlsX509Lookup)); + if (!lookup) + return NULL; + + store_lookup = X509_STORE_add_lookup (mono_btls_x509_store_peek_store (store), method); + if (!store_lookup) + return NULL; + + memset (lookup, 0, sizeof(MonoBtlsX509Lookup)); + // The X509_STORE owns the X509_LOOKUP. + lookup->store = mono_btls_x509_store_up_ref (store); + lookup->lookup = store_lookup; + lookup->owns_lookup = 0; + lookup->references = 1; + lookup->type = type; + return lookup; +} + +MONO_API int +mono_btls_x509_lookup_load_file (MonoBtlsX509Lookup *lookup, const char *file, MonoBtlsX509FileType type) +{ + return X509_LOOKUP_load_file (lookup->lookup, file, type); +} + +MONO_API int +mono_btls_x509_lookup_add_dir (MonoBtlsX509Lookup *lookup, const char *dir, MonoBtlsX509FileType type) +{ + return X509_LOOKUP_add_dir (lookup->lookup, dir, type); +} + +MONO_API MonoBtlsX509Lookup * +mono_btls_x509_lookup_up_ref (MonoBtlsX509Lookup *lookup) +{ + CRYPTO_refcount_inc (&lookup->references); + return lookup; +} + +MONO_API int +mono_btls_x509_lookup_free (MonoBtlsX509Lookup *lookup) +{ + if (!CRYPTO_refcount_dec_and_test_zero (&lookup->references)) + return 0; + + if (lookup->store) { + mono_btls_x509_store_free (lookup->store); + lookup->store = NULL; + } + + if (lookup->lookup) { + if (lookup->owns_lookup) + X509_LOOKUP_free (lookup->lookup); + lookup->lookup = NULL; + } + + OPENSSL_free (lookup); + return 1; +} + +MONO_API int +mono_btls_x509_lookup_init (MonoBtlsX509Lookup *lookup) +{ + return X509_LOOKUP_init (lookup->lookup); +} + +MONO_API int +mono_btls_x509_lookup_shutdown (MonoBtlsX509Lookup *lookup) +{ + return X509_LOOKUP_shutdown (lookup->lookup); +} + +MONO_API MonoBtlsX509LookupType +mono_btls_x509_lookup_get_type (MonoBtlsX509Lookup *lookup) +{ + return lookup->type; +} + +MONO_API X509_LOOKUP * +mono_btls_x509_lookup_peek_lookup (MonoBtlsX509Lookup *lookup) +{ + return lookup->lookup; +} + +MONO_API X509 * +mono_btls_x509_lookup_by_subject (MonoBtlsX509Lookup *lookup, MonoBtlsX509Name *name) +{ + X509_OBJECT obj; + X509 *x509; + int ret; + + ret = X509_LOOKUP_by_subject (lookup->lookup, X509_LU_X509, mono_btls_x509_name_peek_name (name), &obj); + if (ret != X509_LU_X509) { + X509_OBJECT_free_contents (&obj); + return NULL; + } + + x509 = X509_up_ref (obj.data.x509); + return x509; +} + +MONO_API X509 * +mono_btls_x509_lookup_by_fingerprint (MonoBtlsX509Lookup *lookup, unsigned char *bytes, int len) +{ + X509_OBJECT obj; + X509 *x509; + int ret; + + ret = X509_LOOKUP_by_fingerprint (lookup->lookup, X509_LU_X509, bytes, len, &obj); + if (ret != X509_LU_X509) { + X509_OBJECT_free_contents (&obj); + return NULL; + } + + x509 = X509_up_ref (obj.data.x509); + return x509; +} diff --git a/mono/btls/btls-x509-lookup.h b/mono/btls/btls-x509-lookup.h new file mode 100644 index 0000000000..df3d37f1ce --- /dev/null +++ b/mono/btls/btls-x509-lookup.h @@ -0,0 +1,58 @@ +// +// btls-x509-lookup.h +// MonoBtls +// +// Created by Martin Baulig on 3/3/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_lookup__ +#define __btls__btls_x509_lookup__ + +#include +#include +#include +#include + +typedef enum { + MONO_BTLS_X509_LOOKUP_TYPE_UNKNOWN = 0, + MONO_BTLS_X509_LOOKUP_TYPE_FILE, + MONO_BTLS_X509_LOOKUP_TYPE_HASH_DIR, + MONO_BTLS_X509_LOOKUP_TYPE_MONO +} MonoBtlsX509LookupType; + +MonoBtlsX509Lookup * +mono_btls_x509_lookup_new (MonoBtlsX509Store *store, MonoBtlsX509LookupType type); + +int +mono_btls_x509_lookup_load_file (MonoBtlsX509Lookup *lookup, const char *file, MonoBtlsX509FileType type); + +int +mono_btls_x509_lookup_add_dir (MonoBtlsX509Lookup *lookup, const char *dir, MonoBtlsX509FileType type); + +MonoBtlsX509Lookup * +mono_btls_x509_lookup_up_ref (MonoBtlsX509Lookup *lookup); + +int +mono_btls_x509_lookup_free (MonoBtlsX509Lookup *lookup); + +int +mono_btls_x509_lookup_init (MonoBtlsX509Lookup *lookup); + +MonoBtlsX509LookupType +mono_btls_x509_lookup_get_type (MonoBtlsX509Lookup *lookup); + +X509_LOOKUP * +mono_btls_x509_lookup_peek_lookup (MonoBtlsX509Lookup *lookup); + +int +mono_btls_x509_lookup_shutdown (MonoBtlsX509Lookup *lookup); + +X509 * +mono_btls_x509_lookup_by_subject (MonoBtlsX509Lookup *lookup, MonoBtlsX509Name *name); + +X509 * +mono_btls_x509_lookup_by_fingerprint (MonoBtlsX509Lookup *lookup, unsigned char *bytes, int len); + +#endif /* defined(__btls__btls_x509_lookup__) */ + diff --git a/mono/btls/btls-x509-name.c b/mono/btls/btls-x509-name.c new file mode 100644 index 0000000000..7f98758800 --- /dev/null +++ b/mono/btls/btls-x509-name.c @@ -0,0 +1,296 @@ +// +// btls-x509-name.c +// MonoBtls +// +// Created by Martin Baulig on 3/5/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include + +struct MonoBtlsX509Name { + int owns; + X509_NAME *name; +}; + +MONO_API MonoBtlsX509Name * +mono_btls_x509_name_from_name (X509_NAME *xn) +{ + MonoBtlsX509Name *name; + + name = OPENSSL_malloc (sizeof (MonoBtlsX509Name)); + if (!name) + return NULL; + + memset(name, 0, sizeof(MonoBtlsX509Name)); + name->name = xn; + return name; +} + +MONO_API MonoBtlsX509Name * +mono_btls_x509_name_copy (X509_NAME *xn) +{ + MonoBtlsX509Name *name; + + name = OPENSSL_malloc (sizeof (MonoBtlsX509Name)); + if (!name) + return NULL; + + memset(name, 0, sizeof(MonoBtlsX509Name)); + name->name = X509_NAME_dup(xn); + name->owns = 1; + return name; +} + +MONO_API void +mono_btls_x509_name_free (MonoBtlsX509Name *name) +{ + if (name->owns) { + if (name->name) { + X509_NAME_free(name->name); + name->name = NULL; + } + } + OPENSSL_free(name); +} + +MONO_API X509_NAME * +mono_btls_x509_name_peek_name (MonoBtlsX509Name *name) +{ + return name->name; +} + +MONO_API int +mono_btls_x509_name_print_bio (MonoBtlsX509Name *name, BIO *bio) +{ + return X509_NAME_print_ex (bio, name->name, 0, ASN1_STRFLGS_RFC2253 | XN_FLAG_FN_SN | XN_FLAG_SEP_CPLUS_SPC | XN_FLAG_DN_REV); +} + +MONO_API int +mono_btls_x509_name_get_raw_data (MonoBtlsX509Name *name, void **buffer, int use_canon_enc) +{ + int len; + void *ptr; + + if (use_canon_enc) { + // make sure canon_enc is initialized. + i2d_X509_NAME (name->name, NULL); + + len = name->name->canon_enclen; + ptr = name->name->canon_enc; + } else { + len = (int)name->name->bytes->length; + ptr = name->name->bytes->data; + } + + *buffer = OPENSSL_malloc (len); + if (!*buffer) + return 0; + + memcpy (*buffer, ptr, len); + return len; +} + +MONO_API MonoBtlsX509Name * +mono_btls_x509_name_from_data (const void *data, int len, int use_canon_enc) +{ + MonoBtlsX509Name *name; + uint8_t *buf; + const unsigned char *ptr; + X509_NAME *ret; + + name = OPENSSL_malloc (sizeof (MonoBtlsX509Name)); + if (!name) + return NULL; + + memset (name, 0, sizeof(MonoBtlsX509Name)); + name->owns = 1; + + name->name = X509_NAME_new (); + if (!name->name) { + OPENSSL_free (name); + return NULL; + } + + if (use_canon_enc) { + CBB cbb, contents; + size_t buf_len; + + // re-add ASN1 SEQUENCE header. + CBB_init(&cbb, 0); + if (!CBB_add_asn1(&cbb, &contents, 0x30) || + !CBB_add_bytes(&contents, data, len) || + !CBB_finish(&cbb, &buf, &buf_len)) { + CBB_cleanup (&cbb); + mono_btls_x509_name_free (name); + return NULL; + } + + ptr = buf; + len = (int)buf_len; + } else { + ptr = data; + buf = NULL; + } + + ret = d2i_X509_NAME (&name->name, &ptr, len); + + if (buf) + OPENSSL_free (buf); + + if (ret != name->name) { + mono_btls_x509_name_free (name); + return NULL; + } + + return name; +} + +MONO_API int +mono_btls_x509_name_print_string (MonoBtlsX509Name *name, char *buffer, int size) +{ + *buffer = 0; + return X509_NAME_oneline (name->name, buffer, size) != NULL; +} + +MONO_API int64_t +mono_btls_x509_name_hash (MonoBtlsX509Name *name) +{ + return X509_NAME_hash (name->name); +} + +MONO_API int64_t +mono_btls_x509_name_hash_old (MonoBtlsX509Name *name) +{ + return X509_NAME_hash_old (name->name); +} + +MONO_API int +mono_btls_x509_name_get_entry_count (MonoBtlsX509Name *name) +{ + return X509_NAME_entry_count (name->name); +} + +static MonoBtlsX509NameEntryType +nid2mono (int nid) +{ + switch (nid) { + case NID_countryName: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_COUNTRY_NAME; + case NID_organizationName: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_ORGANIZATION_NAME; + case NID_organizationalUnitName: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_ORGANIZATIONAL_UNIT_NAME; + case NID_commonName: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_COMMON_NAME; + case NID_localityName: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_LOCALITY_NAME; + case NID_stateOrProvinceName: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_STATE_OR_PROVINCE_NAME; + case NID_streetAddress: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_STREET_ADDRESS; + case NID_serialNumber: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_SERIAL_NUMBER; + case NID_domainComponent: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_DOMAIN_COMPONENT; + case NID_userId: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_USER_ID; + case NID_dnQualifier: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_DN_QUALIFIER; + case NID_title: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_TITLE; + case NID_surname: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_SURNAME; + case NID_givenName: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_GIVEN_NAME; + case NID_initials: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_INITIAL; + default: + return MONO_BTLS_X509_NAME_ENTRY_TYPE_UNKNOWN; + } +} + +MONO_API MonoBtlsX509NameEntryType +mono_btls_x509_name_get_entry_type (MonoBtlsX509Name *name, int index) +{ + X509_NAME_ENTRY *entry; + ASN1_OBJECT *obj; + + if (index >= X509_NAME_entry_count (name->name)) + return -1; + + entry = X509_NAME_get_entry (name->name, index); + if (!entry) + return -1; + + obj = X509_NAME_ENTRY_get_object (entry); + if (!obj) + return -1; + + return nid2mono (OBJ_obj2nid (obj)); +} + +MONO_API int +mono_btls_x509_name_get_entry_oid (MonoBtlsX509Name *name, int index, char *buffer, int size) +{ + X509_NAME_ENTRY *entry; + ASN1_OBJECT *obj; + + if (index >= X509_NAME_entry_count (name->name)) + return 0; + + entry = X509_NAME_get_entry (name->name, index); + if (!entry) + return 0; + + obj = X509_NAME_ENTRY_get_object (entry); + if (!obj) + return 0; + + return OBJ_obj2txt (buffer, size, obj, 1); +} + +MONO_API int +mono_btls_x509_name_get_entry_oid_data (MonoBtlsX509Name *name, int index, const void **data) +{ + X509_NAME_ENTRY *entry; + ASN1_OBJECT *obj; + + if (index >= X509_NAME_entry_count (name->name)) + return -1; + + entry = X509_NAME_get_entry (name->name, index); + if (!entry) + return -1; + + obj = X509_NAME_ENTRY_get_object (entry); + if (!obj) + return -1; + + *data = obj->data; + return obj->length; +} + +MONO_API int +mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, int *tag, unsigned char **str) +{ + X509_NAME_ENTRY *entry; + ASN1_STRING *data; + + *str = NULL; + *tag = 0; + + if (index >= X509_NAME_entry_count (name->name)) + return 0; + + entry = X509_NAME_get_entry (name->name, index); + if (!entry) + return 0; + + data = X509_NAME_ENTRY_get_data (entry); + if (!data) + return 0; + + *tag = data->type; + return ASN1_STRING_to_UTF8 (str, data); +} diff --git a/mono/btls/btls-x509-name.h b/mono/btls/btls-x509-name.h new file mode 100644 index 0000000000..9d43bc6499 --- /dev/null +++ b/mono/btls/btls-x509-name.h @@ -0,0 +1,80 @@ +// +// btls-x509-name.h +// MonoBtls +// +// Created by Martin Baulig on 3/5/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_name__ +#define __btls__btls_x509_name__ + +#include +#include + +typedef enum { + MONO_BTLS_X509_NAME_ENTRY_TYPE_UNKNOWN = 0, + MONO_BTLS_X509_NAME_ENTRY_TYPE_COUNTRY_NAME, + MONO_BTLS_X509_NAME_ENTRY_TYPE_ORGANIZATION_NAME, + MONO_BTLS_X509_NAME_ENTRY_TYPE_ORGANIZATIONAL_UNIT_NAME, + MONO_BTLS_X509_NAME_ENTRY_TYPE_COMMON_NAME, + MONO_BTLS_X509_NAME_ENTRY_TYPE_LOCALITY_NAME, + MONO_BTLS_X509_NAME_ENTRY_TYPE_STATE_OR_PROVINCE_NAME, + MONO_BTLS_X509_NAME_ENTRY_TYPE_STREET_ADDRESS, + MONO_BTLS_X509_NAME_ENTRY_TYPE_SERIAL_NUMBER, + MONO_BTLS_X509_NAME_ENTRY_TYPE_DOMAIN_COMPONENT, + MONO_BTLS_X509_NAME_ENTRY_TYPE_USER_ID, + MONO_BTLS_X509_NAME_ENTRY_TYPE_EMAIL, + MONO_BTLS_X509_NAME_ENTRY_TYPE_DN_QUALIFIER, + MONO_BTLS_X509_NAME_ENTRY_TYPE_TITLE, + MONO_BTLS_X509_NAME_ENTRY_TYPE_SURNAME, + MONO_BTLS_X509_NAME_ENTRY_TYPE_GIVEN_NAME, + MONO_BTLS_X509_NAME_ENTRY_TYPE_INITIAL +} MonoBtlsX509NameEntryType; + +MonoBtlsX509Name * +mono_btls_x509_name_from_name (X509_NAME *name); + +MonoBtlsX509Name * +mono_btls_x509_name_copy (X509_NAME *xn); + +void +mono_btls_x509_name_free (MonoBtlsX509Name *name); + +X509_NAME * +mono_btls_x509_name_peek_name (MonoBtlsX509Name *name); + +MonoBtlsX509Name * +mono_btls_x509_name_from_data (const void *data, int len, int use_canon_enc); + +int +mono_btls_x509_name_print_bio (MonoBtlsX509Name *name, BIO *bio); + +int +mono_btls_x509_name_print_string (MonoBtlsX509Name *name, char *buffer, int size); + +int +mono_btls_x509_name_get_raw_data (MonoBtlsX509Name *name, void **buffer, int use_canon_enc); + +int64_t +mono_btls_x509_name_hash (MonoBtlsX509Name *name); + +int64_t +mono_btls_x509_name_hash_old (MonoBtlsX509Name *name); + +int +mono_btls_x509_name_get_entry_count (MonoBtlsX509Name *name); + +MonoBtlsX509NameEntryType +mono_btls_x509_name_get_entry_type (MonoBtlsX509Name *name, int index); + +int +mono_btls_x509_name_get_entry_oid (MonoBtlsX509Name *name, int index, char *buffer, int size); + +int +mono_btls_x509_name_get_entry_oid_data (MonoBtlsX509Name *name, int index, const void **data); + +int +mono_btls_x509_name_get_entry_value (MonoBtlsX509Name *name, int index, int *tag, unsigned char **str); + +#endif /* __btls__btls_x509_name__ */ diff --git a/mono/btls/btls-x509-revoked.c b/mono/btls/btls-x509-revoked.c new file mode 100644 index 0000000000..bf9af79de4 --- /dev/null +++ b/mono/btls/btls-x509-revoked.c @@ -0,0 +1,72 @@ +// +// btls-x509-revoked.c +// MonoBtls +// +// Created by Martin Baulig on 3/23/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include + +struct MonoBtlsX509Revoked { + MonoBtlsX509Crl *owner; + X509_REVOKED *revoked; +}; + +MONO_API MonoBtlsX509Revoked * +mono_btls_x509_revoked_new (MonoBtlsX509Crl *owner, X509_REVOKED *revoked) +{ + MonoBtlsX509Revoked *instance; + + instance = OPENSSL_malloc (sizeof (MonoBtlsX509Revoked)); + memset (instance, 0, sizeof (MonoBtlsX509Revoked)); + + instance->owner = mono_btls_x509_crl_ref (owner); + instance->revoked = revoked; + return instance; +} + +MONO_API void +mono_btls_x509_revoked_free (MonoBtlsX509Revoked *revoked) +{ + mono_btls_x509_crl_free (revoked->owner); + OPENSSL_free (revoked); +} + +MONO_API int +mono_btls_x509_revoked_get_serial_number (MonoBtlsX509Revoked *revoked, char *buffer, int size) +{ + ASN1_INTEGER *serial; + + serial = revoked->revoked->serialNumber; + if (serial->length == 0 || serial->length+1 > size) + return 0; + + memcpy (buffer, serial->data, serial->length); + return serial->length; +} + +MONO_API int64_t +mono_btls_x509_revoked_get_revocation_date (MonoBtlsX509Revoked *revoked) +{ + ASN1_TIME *date; + + date = revoked->revoked->revocationDate; + if (!date) + return 0; + + return mono_btls_util_asn1_time_to_ticks (date); +} + +MONO_API int +mono_btls_x509_revoked_get_reason (MonoBtlsX509Revoked *revoked) +{ + return revoked->revoked->reason; +} + +MONO_API int +mono_btls_x509_revoked_get_sequence (MonoBtlsX509Revoked *revoked) +{ + return revoked->revoked->sequence; +} + diff --git a/mono/btls/btls-x509-revoked.h b/mono/btls/btls-x509-revoked.h new file mode 100644 index 0000000000..592fc9316a --- /dev/null +++ b/mono/btls/btls-x509-revoked.h @@ -0,0 +1,34 @@ +// +// btls-x509-revoked.h +// MonoBtls +// +// Created by Martin Baulig on 3/23/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_revoked__ +#define __btls__btls_x509_revoked__ + +#include +#include +#include + +MonoBtlsX509Revoked * +mono_btls_x509_revoked_new (MonoBtlsX509Crl *owner, X509_REVOKED *revoked); + +void +mono_btls_x509_revoked_free (MonoBtlsX509Revoked *revoked); + +int +mono_btls_x509_revoked_get_serial_number (MonoBtlsX509Revoked *revoked, char *buffer, int size); + +int64_t +mono_btls_x509_revoked_get_revocation_date (MonoBtlsX509Revoked *revoked); + +int +mono_btls_x509_revoked_get_reason (MonoBtlsX509Revoked *revoked); + +int +mono_btls_x509_revoked_get_sequence (MonoBtlsX509Revoked *revoked); + +#endif /* __btls__btls_x509_revoked__ */ diff --git a/mono/btls/btls-x509-store-ctx.c b/mono/btls/btls-x509-store-ctx.c new file mode 100644 index 0000000000..8bbb732ac7 --- /dev/null +++ b/mono/btls/btls-x509-store-ctx.c @@ -0,0 +1,217 @@ +// +// btls-x509-store-ctx.c +// MonoBtls +// +// Created by Martin Baulig on 3/5/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include + +struct MonoBtlsX509StoreCtx { + int owns; + X509_STORE_CTX *ctx; + CRYPTO_refcount_t references; + MonoBtlsX509Store *store; + MonoBtlsX509Chain *chain; +}; + +MONO_API MonoBtlsX509StoreCtx * +mono_btls_x509_store_ctx_from_ptr (X509_STORE_CTX *ptr) +{ + MonoBtlsX509StoreCtx *ctx; + + ctx = OPENSSL_malloc (sizeof(MonoBtlsX509StoreCtx)); + if (!ctx) + return NULL; + + memset (ctx, 0, sizeof (MonoBtlsX509StoreCtx)); + ctx->ctx = ptr; + ctx->references = 1; + return ctx; +} + +MONO_API MonoBtlsX509StoreCtx * +mono_btls_x509_store_ctx_new (void) +{ + MonoBtlsX509StoreCtx *ctx; + + ctx = OPENSSL_malloc (sizeof(MonoBtlsX509StoreCtx)); + if (!ctx) + return NULL; + + memset (ctx, 0, sizeof (MonoBtlsX509StoreCtx)); + ctx->ctx = X509_STORE_CTX_new (); + ctx->references = 1; + ctx->owns = 1; + return ctx; +} + +MONO_API MonoBtlsX509StoreCtx * +mono_btls_x509_store_ctx_up_ref (MonoBtlsX509StoreCtx *ctx) +{ + CRYPTO_refcount_inc (&ctx->references); + return ctx; +} + +MONO_API int +mono_btls_x509_store_ctx_free (MonoBtlsX509StoreCtx *ctx) +{ + if (!CRYPTO_refcount_dec_and_test_zero (&ctx->references)) + return 0; + + if (ctx->owns) { + X509_STORE_CTX_cleanup (ctx->ctx); + X509_STORE_CTX_free (ctx->ctx); + ctx->owns = 0; + } + if (ctx->store) { + mono_btls_x509_store_free (ctx->store); + ctx->store = NULL; + } + if (ctx->chain) { + mono_btls_x509_chain_free (ctx->chain); + ctx->chain = NULL; + } + OPENSSL_free (ctx); + return 1; +} + +MONO_API int +mono_btls_x509_store_ctx_get_error (MonoBtlsX509StoreCtx *ctx, const char **error_string) +{ + int error; + + error = X509_STORE_CTX_get_error (ctx->ctx); + if (error_string) + *error_string = X509_verify_cert_error_string (error); + return error; +} + +MONO_API int +mono_btls_x509_store_ctx_get_error_depth (MonoBtlsX509StoreCtx *ctx) +{ + return X509_STORE_CTX_get_error_depth (ctx->ctx); +} + +MONO_API MonoBtlsX509Chain * +mono_btls_x509_store_ctx_get_chain (MonoBtlsX509StoreCtx *ctx) +{ + STACK_OF(X509) *certs; + + certs = X509_STORE_CTX_get_chain (ctx->ctx); + if (!certs) + return NULL; + + return mono_btls_x509_chain_from_certs (certs); +} + +MONO_API MonoBtlsX509Chain * +mono_btls_x509_store_ctx_get_untrusted (MonoBtlsX509StoreCtx *ctx) +{ + STACK_OF(X509) *untrusted; + + /* + * Unfortunately, there is no accessor function for this. + * + * This is the set of certificate that's passed in by + * X509_STORE_CTX_init() and X509_STORE_CTX_set_chain(). + */ + untrusted = ctx->ctx->untrusted; + if (!untrusted) + return NULL; + + return mono_btls_x509_chain_from_certs (untrusted); +} + +MONO_API int +mono_btls_x509_store_ctx_init (MonoBtlsX509StoreCtx *ctx, + MonoBtlsX509Store *store, MonoBtlsX509Chain *chain) +{ + STACK_OF(X509) *certs; + X509 *leaf; + int ret; + + if (ctx->store) + return 0; + + certs = mono_btls_x509_chain_peek_certs (chain); + if (!certs || !sk_X509_num (certs)) + return 0; + + ctx->store = mono_btls_x509_store_up_ref(store); + ctx->chain = mono_btls_x509_chain_up_ref(chain); + + leaf = sk_X509_value (certs, 0); + ret = X509_STORE_CTX_init (ctx->ctx, mono_btls_x509_store_peek_store (store), leaf, certs); + if (ret != 1) + return ret; + + X509_STORE_CTX_set_app_data (ctx->ctx, ctx); + return 1; +} + +MONO_API int +mono_btls_x509_store_ctx_set_param (MonoBtlsX509StoreCtx *ctx, MonoBtlsX509VerifyParam *param) +{ + return X509_VERIFY_PARAM_set1 (X509_STORE_CTX_get0_param (ctx->ctx), mono_btls_x509_verify_param_peek_param (param)); +} + +MONO_API int +mono_btls_x509_store_ctx_verify_cert (MonoBtlsX509StoreCtx *ctx) +{ + return X509_verify_cert (ctx->ctx); +} + +MONO_API X509 * +mono_btls_x509_store_ctx_get_by_subject (MonoBtlsX509StoreCtx *ctx, MonoBtlsX509Name *name) +{ + X509_OBJECT obj; + X509 *x509; + int ret; + + ret = X509_STORE_get_by_subject (ctx->ctx, X509_LU_X509, mono_btls_x509_name_peek_name (name), &obj); + if (ret != X509_LU_X509) { + X509_OBJECT_free_contents (&obj); + return NULL; + } + + x509 = X509_up_ref (obj.data.x509); + return x509; +} + +MONO_API X509 * +mono_btls_x509_store_ctx_get_current_cert (MonoBtlsX509StoreCtx *ctx) +{ + X509 *x509 = X509_STORE_CTX_get_current_cert (ctx->ctx); + if (!x509) + return NULL; + return X509_up_ref (x509); +} + +MONO_API X509 * +mono_btls_x509_store_ctx_get_current_issuer (MonoBtlsX509StoreCtx *ctx) +{ + X509 *x509 = X509_STORE_CTX_get0_current_issuer (ctx->ctx); + if (!x509) + return NULL; + return X509_up_ref (x509); +} + +MONO_API MonoBtlsX509VerifyParam * +mono_btls_x509_store_ctx_get_verify_param (MonoBtlsX509StoreCtx *ctx) +{ + X509_VERIFY_PARAM *param; + + param = X509_STORE_CTX_get0_param (ctx->ctx); + if (!param) + return NULL; + + return mono_btls_x509_verify_param_from_store_ctx (ctx, param); +} + +MONO_API int +mono_btls_x509_store_ctx_get_foo (MonoBtlsX509StoreCtx *ctx) +{ + return 0; +} diff --git a/mono/btls/btls-x509-store-ctx.h b/mono/btls/btls-x509-store-ctx.h new file mode 100644 index 0000000000..188092e0cd --- /dev/null +++ b/mono/btls/btls-x509-store-ctx.h @@ -0,0 +1,66 @@ +// +// btls-x509-store-ctx.h +// MonoBtls +// +// Created by Martin Baulig on 3/3/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_store_ctx__ +#define __btls__btls_x509_store_ctx__ + +#include +#include +#include +#include +#include +#include + +MonoBtlsX509StoreCtx * +mono_btls_x509_store_ctx_from_ptr (X509_STORE_CTX *ptr); + +MonoBtlsX509StoreCtx * +mono_btls_x509_store_ctx_new (void); + +MonoBtlsX509StoreCtx * +mono_btls_x509_store_ctx_up_ref (MonoBtlsX509StoreCtx *ctx); + +int +mono_btls_x509_store_ctx_free (MonoBtlsX509StoreCtx *ctx); + +int +mono_btls_x509_store_ctx_get_error (MonoBtlsX509StoreCtx *ctx, const char **error_string); + +int +mono_btls_x509_store_ctx_get_error_depth (MonoBtlsX509StoreCtx *ctx); + +MonoBtlsX509Chain * +mono_btls_x509_store_ctx_get_chain (MonoBtlsX509StoreCtx *ctx); + +X509 * +mono_btls_x509_store_ctx_get_current_cert (MonoBtlsX509StoreCtx *ctx); + +X509 * +mono_btls_x509_store_ctx_get_current_issuer (MonoBtlsX509StoreCtx *ctx); + +int +mono_btls_x509_store_ctx_init (MonoBtlsX509StoreCtx *ctx, + MonoBtlsX509Store *store, MonoBtlsX509Chain *chain); + +int +mono_btls_x509_store_ctx_set_param (MonoBtlsX509StoreCtx *ctx, MonoBtlsX509VerifyParam *param); + +X509 * +mono_btls_x509_store_ctx_get_by_subject (MonoBtlsX509StoreCtx *ctx, MonoBtlsX509Name *name); + +int +mono_btls_x509_store_ctx_verify_cert (MonoBtlsX509StoreCtx *ctx); + +MonoBtlsX509VerifyParam * +mono_btls_x509_store_ctx_get_verify_param (MonoBtlsX509StoreCtx *ctx); + +MonoBtlsX509Chain * +mono_btls_x509_store_ctx_get_untrusted (MonoBtlsX509StoreCtx *ctx); + +#endif /* defined(__btls__btls_x509_store_ctx__) */ + diff --git a/mono/btls/btls-x509-store.c b/mono/btls/btls-x509-store.c new file mode 100644 index 0000000000..3534739a6e --- /dev/null +++ b/mono/btls/btls-x509-store.c @@ -0,0 +1,110 @@ +// +// btls-x509-store.c +// MonoBtls +// +// Created by Martin Baulig on 3/3/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include + +struct MonoBtlsX509Store { + X509_STORE *store; + CRYPTO_refcount_t references; +}; + +MONO_API MonoBtlsX509Store * +mono_btls_x509_store_from_store (X509_STORE *ctx) +{ + MonoBtlsX509Store *store; + + store = OPENSSL_malloc (sizeof(MonoBtlsX509Store)); + if (!store) + return NULL; + + memset (store, 0, sizeof(MonoBtlsX509Store)); + store->store = ctx; + CRYPTO_refcount_inc (&store->store->references); + store->references = 1; + return store; +} + +MONO_API MonoBtlsX509Store * +mono_btls_x509_store_from_ctx (X509_STORE_CTX *ctx) +{ + return mono_btls_x509_store_from_store (ctx->ctx); +} + +MONO_API MonoBtlsX509Store * +mono_btls_x509_store_new (void) +{ + MonoBtlsX509Store *store; + + store = OPENSSL_malloc (sizeof(MonoBtlsX509Store)); + if (!store) + return NULL; + + memset (store, 0, sizeof(MonoBtlsX509Store)); + store->store = X509_STORE_new (); + store->references = 1; + return store; +} + +MONO_API X509_STORE * +mono_btls_x509_store_peek_store (MonoBtlsX509Store *store) +{ + return store->store; +} + +MONO_API MonoBtlsX509Store * +mono_btls_x509_store_from_ssl_ctx (MonoBtlsSslCtx *ctx) +{ + X509_STORE *store = mono_btls_ssl_ctx_peek_store (ctx); + return mono_btls_x509_store_from_store (store); +} + +MONO_API int +mono_btls_x509_store_free (MonoBtlsX509Store *store) +{ + if (!CRYPTO_refcount_dec_and_test_zero(&store->references)) + return 0; + + if (store->store) { + X509_STORE_free (store->store); + store->store = NULL; + } + OPENSSL_free (store); + return 1; +} + +MONO_API MonoBtlsX509Store * +mono_btls_x509_store_up_ref (MonoBtlsX509Store *store) +{ + CRYPTO_refcount_inc (&store->references); + return store; +} + +MONO_API int +mono_btls_x509_store_add_cert (MonoBtlsX509Store *store, X509 *cert) +{ + return X509_STORE_add_cert (store->store, cert); +} + +MONO_API int +mono_btls_x509_store_load_locations (MonoBtlsX509Store *store, const char *file, const char *path) +{ + return X509_STORE_load_locations (store->store, file, path); +} + +MONO_API int +mono_btls_x509_store_set_default_paths (MonoBtlsX509Store *store) +{ + return X509_STORE_set_default_paths (store->store); +} + +MONO_API int +mono_btls_x509_store_get_count (MonoBtlsX509Store *store) +{ + return (int)sk_X509_OBJECT_num (store->store->objs); +} + diff --git a/mono/btls/btls-x509-store.h b/mono/btls/btls-x509-store.h new file mode 100644 index 0000000000..67ffe00cd3 --- /dev/null +++ b/mono/btls/btls-x509-store.h @@ -0,0 +1,46 @@ +// +// btls-x509-store.h +// MonoBtls +// +// Created by Martin Baulig on 3/3/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_store__ +#define __btls__btls_x509_store__ + +#include +#include + +MonoBtlsX509Store * +mono_btls_x509_store_new (void); + +MonoBtlsX509Store * +mono_btls_x509_store_from_ctx (X509_STORE_CTX *ctx); + +MonoBtlsX509Store * +mono_btls_x509_store_from_ssl_ctx (MonoBtlsSslCtx *ctx); + +MonoBtlsX509Store * +mono_btls_x509_store_up_ref (MonoBtlsX509Store *store); + +int +mono_btls_x509_store_free (MonoBtlsX509Store *store); + +X509_STORE * +mono_btls_x509_store_peek_store (MonoBtlsX509Store *store); + +int +mono_btls_x509_store_add_cert (MonoBtlsX509Store *store, X509 *cert); + +int +mono_btls_x509_store_load_locations (MonoBtlsX509Store *store, const char *file, const char *path); + +int +mono_btls_x509_store_set_default_paths (MonoBtlsX509Store *store); + +int +mono_btls_x509_store_get_count (MonoBtlsX509Store *store); + +#endif /* defined(__btls__btls_x509_store__) */ + diff --git a/mono/btls/btls-x509-verify-param.c b/mono/btls/btls-x509-verify-param.c new file mode 100644 index 0000000000..24be3da8ca --- /dev/null +++ b/mono/btls/btls-x509-verify-param.c @@ -0,0 +1,221 @@ +// +// btls-x509-verify-param.c +// MonoBtls +// +// Created by Martin Baulig on 3/5/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#include +#include + +struct MonoBtlsX509VerifyParam { + int owns; + MonoBtlsX509StoreCtx *owner; + X509_VERIFY_PARAM *param; +}; + +MONO_API MonoBtlsX509VerifyParam * +mono_btls_x509_verify_param_new (void) +{ + MonoBtlsX509VerifyParam *param; + + param = OPENSSL_malloc (sizeof(MonoBtlsX509VerifyParam)); + if (!param) + return NULL; + memset (param, 0, sizeof (MonoBtlsX509VerifyParam)); + param->param = X509_VERIFY_PARAM_new(); + param->owns = 1; + return param; +} + +MONO_API MonoBtlsX509VerifyParam * +mono_btls_x509_verify_param_from_store_ctx (MonoBtlsX509StoreCtx *ctx, X509_VERIFY_PARAM *param) +{ + MonoBtlsX509VerifyParam *instance; + + instance = OPENSSL_malloc (sizeof(MonoBtlsX509VerifyParam)); + if (!instance) + return NULL; + memset (instance, 0, sizeof (MonoBtlsX509VerifyParam)); + instance->param = param; + instance->owner = mono_btls_x509_store_ctx_up_ref (ctx); + return instance; +} + +MONO_API MonoBtlsX509VerifyParam * +mono_btls_x509_verify_param_copy (const MonoBtlsX509VerifyParam *from) +{ + MonoBtlsX509VerifyParam *param; + + param = mono_btls_x509_verify_param_new (); + if (!param) + return NULL; + + X509_VERIFY_PARAM_set1 (param->param, from->param); + return param; +} + +MONO_API const X509_VERIFY_PARAM * +mono_btls_x509_verify_param_peek_param (const MonoBtlsX509VerifyParam *param) +{ + return param->param; +} + +MONO_API int +mono_btls_x509_verify_param_can_modify (MonoBtlsX509VerifyParam *param) +{ + return param->owns; +} + +MONO_API MonoBtlsX509VerifyParam * +mono_btls_x509_verify_param_lookup (const char *name) +{ + MonoBtlsX509VerifyParam *param; + const X509_VERIFY_PARAM *p; + + p = X509_VERIFY_PARAM_lookup(name); + if (!p) + return NULL; + + param = OPENSSL_malloc (sizeof(MonoBtlsX509VerifyParam)); + if (!param) + return NULL; + memset (param, 0, sizeof (MonoBtlsX509VerifyParam)); + param->param = (X509_VERIFY_PARAM *)p; + return param; +} + +MONO_API void +mono_btls_x509_verify_param_free (MonoBtlsX509VerifyParam *param) +{ + if (param->owns) { + if (param->param) { + X509_VERIFY_PARAM_free (param->param); + param->param = NULL; + } + } + if (param->owner) { + mono_btls_x509_store_ctx_free (param->owner); + param->owner = NULL; + } + OPENSSL_free (param); +} + +MONO_API int +mono_btls_x509_verify_param_set_name (MonoBtlsX509VerifyParam *param, const char *name) +{ + if (!param->owns) + return -1; + return X509_VERIFY_PARAM_set1_name (param->param, name); +} + +MONO_API int +mono_btls_x509_verify_param_set_host (MonoBtlsX509VerifyParam *param, const char *host, int namelen) +{ + if (!param->owns) + return -1; + return X509_VERIFY_PARAM_set1_host (param->param, host, namelen); +} + +MONO_API int +mono_btls_x509_verify_param_add_host (MonoBtlsX509VerifyParam *param, const char *host, int namelen) +{ + if (!param->owns) + return -1; + return X509_VERIFY_PARAM_set1_host (param->param, host, namelen); +} + +MONO_API uint64_t +mono_btls_x509_verify_param_get_flags (MonoBtlsX509VerifyParam *param) +{ + return X509_VERIFY_PARAM_get_flags (param->param); +} + +MONO_API int +mono_btls_x509_verify_param_set_flags (MonoBtlsX509VerifyParam *param, uint64_t flags) +{ + if (!param->owns) + return -1; + return X509_VERIFY_PARAM_set_flags (param->param, flags); +} + +MONO_API MonoBtlsX509VerifyFlags +mono_btls_x509_verify_param_get_mono_flags (MonoBtlsX509VerifyParam *param) +{ + MonoBtlsX509VerifyFlags current; + uint64_t flags; + + if (!param->owns) + return -1; + + current = 0; + flags = X509_VERIFY_PARAM_get_flags (param->param); + + if (flags & X509_V_FLAG_CRL_CHECK) + current |= MONO_BTLS_X509_VERIFY_FLAGS_CRL_CHECK; + if (flags & X509_V_FLAG_CRL_CHECK_ALL) + current |= MONO_BTLS_X509_VERIFY_FLAGS_CRL_CHECK_ALL; + if (flags & X509_V_FLAG_X509_STRICT) + current |= MONO_BTLS_X509_VERIFY_FLAGS_X509_STRICT; + + return current; +} + +MONO_API int +mono_btls_x509_verify_param_set_mono_flags (MonoBtlsX509VerifyParam *param, MonoBtlsX509VerifyFlags flags) +{ + uint64_t current; + + if (!param->owns) + return -1; + + current = X509_VERIFY_PARAM_get_flags (param->param); + if (flags & MONO_BTLS_X509_VERIFY_FLAGS_CRL_CHECK) + current |= X509_V_FLAG_CRL_CHECK; + if (flags & MONO_BTLS_X509_VERIFY_FLAGS_CRL_CHECK_ALL) + current |= X509_V_FLAG_CRL_CHECK_ALL; + if (flags & MONO_BTLS_X509_VERIFY_FLAGS_X509_STRICT) + current |= X509_V_FLAG_X509_STRICT; + + return X509_VERIFY_PARAM_set_flags (param->param, current); +} + +MONO_API int +mono_btls_x509_verify_param_set_purpose (MonoBtlsX509VerifyParam *param, MonoBtlsX509Purpose purpose) +{ + if (!param->owns) + return -1; + return X509_VERIFY_PARAM_set_purpose (param->param, purpose); +} + +MONO_API int +mono_btls_x509_verify_param_get_depth (MonoBtlsX509VerifyParam *param) +{ + return X509_VERIFY_PARAM_get_depth (param->param); +} + +MONO_API int +mono_btls_x509_verify_param_set_depth (MonoBtlsX509VerifyParam *param, int depth) +{ + if (!param->owns) + return -1; + X509_VERIFY_PARAM_set_depth (param->param, depth); + return 1; +} + +MONO_API int +mono_btls_x509_verify_param_set_time (MonoBtlsX509VerifyParam *param, int64_t time) +{ + if (!param->owns) + return -1; + X509_VERIFY_PARAM_set_time (param->param, time); + return 1; +} + +MONO_API char * +mono_btls_x509_verify_param_get_peername (MonoBtlsX509VerifyParam *param) +{ + char *peer = X509_VERIFY_PARAM_get0_peername (param->param); + return peer; +} diff --git a/mono/btls/btls-x509-verify-param.h b/mono/btls/btls-x509-verify-param.h new file mode 100644 index 0000000000..e85d547fb3 --- /dev/null +++ b/mono/btls/btls-x509-verify-param.h @@ -0,0 +1,81 @@ +// +// btls-x509-verify-param.h +// MonoBtls +// +// Created by Martin Baulig on 3/3/16. +// Copyright © 2016 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509_verify_param__ +#define __btls__btls_x509_verify_param__ + +#include +#include +#include + +typedef enum { + MONO_BTLS_X509_VERIFY_FLAGS_DEFAULT = 0, + MONO_BTLS_X509_VERIFY_FLAGS_CRL_CHECK = 1, + MONO_BTLS_X509_VERIFY_FLAGS_CRL_CHECK_ALL = 2, + MONO_BTLS_X509_VERIFY_FLAGS_X509_STRICT = 4 +} MonoBtlsX509VerifyFlags; + +MonoBtlsX509VerifyParam * +mono_btls_x509_verify_param_new (void); + +MonoBtlsX509VerifyParam * +mono_btls_x509_verify_param_from_store_ctx (MonoBtlsX509StoreCtx *ctx, X509_VERIFY_PARAM *param); + +MonoBtlsX509VerifyParam * +mono_btls_x509_verify_param_copy (const MonoBtlsX509VerifyParam *from); + +void +mono_btls_x509_verify_param_free (MonoBtlsX509VerifyParam *param); + +const X509_VERIFY_PARAM * +mono_btls_x509_verify_param_peek_param (const MonoBtlsX509VerifyParam *param); + +int +mono_btls_x509_verify_param_can_modify (MonoBtlsX509VerifyParam *param); + +MonoBtlsX509VerifyParam * +mono_btls_x509_verify_param_lookup (const char *name); + +int +mono_btls_x509_verify_param_set_name (MonoBtlsX509VerifyParam *param, const char *name); + +int +mono_btls_x509_verify_param_set_host (MonoBtlsX509VerifyParam *param, const char *host, int namelen); + +int +mono_btls_x509_verify_param_add_host (MonoBtlsX509VerifyParam *param, const char *host, int namelen); + +uint64_t +mono_btls_x509_verify_param_get_flags (MonoBtlsX509VerifyParam *param); + +int +mono_btls_x509_verify_param_set_flags (MonoBtlsX509VerifyParam *param, uint64_t flags); + +MonoBtlsX509VerifyFlags +mono_btls_x509_verify_param_get_mono_flags (MonoBtlsX509VerifyParam *param); + +int +mono_btls_x509_verify_param_set_mono_flags (MonoBtlsX509VerifyParam *param, MonoBtlsX509VerifyFlags flags); + +int +mono_btls_x509_verify_param_set_purpose (MonoBtlsX509VerifyParam *param, MonoBtlsX509Purpose purpose); + +int +mono_btls_x509_verify_param_get_depth (MonoBtlsX509VerifyParam *param); + +int +mono_btls_x509_verify_param_set_depth (MonoBtlsX509VerifyParam *param, int depth); + +int +mono_btls_x509_verify_param_set_time (MonoBtlsX509VerifyParam *param, int64_t time); + +char * +mono_btls_x509_verify_param_get_peername (MonoBtlsX509VerifyParam *param); + +#endif /* defined(__btls__btls_x509_verify_param__) */ + diff --git a/mono/btls/btls-x509.c b/mono/btls/btls-x509.c new file mode 100644 index 0000000000..473d94fbaf --- /dev/null +++ b/mono/btls/btls-x509.c @@ -0,0 +1,441 @@ +// +// btls-x509.c +// MonoBtls +// +// Created by Martin Baulig on 14/11/15. +// Copyright (c) 2015 Xamarin. All rights reserved. +// + +#include +#include +#include + +MONO_API X509 * +mono_btls_x509_from_data (const void *buf, int len, MonoBtlsX509Format format) +{ + BIO *bio; + X509 *cert = NULL; + + bio = BIO_new_mem_buf ((void *)buf, len); + switch (format) { + case MONO_BTLS_X509_FORMAT_DER: + cert = d2i_X509_bio (bio, NULL); + break; + case MONO_BTLS_X509_FORMAT_PEM: + cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL); + break; + } + BIO_free (bio); + return cert; +} + +MONO_API X509 * +mono_btls_x509_up_ref (X509 *x509) +{ + X509_up_ref (x509); + return x509; +} + +MONO_API void +mono_btls_x509_free (X509 *x509) +{ + X509_free (x509); +} + +MONO_API X509 * +mono_btls_x509_dup (X509 *x509) +{ + return X509_dup (x509); +} + +MONO_API MonoBtlsX509Name * +mono_btls_x509_get_subject_name (X509 *x509) +{ + return mono_btls_x509_name_copy (X509_get_subject_name (x509)); +} + +MONO_API MonoBtlsX509Name * +mono_btls_x509_get_issuer_name (X509 *x509) +{ + return mono_btls_x509_name_copy (X509_get_issuer_name (x509)); +} + +MONO_API int +mono_btls_x509_get_subject_name_string (X509 *name, char *buffer, int size) +{ + *buffer = 0; + return X509_NAME_oneline (X509_get_subject_name (name), buffer, size) != NULL; +} + +MONO_API int +mono_btls_x509_get_issuer_name_string (X509 *name, char *buffer, int size) +{ + *buffer = 0; + return X509_NAME_oneline (X509_get_issuer_name (name), buffer, size) != NULL; +} + +MONO_API int +mono_btls_x509_get_raw_data (X509 *x509, BIO *bio, MonoBtlsX509Format format) +{ + switch (format) { + case MONO_BTLS_X509_FORMAT_DER: + return i2d_X509_bio (bio, x509); + case MONO_BTLS_X509_FORMAT_PEM: + return PEM_write_bio_X509 (bio, x509); + default: + return 0; + } +} + +MONO_API int +mono_btls_x509_cmp (const X509 *a, const X509 *b) +{ + return X509_cmp (a, b); +} + +MONO_API int +mono_btls_x509_get_hash (X509 *x509, const void **data) +{ + X509_check_purpose (x509, -1, 0); + *data = x509->sha1_hash; + return SHA_DIGEST_LENGTH; +} + +MONO_API int64_t +mono_btls_x509_get_not_before (X509 *x509) +{ + return mono_btls_util_asn1_time_to_ticks (X509_get_notBefore (x509)); +} + +MONO_API int64_t +mono_btls_x509_get_not_after (X509 *x509) +{ + return mono_btls_util_asn1_time_to_ticks (X509_get_notAfter (x509)); +} + +MONO_API int +mono_btls_x509_get_public_key (X509 *x509, BIO *bio) +{ + EVP_PKEY *pkey; + uint8_t *data = NULL; + int ret; + + pkey = X509_get_pubkey (x509); + if (!pkey) + return -1; + + ret = i2d_PublicKey (pkey, &data); + + if (ret > 0 && data) { + ret = BIO_write (bio, data, ret); + OPENSSL_free (data); + } + + EVP_PKEY_free (pkey); + return ret; +} + +MONO_API int +mono_btls_x509_get_serial_number (X509 *x509, char *buffer, int size, int mono_style) +{ + ASN1_INTEGER *serial; + unsigned char *temp, *p; + int len, idx; + + serial = X509_get_serialNumber (x509); + if (serial->length == 0 || serial->length+1 > size) + return 0; + + if (!mono_style) { + memcpy (buffer, serial->data, serial->length); + return serial->length; + } + + temp = OPENSSL_malloc (serial->length + 1); + if (!temp) + return 0; + + p = temp; + len = i2c_ASN1_INTEGER (serial, &p); + + if (!len) { + OPENSSL_free (temp); + return 0; + } + + for (idx = 0; idx < len; idx++) { + buffer [idx] = *(--p); + } + buffer [len] = 0; + + OPENSSL_free (temp); + return len; +} + +MONO_API int +mono_btls_x509_get_public_key_algorithm (X509 *x509, char *buffer, int size) +{ + X509_PUBKEY *pkey; + ASN1_OBJECT *ppkalg; + int ret; + + *buffer = 0; + pkey = X509_get_X509_PUBKEY (x509); + if (!pkey) + return 0; + + ret = X509_PUBKEY_get0_param (&ppkalg, NULL, NULL, NULL, pkey); + if (!ret || !ppkalg) + return ret; + + return OBJ_obj2txt (buffer, size, ppkalg, 1); +} + +MONO_API int +mono_btls_x509_get_version (X509 *x509) +{ + return (int)X509_get_version (x509) + 1; +} + +MONO_API int +mono_btls_x509_get_signature_algorithm (X509 *x509, char *buffer, int size) +{ + const ASN1_OBJECT *obj; + int nid; + + *buffer = 0; + + nid = X509_get_signature_nid (x509); + + obj = OBJ_nid2obj (nid); + if (!obj) + return 0; + + return OBJ_obj2txt (buffer, size, obj, 1); +} + +MONO_API int +mono_btls_x509_get_public_key_asn1 (X509 *x509, char *out_oid, int oid_len, uint8_t **buffer, int *size) +{ + X509_PUBKEY *pkey; + ASN1_OBJECT *ppkalg; + const unsigned char *pk; + int pk_len; + int ret; + + if (out_oid) + *out_oid = 0; + + pkey = X509_get_X509_PUBKEY (x509); + if (!pkey || !pkey->public_key) + return 0; + + ret = X509_PUBKEY_get0_param (&ppkalg, &pk, &pk_len, NULL, pkey); + if (ret != 1 || !ppkalg || !pk) + return 0; + + if (out_oid) { + OBJ_obj2txt (out_oid, oid_len, ppkalg, 1); + } + + if (buffer) { + *size = pk_len; + *buffer = OPENSSL_malloc (pk_len); + if (!*buffer) + return 0; + + memcpy (*buffer, pk, pk_len); + } + + return 1; + +} + +MONO_API int +mono_btls_x509_get_public_key_parameters (X509 *x509, char *out_oid, int oid_len, uint8_t **buffer, int *size) +{ + X509_PUBKEY *pkey; + X509_ALGOR *algor; + ASN1_OBJECT *paobj; + int ptype; + void *pval; + int ret; + + if (out_oid) + *out_oid = 0; + + pkey = X509_get_X509_PUBKEY (x509); + + ret = X509_PUBKEY_get0_param (NULL, NULL, NULL, &algor, pkey); + if (ret != 1 || !algor) + return 0; + + X509_ALGOR_get0 (&paobj, &ptype, &pval, algor); + + if (ptype != V_ASN1_NULL && ptype != V_ASN1_SEQUENCE) + return 0; + + if (ptype == V_ASN1_NULL) { + uint8_t *ptr; + + *size = 2; + *buffer = OPENSSL_malloc (2); + if (!*buffer) + return 0; + + ptr = *buffer; + *ptr++ = 0x05; + *ptr++ = 0x00; + + if (out_oid) + OBJ_obj2txt (out_oid, oid_len, paobj, 1); + + return 1; + } else if (ptype == V_ASN1_SEQUENCE) { + ASN1_STRING *pstr = pval; + + *size = pstr->length; + *buffer = OPENSSL_malloc (pstr->length); + if (!*buffer) + return 0; + + memcpy (*buffer, pstr->data, pstr->length); + + if (out_oid) + OBJ_obj2txt (out_oid, oid_len, paobj, 1); + + return 1; + } else { + return 0; + } +} + +MONO_API EVP_PKEY * +mono_btls_x509_get_pubkey (X509 *x509) +{ + return X509_get_pubkey (x509); +} + +MONO_API int +mono_btls_x509_get_subject_key_identifier (X509 *x509, uint8_t **buffer, int *size) +{ + ASN1_OCTET_STRING *skid; + + *size = 0; + *buffer = NULL; + + if (X509_get_version (x509) != 2) + return 0; + + skid = X509_get_ext_d2i (x509, NID_subject_key_identifier, NULL, NULL); + if (!skid) + return 0; + + *size = skid->length; + *buffer = OPENSSL_malloc (*size); + if (!*buffer) + return 0; + + memcpy (*buffer, skid->data, *size); + return 1; +} + +MONO_API int +mono_btls_x509_print (X509 *x509, BIO *bio) +{ + return X509_print_ex (bio, x509, XN_FLAG_COMPAT, X509_FLAG_COMPAT); +} + +static int +get_trust_nid (MonoBtlsX509Purpose purpose) +{ + switch (purpose) { + case MONO_BTLS_X509_PURPOSE_SSL_CLIENT: + return NID_client_auth; + case MONO_BTLS_X509_PURPOSE_SSL_SERVER: + return NID_server_auth; + default: + return 0; + } +} + +MONO_API int +mono_btls_x509_add_trust_object (X509 *x509, MonoBtlsX509Purpose purpose) +{ + ASN1_OBJECT *trust; + int nid; + + nid = get_trust_nid (purpose); + if (!nid) + return 0; + + trust = ASN1_OBJECT_new (); + if (!trust) + return 0; + + trust->nid = nid; + return X509_add1_trust_object (x509, trust); +} + +MONO_API int +mono_btls_x509_add_reject_object (X509 *x509, MonoBtlsX509Purpose purpose) +{ + ASN1_OBJECT *reject; + int nid; + + nid = get_trust_nid (purpose); + if (!nid) + return 0; + + reject = ASN1_OBJECT_new (); + if (!reject) + return 0; + + reject->nid = nid; + return X509_add1_reject_object (x509, reject); +} + +MONO_API int +mono_btls_x509_add_explicit_trust (X509 *x509, MonoBtlsX509TrustKind kind) +{ + int ret = 0; + + if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_ALL) != 0) + kind |= MONO_BTLS_X509_TRUST_KIND_REJECT_CLIENT | MONO_BTLS_X509_TRUST_KIND_REJECT_SERVER; + + if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_ALL) != 0) + kind |= MONO_BTLS_X509_TRUST_KIND_TRUST_CLIENT | MONO_BTLS_X509_TRUST_KIND_TRUST_SERVER; + + + if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_CLIENT) != 0) { + ret = mono_btls_x509_add_reject_object (x509, MONO_BTLS_X509_PURPOSE_SSL_CLIENT); + if (!ret) + return ret; + } + + if ((kind & MONO_BTLS_X509_TRUST_KIND_REJECT_SERVER) != 0) { + ret = mono_btls_x509_add_reject_object (x509, MONO_BTLS_X509_PURPOSE_SSL_SERVER); + if (!ret) + return ret; + } + + if (ret) { + // Ignore any MONO_BTLS_X509_TRUST_KIND_TRUST_* settings if we added + // any kind of MONO_BTLS_X509_TRUST_KIND_REJECT_* before. + return ret; + } + + if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_CLIENT) != 0) { + ret = mono_btls_x509_add_trust_object (x509, MONO_BTLS_X509_PURPOSE_SSL_CLIENT); + if (!ret) + return ret; + } + + if ((kind & MONO_BTLS_X509_TRUST_KIND_TRUST_SERVER) != 0) { + ret = mono_btls_x509_add_trust_object (x509, MONO_BTLS_X509_PURPOSE_SSL_SERVER); + if (!ret) + return ret; + } + + return ret; +} diff --git a/mono/btls/btls-x509.h b/mono/btls/btls-x509.h new file mode 100644 index 0000000000..d913743133 --- /dev/null +++ b/mono/btls/btls-x509.h @@ -0,0 +1,127 @@ +// +// btls-x509.h +// MonoBtls +// +// Created by Martin Baulig on 14/11/15. +// Copyright (c) 2015 Xamarin. All rights reserved. +// + +#ifndef __btls__btls_x509__ +#define __btls__btls_x509__ + +#include +#include +#include + +typedef enum { + MONO_BTLS_X509_FORMAT_DER = 1, + MONO_BTLS_X509_FORMAT_PEM = 2 +} MonoBtlsX509Format; + +typedef enum { + MONO_BTLS_x509_FILE_TYPE_PEM = 1, // X509_FILETYPE_PEM + MONO_BTLS_x509_FILE_TYPE_ASN1 = 2, // X509_FILETYPE_ASN1 + MONO_BTLS_x509_FILE_TYPE_DEFAULT = 3, // X509_FILETYPE_DEFAULT +} MonoBtlsX509FileType; + +typedef enum { + MONO_BTLS_X509_PURPOSE_SSL_CLIENT = 1, + MONO_BTLS_X509_PURPOSE_SSL_SERVER = 2, + MONO_BTLS_X509_PURPOSE_NS_SSL_SERVER = 3, + MONO_BTLS_X509_PURPOSE_SMIME_SIGN = 4, + MONO_BTLS_X509_PURPOSE_SMIME_ENCRYPT = 5, + MONO_BTLS_X509_PURPOSE_CRL_SIGN = 6, + MONO_BTLS_X509_PURPOSE_ANY = 7, + MONO_BTLS_X509_PURPOSE_OCSP_HELPER = 8, + MONO_BTLS_X509_PURPOSE_TIMESTAMP_SIGN = 9, +} MonoBtlsX509Purpose; + +typedef enum { + MONO_BTLS_X509_TRUST_KIND_DEFAULT = 0, + MONO_BTLS_X509_TRUST_KIND_TRUST_CLIENT = 1, + MONO_BTLS_X509_TRUST_KIND_TRUST_SERVER = 2, + MONO_BTLS_X509_TRUST_KIND_TRUST_ALL = 4, + MONO_BTLS_X509_TRUST_KIND_REJECT_CLIENT = 32, + MONO_BTLS_X509_TRUST_KIND_REJECT_SERVER = 64, + MONO_BTLS_X509_TRUST_KIND_REJECT_ALL = 128 +} MonoBtlsX509TrustKind; + +X509 * +mono_btls_x509_from_data (const void *buf, int len, MonoBtlsX509Format format); + +X509 * +mono_btls_x509_up_ref (X509 *x509); + +void +mono_btls_x509_free (X509 *x509); + +X509 * +mono_btls_x509_dup (X509 *x509); + +MonoBtlsX509Name * +mono_btls_x509_get_subject_name (X509 *x509); + +MonoBtlsX509Name * +mono_btls_x509_get_issuer_name (X509 *x509); + +int +mono_btls_x509_get_subject_name_string (X509 *name, char *buffer, int size); + +int +mono_btls_x509_get_issuer_name_string (X509 *name, char *buffer, int size); + +int +mono_btls_x509_get_raw_data (X509 *x509, BIO *bio, MonoBtlsX509Format format); + +int +mono_btls_x509_cmp (const X509 *a, const X509 *b); + +int +mono_btls_x509_get_hash (X509 *x509, const void **data); + +int64_t +mono_btls_x509_get_not_before (X509 *x509); + +int64_t +mono_btls_x509_get_not_after (X509 *x509); + +int +mono_btls_x509_get_public_key (X509 *x509, BIO *bio); + +int +mono_btls_x509_get_public_key_parameters (X509 *x509, char *out_oid, int oid_len, uint8_t **buffer, int *size); + +int +mono_btls_x509_get_serial_number (X509 *x509, char *buffer, int size, int mono_style); + +int +mono_btls_x509_get_public_key_algorithm (X509 *x509, char *buffer, int size); + +int +mono_btls_x509_get_version (X509 *x509); + +int +mono_btls_x509_get_signature_algorithm (X509 *x509, char *buffer, int size); + +int +mono_btls_x509_get_public_key_asn1 (X509 *x509, char *out_oid, int oid_len, uint8_t **buffer, int *size); + +EVP_PKEY * +mono_btls_x509_get_pubkey (X509 *x509); + +int +mono_btls_x509_get_subject_key_identifier (X509 *x509, uint8_t **buffer, int *size); + +int +mono_btls_x509_print (X509 *x509, BIO *bio); + +int +mono_btls_x509_add_trust_object (X509 *x509, MonoBtlsX509Purpose purpose); + +int +mono_btls_x509_add_reject_object (X509 *x509, MonoBtlsX509Purpose purpose); + +int +mono_btls_x509_add_explicit_trust (X509 *x509, MonoBtlsX509TrustKind kind); + +#endif /* defined(__btls__btls_x509__) */ diff --git a/mono/btls/create-object-library.sh b/mono/btls/create-object-library.sh new file mode 100755 index 0000000000..8ceda08a77 --- /dev/null +++ b/mono/btls/create-object-library.sh @@ -0,0 +1,33 @@ +#!/bin/sh + +DIR=$1; shift +FILELIST=$1; shift +LOFILELIST=$1 ; shift +TARGET=$1; shift +STATIC=$1; shift +AR=$1; shift +RANLIB=$1; shift + +HEADER="# Generated by Martin's tool $0, not libtool" + +test -f $TARGET && exit 0 + +rm -f $FILELIST +rm -f $LOFILELIST + +while [ "$1" != "--" ]; do + file=$1; shift + filename=`basename $file` + LOFILE=$file.lo + echo "$HEADER" > $LOFILE + if [ "$STATIC" = "static" ]; then + echo "non_pic_object='$filename'" >> $LOFILE + else + echo "pic_object='$filename'" >> $LOFILE + fi + echo "$DIR/$file " >> $FILELIST + echo "$DIR/$LOFILE " >> $LOFILELIST +done + +(cd $DIR && $AR cr $TARGET `cat $FILELIST` && $RANLIB $TARGET) + diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 92cb607993..5fae5ea933 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -953,9 +953,7 @@ ICALL(MARSHAL_13, "Prelink", ves_icall_System_Runtime_InteropServices_Marshal_Pr ICALL(MARSHAL_14, "PrelinkAll", ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll) ICALL(MARSHAL_15, "PtrToStringAnsi(intptr)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi) ICALL(MARSHAL_16, "PtrToStringAnsi(intptr,int)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len) -#ifndef DISABLE_COM ICALL(MARSHAL_17, "PtrToStringBSTR", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR) -#endif ICALL(MARSHAL_18, "PtrToStringUni(intptr)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni) ICALL(MARSHAL_19, "PtrToStringUni(intptr,int)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringUni_len) ICALL(MARSHAL_20, "PtrToStructure(intptr,System.Type)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type) diff --git a/mono/metadata/metadata.c.REMOVED.git-id b/mono/metadata/metadata.c.REMOVED.git-id index a248df3cd0..e2def32057 100644 --- a/mono/metadata/metadata.c.REMOVED.git-id +++ b/mono/metadata/metadata.c.REMOVED.git-id @@ -1 +1 @@ -27115ccc9c1b1e384c9245ff8e976882159a9ed1 \ No newline at end of file +a5c505495191bdcc23d959d1c02162890e68ac9c \ No newline at end of file diff --git a/mono/metadata/object-offsets.h b/mono/metadata/object-offsets.h index e4965a512a..5c78288ec8 100644 --- a/mono/metadata/object-offsets.h +++ b/mono/metadata/object-offsets.h @@ -238,6 +238,8 @@ DECL_OFFSET(GSharedVtCallInfo, gsharedvt_in) #endif #if defined(TARGET_ARM64) +DECL_OFFSET (MonoContext, has_fregs) + DECL_OFFSET(GSharedVtCallInfo, stack_usage) DECL_OFFSET(GSharedVtCallInfo, gsharedvt_in) DECL_OFFSET(GSharedVtCallInfo, ret_marshal) diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c index 0a5ea615a0..6f5d1f82fb 100644 --- a/mono/metadata/reflection.c +++ b/mono/metadata/reflection.c @@ -2259,10 +2259,17 @@ mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc if (klass->wastypebuilder) { tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass); - is_dynamic = TRUE; } + guint gtd_type_argc = mono_class_get_generic_container (klass)->type_argc; + if (gtd_type_argc != type_argc) { + mono_loader_unlock (); + mono_error_set_argument (error, "types", "The generic type definition needs %d type arguments, but was instantiated with %d ", gtd_type_argc, type_argc); + return NULL; + } + + mono_loader_unlock (); geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic); diff --git a/mono/metadata/threadpool-ms.c b/mono/metadata/threadpool-ms.c index 3eaa48dc51..666e373936 100644 --- a/mono/metadata/threadpool-ms.c +++ b/mono/metadata/threadpool-ms.c @@ -423,18 +423,20 @@ domain_remove (ThreadPoolDomain *tpdomain) static ThreadPoolDomain * domain_get (MonoDomain *domain, gboolean create) { - ThreadPoolDomain *tpdomain = NULL; guint i; g_assert (domain); for (i = 0; i < threadpool->domains->len; ++i) { + ThreadPoolDomain *tpdomain; + tpdomain = (ThreadPoolDomain *)g_ptr_array_index (threadpool->domains, i); if (tpdomain->domain == domain) return tpdomain; } if (create) { + ThreadPoolDomain *tpdomain; ThreadPoolDomainCleanupSemaphore *cleanup_semaphore; cleanup_semaphore = g_new0 (ThreadPoolDomainCleanupSemaphore, 1); cleanup_semaphore->ref = 2; @@ -446,9 +448,11 @@ domain_get (MonoDomain *domain, gboolean create) tpdomain = g_new0 (ThreadPoolDomain, 1); tpdomain->domain = domain; domain_add (tpdomain); + + return tpdomain; } - return tpdomain; + return NULL; } static void diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am index d745bb5dd4..a30b00dd80 100644 --- a/mono/mini/Makefile.am +++ b/mono/mini/Makefile.am @@ -860,7 +860,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 4.8.0.309/dea12ad\"" > version.h + echo "#define FULL_VERSION \"Stable 4.8.0.344/f5fbc32\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.am.in b/mono/mini/Makefile.am.in index d745bb5dd4..a30b00dd80 100755 --- a/mono/mini/Makefile.am.in +++ b/mono/mini/Makefile.am.in @@ -860,7 +860,7 @@ EXTRA_DIST = TestDriver.cs \ Makefile.am.in version.h: Makefile - echo "#define FULL_VERSION \"Stable 4.8.0.309/dea12ad\"" > version.h + echo "#define FULL_VERSION \"Stable 4.8.0.344/f5fbc32\"" > version.h # Utility target for patching libtool to speed up linking patch-libtool: diff --git a/mono/mini/Makefile.in.REMOVED.git-id b/mono/mini/Makefile.in.REMOVED.git-id index 00e2abd56e..d75b1d9af7 100644 --- a/mono/mini/Makefile.in.REMOVED.git-id +++ b/mono/mini/Makefile.in.REMOVED.git-id @@ -1 +1 @@ -758b7a9eb4e4abb105aa5381c4c9a16a34e8b4d6 \ No newline at end of file +d1e6363311745351e05c4bd7f744e07b7ea2f128 \ No newline at end of file diff --git a/mono/mini/debugger-agent.c.REMOVED.git-id b/mono/mini/debugger-agent.c.REMOVED.git-id index f71b8e489a..e8aabfddbd 100644 --- a/mono/mini/debugger-agent.c.REMOVED.git-id +++ b/mono/mini/debugger-agent.c.REMOVED.git-id @@ -1 +1 @@ -0a708d482293b4d8f1e47e5e967134b8878d3882 \ No newline at end of file +747cc484fae7811f7e3041ef630f393f4e180cc3 \ No newline at end of file diff --git a/mono/mini/exceptions-arm64.c b/mono/mini/exceptions-arm64.c index fe210faa3a..9b7f762e99 100644 --- a/mono/mini/exceptions-arm64.c +++ b/mono/mini/exceptions-arm64.c @@ -29,15 +29,21 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot) MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; int i, ctx_reg, size; + guint8 *labels [16]; size = 256; code = start = mono_global_codeman_reserve (size); arm_movx (code, ARMREG_IP0, ARMREG_R0); ctx_reg = ARMREG_IP0; + /* Restore fregs */ + arm_ldrx (code, ARMREG_IP1, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, has_fregs)); + labels [0] = code; + arm_cbzx (code, ARMREG_IP1, 0); for (i = 0; i < 32; ++i) arm_ldrfpx (code, i, ctx_reg, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * 8)); + mono_arm_patch (labels [0], code, MONO_R_ARM64_CBZ); /* Restore gregs */ // FIXME: Restore less registers // FIXME: fp should be restored later @@ -69,9 +75,10 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) { guint8 *code; guint8* start; - int size, offset, gregs_offset, fregs_offset, ctx_offset, num_fregs, frame_size; + int i, size, offset, gregs_offset, fregs_offset, ctx_offset, num_fregs, frame_size; MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; + guint8 *labels [16]; size = 512; start = code = mono_global_codeman_reserve (size); @@ -105,10 +112,19 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) arm_strx (code, ARMREG_R0, ARMREG_FP, ctx_offset); /* Save gregs */ code = mono_arm_emit_store_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS | (1 << ARMREG_FP), ARMREG_FP, gregs_offset); - /* No need to save/restore fregs, since we don't currently use them */ + /* Save fregs */ + for (i = 0; i < num_fregs; ++i) + arm_strfpx (code, ARMREG_D8 + i, ARMREG_FP, fregs_offset + (i * 8)); /* Load regs from ctx */ code = mono_arm_emit_load_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, regs)); + /* Load fregs */ + arm_ldrx (code, ARMREG_IP0, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, has_fregs)); + labels [0] = code; + arm_cbzx (code, ARMREG_IP0, 0); + for (i = 0; i < num_fregs; ++i) + arm_ldrfpx (code, ARMREG_D8 + i, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, fregs) + (i * 8)); + mono_arm_patch (labels [0], code, MONO_R_ARM64_CBZ); /* Load fp */ arm_ldrx (code, ARMREG_FP, ARMREG_R0, MONO_STRUCT_OFFSET (MonoContext, regs) + (ARMREG_FP * 8)); @@ -126,6 +142,9 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) /* Restore regs */ code = mono_arm_emit_load_regarray (code, MONO_ARCH_CALLEE_SAVED_REGS, ARMREG_FP, gregs_offset); + /* Restore fregs */ + for (i = 0; i < num_fregs; ++i) + arm_ldrfpx (code, ARMREG_D8 + i, ARMREG_FP, fregs_offset + (i * 8)); /* Destroy frame */ code = mono_arm_emit_destroy_frame (code, frame_size, (1 << ARMREG_IP0)); arm_retx (code, ARMREG_LR); @@ -374,6 +393,7 @@ mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble * memset (&ctx, 0, sizeof (MonoContext)); memcpy (&(ctx.regs [0]), int_regs, sizeof (mgreg_t) * 32); memcpy (&(ctx.fregs [ARMREG_D8]), fp_regs, sizeof (double) * 8); + ctx.has_fregs = 1; ctx.pc = pc; if (mono_object_isinst_checked (exc, mono_defaults.exception_class, &error)) { @@ -402,6 +422,7 @@ mono_arm_resume_unwind (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp memset (&ctx, 0, sizeof (MonoContext)); memcpy (&(ctx.regs [0]), int_regs, sizeof (mgreg_t) * 32); memcpy (&(ctx.fregs [ARMREG_D8]), fp_regs, sizeof (double) * 8); + ctx.has_fregs = 1; ctx.pc = pc; mono_resume_unwind (&ctx); diff --git a/mono/mini/main.c b/mono/mini/main.c index 80044897a8..77f8bc9578 100644 --- a/mono/mini/main.c +++ b/mono/mini/main.c @@ -151,7 +151,7 @@ bundle_save_library_initialize () bundle_save_library_initialized = 1; char *path = g_build_filename (g_get_tmp_dir (), "mono-bundle-XXXXXX", NULL); bundled_dylibrary_directory = g_mkdtemp (path); - g_free (path); + /* don't free path - mkdtemp modifies it in place, and bundled_dylibrary_directory is an alias of it */ if (bundled_dylibrary_directory == NULL) return; atexit (delete_bundled_libraries); diff --git a/mono/mini/mini-arm64.c.REMOVED.git-id b/mono/mini/mini-arm64.c.REMOVED.git-id index 6623c313a7..dc87bb7c47 100644 --- a/mono/mini/mini-arm64.c.REMOVED.git-id +++ b/mono/mini/mini-arm64.c.REMOVED.git-id @@ -1 +1 @@ -b7652c94f218e0d67ed6ef9ae1bf0c0e4ff1493a \ No newline at end of file +b4871f36b910f3efc6be8a41a65c6d80a1e7d70b \ No newline at end of file diff --git a/mono/mini/version.h b/mono/mini/version.h index 43fb80b19e..6fc571709d 100644 --- a/mono/mini/version.h +++ b/mono/mini/version.h @@ -1 +1 @@ -#define FULL_VERSION "Stable 4.8.0.309/dea12ad" +#define FULL_VERSION "Stable 4.8.0.344/f5fbc32" diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 41e4a9b9a4..51ceefca2e 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -140,7 +140,8 @@ BASE_TEST_MOBILE_STATIC_NOT_SUPPORTED= \ threadpool-exceptions7.cs # Needs AppDomains \ cross-domain.cs # Needs AppDomains \ generic-unloading.2.cs # Needs AppDomains \ - thread6.cs # On MOBILE, ThreadAbortException doesn't have necessary field for this test + thread6.cs # On MOBILE, ThreadAbortException doesn't have necessary field for this test \ + appdomain-threadpool-unload.cs # Disabled until ?mcs is fixed # bug-331958.cs diff --git a/mono/tests/Makefile.in b/mono/tests/Makefile.in index cb3b5164d0..59dd848612 100644 --- a/mono/tests/Makefile.in +++ b/mono/tests/Makefile.in @@ -544,7 +544,8 @@ BASE_TEST_MOBILE_STATIC_NOT_SUPPORTED = \ threadpool-exceptions7.cs # Needs AppDomains \ cross-domain.cs # Needs AppDomains \ generic-unloading.2.cs # Needs AppDomains \ - thread6.cs # On MOBILE, ThreadAbortException doesn't have necessary field for this test + thread6.cs # On MOBILE, ThreadAbortException doesn't have necessary field for this test \ + appdomain-threadpool-unload.cs # Disabled until ?mcs is fixed diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h index 907c62ee2e..c5769237e7 100644 --- a/mono/utils/mono-context.h +++ b/mono/utils/mono-context.h @@ -294,6 +294,11 @@ typedef struct { mgreg_t regs [32]; double fregs [32]; mgreg_t pc; + /* + * fregs might not be initialized if this context was created from a + * ucontext. + */ + mgreg_t has_fregs; } MonoContext; #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->pc = (mgreg_t)ip; } while (0) diff --git a/mono/utils/mono-threads-posix.c b/mono/utils/mono-threads-posix.c index ce2f58ad13..de38adf137 100644 --- a/mono/utils/mono-threads-posix.c +++ b/mono/utils/mono-threads-posix.c @@ -456,8 +456,13 @@ This begins async resume. This function must do the following: gboolean mono_threads_suspend_begin_async_resume (MonoThreadInfo *info) { - mono_threads_add_to_pending_operation_set (info); - return mono_threads_pthread_kill (info, mono_threads_posix_get_restart_signal ()) == 0; + int sig = mono_threads_posix_get_restart_signal (); + + if (!mono_threads_pthread_kill (info, sig)) { + mono_threads_add_to_pending_operation_set (info); + return TRUE; + } + return FALSE; } void diff --git a/mono/utils/mono-threads.c b/mono/utils/mono-threads.c index d0eedf683e..a33bbf1d01 100644 --- a/mono/utils/mono-threads.c +++ b/mono/utils/mono-threads.c @@ -916,7 +916,7 @@ suspend_sync (MonoNativeThreadId tid, gboolean interrupt_kernel) } break; case AsyncSuspendBlocking: - if (interrupt_kernel) + if (interrupt_kernel && mono_threads_suspend_needs_abort_syscall ()) mono_threads_suspend_abort_syscall (info); break; diff --git a/po/mcs/de.gmo b/po/mcs/de.gmo index 6a8e12f4cf..bca6d0c6c4 100644 Binary files a/po/mcs/de.gmo and b/po/mcs/de.gmo differ diff --git a/po/mcs/de.po.REMOVED.git-id b/po/mcs/de.po.REMOVED.git-id index 49000b636c..244e9695b5 100644 --- a/po/mcs/de.po.REMOVED.git-id +++ b/po/mcs/de.po.REMOVED.git-id @@ -1 +1 @@ -4b4c8c95c1fb9efeb02fa1c5f3c296ffc26f263e \ No newline at end of file +57fd3fa17feba29a807193571faff35ba24382a7 \ No newline at end of file diff --git a/po/mcs/es.gmo b/po/mcs/es.gmo index fb569f29bd..0b1ab412c3 100644 Binary files a/po/mcs/es.gmo and b/po/mcs/es.gmo differ diff --git a/po/mcs/es.po.REMOVED.git-id b/po/mcs/es.po.REMOVED.git-id index 4e0148bc65..bff2d5bf02 100644 --- a/po/mcs/es.po.REMOVED.git-id +++ b/po/mcs/es.po.REMOVED.git-id @@ -1 +1 @@ -fbacc0386bed56cd426fa6d1519d7238d83e1658 \ No newline at end of file +25ed8e9ca5aea8f09cbeab179abb3f686343b9d4 \ No newline at end of file diff --git a/po/mcs/ja.gmo b/po/mcs/ja.gmo index a3f815606a..d9d04ba929 100644 Binary files a/po/mcs/ja.gmo and b/po/mcs/ja.gmo differ diff --git a/po/mcs/ja.po.REMOVED.git-id b/po/mcs/ja.po.REMOVED.git-id index b25801e01f..fbb803a64b 100644 --- a/po/mcs/ja.po.REMOVED.git-id +++ b/po/mcs/ja.po.REMOVED.git-id @@ -1 +1 @@ -40c5ac34c575e1d103e7012e5e11b3dabe35f4ca \ No newline at end of file +887acfaf4483d20c897f95097cf4b45032f87c00 \ No newline at end of file diff --git a/po/mcs/mcs.pot b/po/mcs/mcs.pot index 1f91fb62fc..5477836962 100644 --- a/po/mcs/mcs.pot +++ b/po/mcs/mcs.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: mono 4.8.0\n" "Report-Msgid-Bugs-To: http://www.mono-project.com/Bugs\n" -"POT-Creation-Date: 2016-11-10 12:38+0000\n" +"POT-Creation-Date: 2016-11-16 13:09+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" diff --git a/po/mcs/pt_BR.gmo b/po/mcs/pt_BR.gmo index 08e3a30f36..a980ace30d 100644 Binary files a/po/mcs/pt_BR.gmo and b/po/mcs/pt_BR.gmo differ diff --git a/po/mcs/pt_BR.po.REMOVED.git-id b/po/mcs/pt_BR.po.REMOVED.git-id index 7e01505895..b9b2f59725 100644 --- a/po/mcs/pt_BR.po.REMOVED.git-id +++ b/po/mcs/pt_BR.po.REMOVED.git-id @@ -1 +1 @@ -7925e43a8725e46f8222cc890cff7acfbe7b709b \ No newline at end of file +71cec70833a5f9d22261d7bf02c81682266a7506 \ No newline at end of file diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 3174ec4c3f..39595455da 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -158,6 +158,7 @@ EXTRA_DIST = \ update_submodules \ mcs.in \ dmcs.in \ + mono-package-runtime \ mono-test-install \ mono-heapviz \ $(MDOC_COMPAT) \ diff --git a/scripts/Makefile.in b/scripts/Makefile.in index a2c3120079..a5f782cae6 100644 --- a/scripts/Makefile.in +++ b/scripts/Makefile.in @@ -500,6 +500,7 @@ EXTRA_DIST = \ update_submodules \ mcs.in \ dmcs.in \ + mono-package-runtime \ mono-test-install \ mono-heapviz \ $(MDOC_COMPAT) \ diff --git a/scripts/mono-package-runtime b/scripts/mono-package-runtime new file mode 100644 index 0000000000..d71942ba0c --- /dev/null +++ b/scripts/mono-package-runtime @@ -0,0 +1,36 @@ +#!/bin/sh + +if test x$2 = x; then + echo usage is: mono-package-runtime MONO_INSTALL_PREFIX LABEL + echo The file will be created in the current directory + exit 1 +fi + +prefix=$1 +output=$2 +if test ! -d $prefix; then + echo the specified path is not a directory: $prefix + exit 1 +fi + +if test -e $output.zip; then + echo The output file already exists, refusing to overwrite: $output.zip + exit 1 +fi + +if test ! -e $prefix/bin/mono; then + echo The $prefix does not contains a bin/mono + exit 1 +fi + +if test ! -d $prefix/lib/mono/4.5; then + echo The $prefix does not contains a lib/mono/4.5 + exit 1 +fi + +o=`pwd`/$output + +cd $prefix +(zip -u $o.zip bin/mono lib/mono/4.5/mscorlib.dll lib/mono/4.5/System*dll lib/mono/4.5/Mono.CSharp.dll lib/mono/4.5/Microsoft*dll lib/mono/4.5/FSharp*.dll lib/mono/4.5/I18N*dll lib/mono/4.5/Accessibility.dll lib/mono/4.5/RabbitMQ.Client.dll lib/mono/4.5/ICSharpCode.SharpZipLib.dll lib/mono/4.5/CustomMarshalers.dll etc/mono/config etc/mono/4.5/machine.config etc/mono/4.5/web.config lib/mono/4.5/Mono.Cairo.dll lib/mono/4.5/Mono.Data.Sqlite.dll lib/mono/4.5/Mono.Posix.dll lib/mono/4.5/Mono.Security.*dll lib/mono/4.5/Mono.Simd.dll) +echo Created file $o.zip +