diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj index 307c0e87837..9587503e4b3 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.csproj +++ b/src/csharp/Grpc.Core/Grpc.Core.csproj @@ -128,6 +128,7 @@ + @@ -135,4 +136,12 @@ + + + + + + Resources\roots.pem + + \ No newline at end of file diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec index 9a4c1a3c858..49bccb050ef 100644 --- a/src/csharp/Grpc.Core/Grpc.Core.nuspec +++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec @@ -20,7 +20,6 @@ - diff --git a/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs b/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs new file mode 100644 index 00000000000..eeaa7add813 --- /dev/null +++ b/src/csharp/Grpc.Core/Internal/DefaultSslRootsOverride.cs @@ -0,0 +1,72 @@ +#region Copyright notice and license + +// Copyright 2015-2016, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#endregion + +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Grpc.Core.Internal +{ + /// + /// Overrides the content of default SSL roots. + /// + internal static class DefaultSslRootsOverride + { + const string RootsPemResourceName = "Grpc.Core.Resources.roots.pem"; + static object staticLock = new object(); + + /// + /// Overrides C core's default roots with roots.pem loaded as embedded resource. + /// + public static void Override(NativeMethods native) + { + lock (staticLock) + { + var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(RootsPemResourceName); + if (stream == null) + { + throw new IOException(string.Format("Error loading the embedded resource \"{0}\"", RootsPemResourceName)); + } + using (var streamReader = new StreamReader(stream)) + { + var pemRootCerts = streamReader.ReadToEnd(); + native.grpcsharp_override_default_ssl_roots(pemRootCerts); + } + } + } + } +} diff --git a/src/csharp/Grpc.Core/Internal/NativeExtension.cs b/src/csharp/Grpc.Core/Internal/NativeExtension.cs index 137533b3ef3..e14d33ea506 100644 --- a/src/csharp/Grpc.Core/Internal/NativeExtension.cs +++ b/src/csharp/Grpc.Core/Internal/NativeExtension.cs @@ -60,6 +60,8 @@ namespace Grpc.Core.Internal // to make sure we don't lose any logs. NativeLogRedirector.Redirect(this.nativeMethods); + DefaultSslRootsOverride.Override(this.nativeMethods); + Logger.Debug("gRPC native library loaded successfully."); } diff --git a/src/csharp/Grpc.Core/Internal/NativeMethods.cs b/src/csharp/Grpc.Core/Internal/NativeMethods.cs index af37d61c731..19a573581e0 100644 --- a/src/csharp/Grpc.Core/Internal/NativeMethods.cs +++ b/src/csharp/Grpc.Core/Internal/NativeMethods.cs @@ -97,6 +97,7 @@ namespace Grpc.Core.Internal public readonly Delegates.grpcsharp_channel_args_set_integer_delegate grpcsharp_channel_args_set_integer; public readonly Delegates.grpcsharp_channel_args_destroy_delegate grpcsharp_channel_args_destroy; + public readonly Delegates.grpcsharp_override_default_ssl_roots grpcsharp_override_default_ssl_roots; public readonly Delegates.grpcsharp_ssl_credentials_create_delegate grpcsharp_ssl_credentials_create; public readonly Delegates.grpcsharp_composite_channel_credentials_create_delegate grpcsharp_composite_channel_credentials_create; public readonly Delegates.grpcsharp_channel_credentials_release_delegate grpcsharp_channel_credentials_release; @@ -203,6 +204,7 @@ namespace Grpc.Core.Internal this.grpcsharp_channel_args_set_integer = GetMethodDelegate(library); this.grpcsharp_channel_args_destroy = GetMethodDelegate(library); + this.grpcsharp_override_default_ssl_roots = GetMethodDelegate(library); this.grpcsharp_ssl_credentials_create = GetMethodDelegate(library); this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate(library); this.grpcsharp_channel_credentials_release = GetMethodDelegate(library); @@ -306,6 +308,7 @@ namespace Grpc.Core.Internal this.grpcsharp_channel_args_set_integer = PInvokeMethods.grpcsharp_channel_args_set_integer; this.grpcsharp_channel_args_destroy = PInvokeMethods.grpcsharp_channel_args_destroy; + this.grpcsharp_override_default_ssl_roots = PInvokeMethods.grpcsharp_override_default_ssl_roots; this.grpcsharp_ssl_credentials_create = PInvokeMethods.grpcsharp_ssl_credentials_create; this.grpcsharp_composite_channel_credentials_create = PInvokeMethods.grpcsharp_composite_channel_credentials_create; this.grpcsharp_channel_credentials_release = PInvokeMethods.grpcsharp_channel_credentials_release; @@ -449,6 +452,7 @@ namespace Grpc.Core.Internal public delegate void grpcsharp_channel_args_set_integer_delegate(ChannelArgsSafeHandle args, UIntPtr index, string key, int value); public delegate void grpcsharp_channel_args_destroy_delegate(IntPtr args); + public delegate void grpcsharp_override_default_ssl_roots(string pemRootCerts); public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); public delegate ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create_delegate(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds); public delegate void grpcsharp_channel_credentials_release_delegate(IntPtr credentials); @@ -657,6 +661,9 @@ namespace Grpc.Core.Internal // ChannelCredentialsSafeHandle + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] + public static extern void grpcsharp_override_default_ssl_roots(string pemRootCerts); + [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)] public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey); diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c index 26f15373989..1df74a09937 100644 --- a/src/csharp/ext/grpc_csharp_ext.c +++ b/src/csharp/ext/grpc_csharp_ext.c @@ -1,6 +1,6 @@ /* * - * Copyright 2015, Google Inc. + * Copyright 2015-2016, Google Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -835,6 +835,30 @@ grpcsharp_server_request_call(grpc_server *server, grpc_completion_queue *cq, /* Security */ +static char *default_pem_root_certs = NULL; + +static grpc_ssl_roots_override_result override_ssl_roots_handler( + char **pem_root_certs) { + if (!default_pem_root_certs) { + *pem_root_certs = NULL; + return GRPC_SSL_ROOTS_OVERRIDE_FAIL_PERMANENTLY; + } + *pem_root_certs = gpr_strdup(default_pem_root_certs); + return GRPC_SSL_ROOTS_OVERRIDE_OK; +} + +GPR_EXPORT void GPR_CALLTYPE grpcsharp_override_default_ssl_roots( + const char *pem_root_certs) { + /* + * This currently wastes ~300kB of memory by keeping a copy of roots + * in a static variable, but for desktop/server use, the overhead + * is negligible. In the future, we might want to change the behavior + * for mobile (e.g. Xamarin). + */ + default_pem_root_certs = gpr_strdup(pem_root_certs); + grpc_set_ssl_roots_override_callback(override_ssl_roots_handler); +} + GPR_EXPORT grpc_channel_credentials *GPR_CALLTYPE grpcsharp_ssl_credentials_create(const char *pem_root_certs, const char *key_cert_pair_cert_chain, @@ -917,6 +941,7 @@ GPR_EXPORT grpc_call_credentials *GPR_CALLTYPE grpcsharp_composite_call_credenti return grpc_composite_call_credentials_create(creds1, creds2, NULL); } + /* Metadata credentials plugin */ GPR_EXPORT void GPR_CALLTYPE grpcsharp_metadata_credentials_notify_from_plugin( diff --git a/tools/dockerfile/grpc_interop_csharp/build_interop.sh b/tools/dockerfile/grpc_interop_csharp/build_interop.sh index e87fe2f6928..5ad525f41c5 100755 --- a/tools/dockerfile/grpc_interop_csharp/build_interop.sh +++ b/tools/dockerfile/grpc_interop_csharp/build_interop.sh @@ -39,8 +39,6 @@ cp -r /var/local/jenkins/service_account $HOME || true cd /var/local/git/grpc -make install-certs - # build C# interop client & server make CONFIG=dbg grpc_csharp_ext (cd src/csharp && mono /var/local/NuGet.exe restore Grpc.sln)