aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/csharp/Grpc.Core
diff options
context:
space:
mode:
Diffstat (limited to 'src/csharp/Grpc.Core')
-rw-r--r--src/csharp/Grpc.Core/Credentials.cs52
-rw-r--r--src/csharp/Grpc.Core/Grpc.Core.csproj1
-rw-r--r--src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs8
-rw-r--r--src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs112
4 files changed, 173 insertions, 0 deletions
diff --git a/src/csharp/Grpc.Core/Credentials.cs b/src/csharp/Grpc.Core/Credentials.cs
index 4fcac0c4c0..e653d3688c 100644
--- a/src/csharp/Grpc.Core/Credentials.cs
+++ b/src/csharp/Grpc.Core/Credentials.cs
@@ -32,10 +32,17 @@
#endregion
using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
using Grpc.Core.Internal;
+using Grpc.Core.Utils;
namespace Grpc.Core
{
+ // TODO: rename
+ public delegate Task AsyncAuthInterceptor(string authUri, Metadata metadata);
+
/// <summary>
/// Client-side credentials. Used for creation of a secure channel.
/// </summary>
@@ -135,4 +142,49 @@ namespace Grpc.Core
return CredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair);
}
}
+
+ /// <summary>
+ /// Client-side credentials that delegate metadata based auth to an interceptor.
+ /// </summary>
+ public partial class MetadataCredentials : Credentials
+ {
+ readonly AsyncAuthInterceptor interceptor;
+
+ public MetadataCredentials(AsyncAuthInterceptor interceptor)
+ {
+ this.interceptor = interceptor;
+ }
+
+ internal override CredentialsSafeHandle ToNativeCredentials()
+ {
+ NativeMetadataCredentialsPlugin plugin = new NativeMetadataCredentialsPlugin(interceptor);
+ return plugin.Credentials;
+ }
+ }
+
+ public sealed class CompositeCredentials : Credentials
+ {
+ readonly List<Credentials> credentials;
+
+ public CompositeCredentials(params Credentials[] credentials)
+ {
+ Preconditions.CheckArgument(credentials.Length >= 2, "Composite credentials object can only be created from 2 or more credentials.");
+ this.credentials = new List<Credentials>(credentials);
+ }
+
+ public static CompositeCredentials Create(params Credentials[] credentials)
+ {
+ return new CompositeCredentials(credentials);
+ }
+
+ internal override CredentialsSafeHandle ToNativeCredentials()
+ {
+ var nativeComposite = credentials[0].ToNativeCredentials();
+ for (int i = 1; i < credentials.Count; i++)
+ {
+ nativeComposite = CredentialsSafeHandle.CreateComposite(nativeComposite, credentials[i].ToNativeCredentials());
+ }
+ return nativeComposite;
+ }
+ }
}
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index ad2af17bc7..04c3eda113 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -49,6 +49,7 @@
<Compile Include="AsyncDuplexStreamingCall.cs" />
<Compile Include="AsyncServerStreamingCall.cs" />
<Compile Include="IClientStreamWriter.cs" />
+ <Compile Include="Internal\NativeMetadataCredentialsPlugin.cs" />
<Compile Include="Internal\INativeCall.cs" />
<Compile Include="IServerStreamWriter.cs" />
<Compile Include="IAsyncStreamWriter.cs" />
diff --git a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs
index feed335362..bab45108e0 100644
--- a/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CredentialsSafeHandle.cs
@@ -44,6 +44,9 @@ namespace Grpc.Core.Internal
static extern CredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey);
[DllImport("grpc_csharp_ext.dll")]
+ static extern CredentialsSafeHandle grpcsharp_composite_credentials_create(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2);
+
+ [DllImport("grpc_csharp_ext.dll")]
static extern void grpcsharp_credentials_release(IntPtr credentials);
private CredentialsSafeHandle()
@@ -69,6 +72,11 @@ namespace Grpc.Core.Internal
}
}
+ public static CredentialsSafeHandle CreateComposite(CredentialsSafeHandle creds1, CredentialsSafeHandle creds2)
+ {
+ return grpcsharp_composite_credentials_create(creds1, creds2);
+ }
+
protected override bool ReleaseHandle()
{
grpcsharp_credentials_release(handle);
diff --git a/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
new file mode 100644
index 0000000000..6662a73b17
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/NativeMetadataCredentialsPlugin.cs
@@ -0,0 +1,112 @@
+#region Copyright notice and license
+// Copyright 2015, 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.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+using Grpc.Core.Logging;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+ internal delegate void NativeMetadataInterceptor(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy);
+
+ internal class NativeMetadataCredentialsPlugin
+ {
+ const string GetMetadataExceptionMsg = "Exception occured in metadata credentials plugin.";
+ static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeMetadataCredentialsPlugin>();
+
+ [DllImport("grpc_csharp_ext.dll")]
+ static extern CredentialsSafeHandle grpcsharp_metadata_credentials_create_from_plugin(NativeMetadataInterceptor interceptor);
+
+ [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
+ static extern void grpcsharp_metadata_credentials_notify_from_plugin(IntPtr callbackPtr, IntPtr userData, MetadataArraySafeHandle metadataArray, StatusCode statusCode, string errorDetails);
+
+ AsyncAuthInterceptor interceptor;
+ GCHandle gcHandle;
+ NativeMetadataInterceptor nativeInterceptor;
+ CredentialsSafeHandle credentials;
+
+ public NativeMetadataCredentialsPlugin(AsyncAuthInterceptor interceptor)
+ {
+ this.interceptor = Preconditions.CheckNotNull(interceptor, "interceptor");
+ this.nativeInterceptor = NativeMetadataInterceptorHandler;
+
+ // Make sure the callback doesn't get garbage collected until it is destroyed.
+ this.gcHandle = GCHandle.Alloc(this.nativeInterceptor, GCHandleType.Normal);
+ this.credentials = grpcsharp_metadata_credentials_create_from_plugin(nativeInterceptor);
+ }
+
+ public CredentialsSafeHandle Credentials
+ {
+ get { return credentials; }
+ }
+
+ private void NativeMetadataInterceptorHandler(IntPtr statePtr, IntPtr serviceUrlPtr, IntPtr callbackPtr, IntPtr userDataPtr, bool isDestroy)
+ {
+ if (isDestroy)
+ {
+ gcHandle.Free();
+ return;
+ }
+
+ try
+ {
+ string serviceUrl = Marshal.PtrToStringAnsi(serviceUrlPtr);
+ StartGetMetadata(serviceUrl, callbackPtr, userDataPtr);
+ }
+ catch (Exception e)
+ {
+ grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, null, StatusCode.Unknown, GetMetadataExceptionMsg);
+ Logger.Error(e, GetMetadataExceptionMsg);
+ }
+ }
+
+ private async void StartGetMetadata(string serviceUrl, IntPtr callbackPtr, IntPtr userDataPtr)
+ {
+ try
+ {
+ var metadata = new Metadata();
+ await interceptor(serviceUrl, metadata);
+ using (var metadataArray = MetadataArraySafeHandle.Create(metadata))
+ {
+ grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, metadataArray, StatusCode.OK, null);
+ }
+ }
+ catch (Exception e)
+ {
+ grpcsharp_metadata_credentials_notify_from_plugin(callbackPtr, userDataPtr, null, StatusCode.Unknown, GetMetadataExceptionMsg);
+ Logger.Error(e, GetMetadataExceptionMsg);
+ }
+ }
+ }
+}