Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add C# "LocalCredentials" #19287

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 0 additions & 185 deletions src/csharp/Grpc.Core/ChannelCredentials.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,189 +105,4 @@ internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
}
}
}

/// <summary>
/// Callback invoked with the expected targetHost and the peer's certificate.
/// If false is returned by this callback then it is treated as a
/// verification failure and the attempted connection will fail.
/// Invocation of the callback is blocking, so any
/// implementation should be light-weight.
/// Note that the callback can potentially be invoked multiple times,
/// concurrently from different threads (e.g. when multiple connections
/// are being created for the same credentials).
/// </summary>
/// <param name="context">The <see cref="T:Grpc.Core.VerifyPeerContext"/> associated with the callback</param>
/// <returns>true if verification succeeded, false otherwise.</returns>
/// Note: experimental API that can change or be removed without any prior notice.
public delegate bool VerifyPeerCallback(VerifyPeerContext context);

/// <summary>
/// Client-side SSL credentials.
/// </summary>
public sealed class SslCredentials : ChannelCredentials
{
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<SslCredentials>();

readonly string rootCertificates;
readonly KeyCertificatePair keyCertificatePair;
readonly VerifyPeerCallback verifyPeerCallback;

/// <summary>
/// Creates client-side SSL credentials loaded from
/// disk file pointed to by the GRPC_DEFAULT_SSL_ROOTS_FILE_PATH environment variable.
/// If that fails, gets the roots certificates from a well known place on disk.
/// </summary>
public SslCredentials() : this(null, null, null)
{
}

/// <summary>
/// Creates client-side SSL credentials from
/// a string containing PEM encoded root certificates.
/// </summary>
public SslCredentials(string rootCertificates) : this(rootCertificates, null, null)
{
}

/// <summary>
/// Creates client-side SSL credentials.
/// </summary>
/// <param name="rootCertificates">string containing PEM encoded server root certificates.</param>
/// <param name="keyCertificatePair">a key certificate pair.</param>
public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair) :
this(rootCertificates, keyCertificatePair, null)
{
}

/// <summary>
/// Creates client-side SSL credentials.
/// </summary>
/// <param name="rootCertificates">string containing PEM encoded server root certificates.</param>
/// <param name="keyCertificatePair">a key certificate pair.</param>
/// <param name="verifyPeerCallback">a callback to verify peer's target name and certificate.</param>
/// Note: experimental API that can change or be removed without any prior notice.
public SslCredentials(string rootCertificates, KeyCertificatePair keyCertificatePair, VerifyPeerCallback verifyPeerCallback)
{
this.rootCertificates = rootCertificates;
this.keyCertificatePair = keyCertificatePair;
this.verifyPeerCallback = verifyPeerCallback;
}

/// <summary>
/// PEM encoding of the server root certificates.
/// </summary>
public string RootCertificates
{
get
{
return this.rootCertificates;
}
}

/// <summary>
/// Client side key and certificate pair.
/// If null, client will not use key and certificate pair.
/// </summary>
public KeyCertificatePair KeyCertificatePair
{
get
{
return this.keyCertificatePair;
}
}

// Composing composite makes no sense.
internal override bool IsComposable
{
get { return true; }
}

internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
{
IntPtr verifyPeerCallbackTag = IntPtr.Zero;
if (verifyPeerCallback != null)
{
verifyPeerCallbackTag = new VerifyPeerCallbackRegistration(verifyPeerCallback).CallbackRegistration.Tag;
}
return ChannelCredentialsSafeHandle.CreateSslCredentials(rootCertificates, keyCertificatePair, verifyPeerCallbackTag);
}

private class VerifyPeerCallbackRegistration
{
readonly VerifyPeerCallback verifyPeerCallback;
readonly NativeCallbackRegistration callbackRegistration;

public VerifyPeerCallbackRegistration(VerifyPeerCallback verifyPeerCallback)
{
this.verifyPeerCallback = verifyPeerCallback;
this.callbackRegistration = NativeCallbackDispatcher.RegisterCallback(HandleUniversalCallback);
}

public NativeCallbackRegistration CallbackRegistration => callbackRegistration;

private int HandleUniversalCallback(IntPtr arg0, IntPtr arg1, IntPtr arg2, IntPtr arg3, IntPtr arg4, IntPtr arg5)
{
return VerifyPeerCallbackHandler(arg0, arg1, arg2 != IntPtr.Zero);
}

private int VerifyPeerCallbackHandler(IntPtr targetName, IntPtr peerPem, bool isDestroy)
{
if (isDestroy)
{
this.callbackRegistration.Dispose();
return 0;
}

try
{
var context = new VerifyPeerContext(Marshal.PtrToStringAnsi(targetName), Marshal.PtrToStringAnsi(peerPem));

return this.verifyPeerCallback(context) ? 0 : 1;
}
catch (Exception e)
{
// eat the exception, we must not throw when inside callback from native code.
Logger.Error(e, "Exception occurred while invoking verify peer callback handler.");
// Return validation failure in case of exception.
return 1;
}
}
}
}

/// <summary>
/// Credentials that allow composing one <see cref="ChannelCredentials"/> object and
/// one or more <see cref="CallCredentials"/> objects into a single <see cref="ChannelCredentials"/>.
/// </summary>
internal sealed class CompositeChannelCredentials : ChannelCredentials
{
readonly ChannelCredentials channelCredentials;
readonly CallCredentials callCredentials;

/// <summary>
/// Initializes a new instance of <c>CompositeChannelCredentials</c> class.
/// The resulting credentials object will be composite of all the credentials specified as parameters.
/// </summary>
/// <param name="channelCredentials">channelCredentials to compose</param>
/// <param name="callCredentials">channelCredentials to compose</param>
public CompositeChannelCredentials(ChannelCredentials channelCredentials, CallCredentials callCredentials)
{
this.channelCredentials = GrpcPreconditions.CheckNotNull(channelCredentials);
this.callCredentials = GrpcPreconditions.CheckNotNull(callCredentials);
GrpcPreconditions.CheckArgument(channelCredentials.IsComposable, "Supplied channel credentials do not allow composition.");
}

internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
{
using (var callCreds = callCredentials.ToNativeCredentials())
{
var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCredentials.GetNativeCredentials(), callCreds);
if (nativeComposite.IsInvalid)
{
throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");
}
return nativeComposite;
}
}
}
}
5 changes: 5 additions & 0 deletions src/csharp/Grpc.Core/Internal/ChannelCredentialsSafeHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ public static ChannelCredentialsSafeHandle CreateSslCredentials(string pemRootCe
}
}

public static ChannelCredentialsSafeHandle CreateLocal(LocalCredentialsType type)
{
return Native.grpcsharp_local_credentials_create(type);
}

public static ChannelCredentialsSafeHandle CreateComposite(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds)
{
return Native.grpcsharp_composite_channel_credentials_create(channelCreds, callCreds);
Expand Down
65 changes: 65 additions & 0 deletions src/csharp/Grpc.Core/Internal/CompositeChannelCredentials.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#region Copyright notice and license

// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#endregion

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

using Grpc.Core.Internal;
using Grpc.Core.Logging;
using Grpc.Core.Utils;

namespace Grpc.Core.Internal
{
/// <summary>
/// Credentials that allow composing one <see cref="ChannelCredentials"/> object and
/// one or more <see cref="CallCredentials"/> objects into a single <see cref="ChannelCredentials"/>.
/// </summary>
internal sealed class CompositeChannelCredentials : ChannelCredentials
{
readonly ChannelCredentials channelCredentials;
readonly CallCredentials callCredentials;

/// <summary>
/// Initializes a new instance of <c>CompositeChannelCredentials</c> class.
/// The resulting credentials object will be composite of all the credentials specified as parameters.
/// </summary>
/// <param name="channelCredentials">channelCredentials to compose</param>
/// <param name="callCredentials">channelCredentials to compose</param>
public CompositeChannelCredentials(ChannelCredentials channelCredentials, CallCredentials callCredentials)
{
this.channelCredentials = GrpcPreconditions.CheckNotNull(channelCredentials);
this.callCredentials = GrpcPreconditions.CheckNotNull(callCredentials);
GrpcPreconditions.CheckArgument(channelCredentials.IsComposable, "Supplied channel credentials do not allow composition.");
}

internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
{
using (var callCreds = callCredentials.ToNativeCredentials())
{
var nativeComposite = ChannelCredentialsSafeHandle.CreateComposite(channelCredentials.GetNativeCredentials(), callCreds);
if (nativeComposite.IsInvalid)
{
throw new ArgumentException("Error creating native composite credentials. Likely, this is because you are trying to compose incompatible credentials.");
}
return nativeComposite;
}
}
}
}
11 changes: 11 additions & 0 deletions src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ internal partial class NativeMethods
public readonly Delegates.grpcsharp_channel_args_destroy_delegate grpcsharp_channel_args_destroy;
public readonly Delegates.grpcsharp_override_default_ssl_roots_delegate grpcsharp_override_default_ssl_roots;
public readonly Delegates.grpcsharp_ssl_credentials_create_delegate grpcsharp_ssl_credentials_create;
public readonly Delegates.grpcsharp_local_credentials_create_delegate grpcsharp_local_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;
public readonly Delegates.grpcsharp_insecure_channel_create_delegate grpcsharp_insecure_channel_create;
Expand Down Expand Up @@ -180,6 +181,7 @@ public NativeMethods(UnmanagedLibrary library)
this.grpcsharp_channel_args_destroy = GetMethodDelegate<Delegates.grpcsharp_channel_args_destroy_delegate>(library);
this.grpcsharp_override_default_ssl_roots = GetMethodDelegate<Delegates.grpcsharp_override_default_ssl_roots_delegate>(library);
this.grpcsharp_ssl_credentials_create = GetMethodDelegate<Delegates.grpcsharp_ssl_credentials_create_delegate>(library);
this.grpcsharp_local_credentials_create = GetMethodDelegate<Delegates.grpcsharp_local_credentials_create_delegate>(library);
this.grpcsharp_composite_channel_credentials_create = GetMethodDelegate<Delegates.grpcsharp_composite_channel_credentials_create_delegate>(library);
this.grpcsharp_channel_credentials_release = GetMethodDelegate<Delegates.grpcsharp_channel_credentials_release_delegate>(library);
this.grpcsharp_insecure_channel_create = GetMethodDelegate<Delegates.grpcsharp_insecure_channel_create_delegate>(library);
Expand Down Expand Up @@ -280,6 +282,7 @@ public NativeMethods(DllImportsFromStaticLib unusedInstance)
this.grpcsharp_channel_args_destroy = DllImportsFromStaticLib.grpcsharp_channel_args_destroy;
this.grpcsharp_override_default_ssl_roots = DllImportsFromStaticLib.grpcsharp_override_default_ssl_roots;
this.grpcsharp_ssl_credentials_create = DllImportsFromStaticLib.grpcsharp_ssl_credentials_create;
this.grpcsharp_local_credentials_create = DllImportsFromStaticLib.grpcsharp_local_credentials_create;
this.grpcsharp_composite_channel_credentials_create = DllImportsFromStaticLib.grpcsharp_composite_channel_credentials_create;
this.grpcsharp_channel_credentials_release = DllImportsFromStaticLib.grpcsharp_channel_credentials_release;
this.grpcsharp_insecure_channel_create = DllImportsFromStaticLib.grpcsharp_insecure_channel_create;
Expand Down Expand Up @@ -380,6 +383,7 @@ public NativeMethods(DllImportsFromSharedLib unusedInstance)
this.grpcsharp_channel_args_destroy = DllImportsFromSharedLib.grpcsharp_channel_args_destroy;
this.grpcsharp_override_default_ssl_roots = DllImportsFromSharedLib.grpcsharp_override_default_ssl_roots;
this.grpcsharp_ssl_credentials_create = DllImportsFromSharedLib.grpcsharp_ssl_credentials_create;
this.grpcsharp_local_credentials_create = DllImportsFromSharedLib.grpcsharp_local_credentials_create;
this.grpcsharp_composite_channel_credentials_create = DllImportsFromSharedLib.grpcsharp_composite_channel_credentials_create;
this.grpcsharp_channel_credentials_release = DllImportsFromSharedLib.grpcsharp_channel_credentials_release;
this.grpcsharp_insecure_channel_create = DllImportsFromSharedLib.grpcsharp_insecure_channel_create;
Expand Down Expand Up @@ -483,6 +487,7 @@ public class Delegates
public delegate void grpcsharp_channel_args_destroy_delegate(IntPtr args);
public delegate void grpcsharp_override_default_ssl_roots_delegate(string pemRootCerts);
public delegate ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create_delegate(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag);
public delegate ChannelCredentialsSafeHandle grpcsharp_local_credentials_create_delegate(LocalCredentialsType type);
public delegate ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create_delegate(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds);
public delegate void grpcsharp_channel_credentials_release_delegate(IntPtr credentials);
public delegate ChannelSafeHandle grpcsharp_insecure_channel_create_delegate(string target, ChannelArgsSafeHandle channelArgs);
Expand Down Expand Up @@ -678,6 +683,9 @@ internal class DllImportsFromStaticLib
[DllImport(ImportName)]
public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag);

[DllImport(ImportName)]
public static extern ChannelCredentialsSafeHandle grpcsharp_local_credentials_create(LocalCredentialsType type);

[DllImport(ImportName)]
public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds);

Expand Down Expand Up @@ -974,6 +982,9 @@ internal class DllImportsFromSharedLib
[DllImport(ImportName)]
public static extern ChannelCredentialsSafeHandle grpcsharp_ssl_credentials_create(string pemRootCerts, string keyCertPairCertChain, string keyCertPairPrivateKey, IntPtr verifyPeerCallbackTag);

[DllImport(ImportName)]
public static extern ChannelCredentialsSafeHandle grpcsharp_local_credentials_create(LocalCredentialsType type);

[DllImport(ImportName)]
public static extern ChannelCredentialsSafeHandle grpcsharp_composite_channel_credentials_create(ChannelCredentialsSafeHandle channelCreds, CallCredentialsSafeHandle callCreds);

Expand Down
69 changes: 69 additions & 0 deletions src/csharp/Grpc.Core/LocalCredentials.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#region Copyright notice and license

// Copyright 2019 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#endregion

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

using Grpc.Core.Internal;
using Grpc.Core.Logging;
using Grpc.Core.Utils;

namespace Grpc.Core
{
/// <summary>
/// Type of "local" connections for which the local credentials will be applied.
/// </summary>
public enum LocalCredentialsType
{
/// <summary>
/// Trusted connection over UDS
/// </summary>
UnixDomainSocket = 0,

/// <summary>
/// Trusted TCP connection to the local host
/// </summary>
LocalTcp
}

/// <summary>
/// Credentials that allow sending sensitive metadata such
/// as authentication tokens over a trusted local connection.
/// Note: experimental API that can change or be removed without any prior notice.
/// </summary>
public sealed class LocalCredentials : ChannelCredentials
{
readonly LocalCredentialsType type;

/// <summary>
/// Initializes a new instance of <c>LocalCredentials</c> class.
/// </summary>
/// <param name="type">type of local connection accepted by the credentials</param>
public LocalCredentials(LocalCredentialsType type)
{
this.type = type;
}

internal override ChannelCredentialsSafeHandle CreateNativeCredentials()
{
return ChannelCredentialsSafeHandle.CreateLocal(type);
}
}
}
Loading