-
Notifications
You must be signed in to change notification settings - Fork 925
Support libssh2 based callbacks #2182
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This methods are required to be able to call down into the c libraries methods that are only available when using libssh2. The files in this class can be properly tidied up and split up before merge |
||
| using LibGit2Sharp.Core; | ||
| using System; | ||
| using System.Runtime.InteropServices; | ||
|
|
||
| namespace LibGit2Sharp.Ssh | ||
| { | ||
|
|
||
| internal static class NativeMethods | ||
| { | ||
| private const string libgit2 = NativeDllName.Name; | ||
|
|
||
| [DllImport(libgit2, CallingConvention = CallingConvention.Cdecl)] | ||
| internal static extern int git_cred_ssh_key_new( | ||
| out IntPtr cred, | ||
| [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string username, | ||
| [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string publickey, | ||
| [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string privatekey, | ||
| [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string passphrase); | ||
|
|
||
| [DllImport(libgit2)] | ||
| internal static extern int git_cred_ssh_key_memory_new( | ||
| out IntPtr cred, | ||
| [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string username, | ||
| [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string publickey, | ||
| [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string privatekey, | ||
| [MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string passphrase); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Class that holds SSH username with key credentials for remote repository access. | ||
| /// </summary> | ||
| public sealed class SshUserKeyCredentials : Credentials | ||
| { | ||
| /// <summary> | ||
| /// Callback to acquire a credential object. | ||
| /// </summary> | ||
| /// <param name="cred">The newly created credential object.</param> | ||
| /// <returns>0 for success, < 0 to indicate an error, > 0 to indicate no credential was acquired.</returns> | ||
| protected internal override int GitCredentialHandler(out IntPtr cred) | ||
| { | ||
| if (Username == null) | ||
| { | ||
| throw new InvalidOperationException("SshUserKeyCredentials contains a null Username."); | ||
| } | ||
|
|
||
| if (Passphrase == null) | ||
| { | ||
| throw new InvalidOperationException("SshUserKeyCredentials contains a null Passphrase."); | ||
| } | ||
|
|
||
| if (PublicKey == null) | ||
| { | ||
| throw new InvalidOperationException("SshUserKeyCredentials contains a null PublicKey."); | ||
| } | ||
|
|
||
| if (PrivateKey == null) | ||
| { | ||
| throw new InvalidOperationException("SshUserKeyCredentials contains a null PrivateKey."); | ||
| } | ||
|
|
||
| return NativeMethods.git_cred_ssh_key_new(out cred, Username, PublicKey, PrivateKey, Passphrase); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Username for SSH authentication. | ||
| /// </summary> | ||
| public string Username { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Public key file location for SSH authentication. | ||
| /// </summary> | ||
| public string PublicKey { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Private key file location for SSH authentication. | ||
| /// </summary> | ||
| public string PrivateKey { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Passphrase for SSH authentication. | ||
| /// </summary> | ||
| public string Passphrase { get; set; } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Class that holds SSH username with in-memory key credentials for remote repository access. | ||
| /// </summary> | ||
| public sealed class SshUserKeyMemoryCredentials : Credentials | ||
| { | ||
| /// <summary> | ||
| /// Callback to acquire a credential object. | ||
| /// </summary> | ||
| /// <param name="cred">The newly created credential object.</param> | ||
| /// <returns>0 for success, < 0 to indicate an error, > 0 to indicate no credential was acquired.</returns> | ||
| protected internal override int GitCredentialHandler(out IntPtr cred) | ||
| { | ||
| if (Username == null) | ||
| { | ||
| throw new InvalidOperationException("SshUserKeyMemoryCredentials contains a null Username."); | ||
| } | ||
|
|
||
| if (Passphrase == null) | ||
| { | ||
| throw new InvalidOperationException("SshUserKeyMemoryCredentials contains a null Passphrase."); | ||
| } | ||
|
|
||
| if (PublicKey == null) | ||
| { | ||
| //throw new InvalidOperationException("SshUserKeyMemoryCredentials contains a null PublicKey."); | ||
| } | ||
|
|
||
| if (PrivateKey == null) | ||
| { | ||
| throw new InvalidOperationException("SshUserKeyMemoryCredentials contains a null PrivateKey."); | ||
| } | ||
|
|
||
| return NativeMethods.git_cred_ssh_key_memory_new(out cred, Username, PublicKey, PrivateKey, Passphrase); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Username for SSH authentication. | ||
| /// </summary> | ||
| public string Username { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Public key for SSH authentication. | ||
| /// </summary> | ||
| public string PublicKey { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Private key for SSH authentication. | ||
| /// </summary> | ||
| public string PrivateKey { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// Passphrase for SSH authentication. | ||
| /// </summary> | ||
| public string Passphrase { get; set; } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,7 +20,7 @@ public static class GlobalSettings | |
|
|
||
| private static string nativeLibraryPath; | ||
| private static bool nativeLibraryPathLocked; | ||
| private static readonly string nativeLibraryDefaultPath = null; | ||
| private static readonly string nativeLibraryDefaultPath = "/Users/robert/Development/Sandbox/libgit2/build"; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Obviously not something to merge, just that helped testing against my local build of libgit2 |
||
|
|
||
| static GlobalSettings() | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| using LibGit2Sharp.Handlers; | ||
|
|
||
| namespace LibGit2Sharp; | ||
|
|
||
| /// <summary> | ||
| /// Options controlling ListRemote behavior. | ||
| /// </summary> | ||
| public sealed class ListRemoteOptions | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. New
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can probably be put in as its own PR back into the upstream repo as its not really dependant on anything ssh |
||
| { | ||
| /// <summary> | ||
| /// Handler to generate <see cref="LibGit2Sharp.Credentials"/> for authentication. | ||
| /// </summary> | ||
| public CredentialsHandler CredentialsProvider { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// This handler will be called to let the user make a decision on whether to allow | ||
| /// the connection to proceed based on the certificate presented by the server. | ||
| /// </summary> | ||
| public CertificateCheckHandler CertificateCheck { get; set; } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// Options for connecting through a proxy. | ||
| /// </summary> | ||
| public ProxyOptions ProxyOptions { get; set; } = new(); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,9 +52,34 @@ public virtual IEnumerable<Reference> ListReferences(Remote remote) | |
| { | ||
| Ensure.ArgumentNotNull(remote, "remote"); | ||
|
|
||
| return ListReferencesInternal(remote.Url, null, new ProxyOptions()); | ||
| var options = new ListRemoteOptions() | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are a bunch of overloads in this network class to utilize the new ListRemoteOptions, these dont necessarily need to be implemented exactly like this |
||
| { | ||
| ProxyOptions = new ProxyOptions() | ||
| }; | ||
|
|
||
| return ListReferencesInternal(remote.Url, options); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// List references in a <see cref="Remote"/> repository. | ||
| /// <para> | ||
| /// When the remote tips are ahead of the local ones, the retrieved | ||
| /// <see cref="DirectReference"/>s may point to non existing | ||
| /// <see cref="GitObject"/>s in the local repository. In that | ||
| /// case, <see cref="DirectReference.Target"/> will return <c>null</c>. | ||
| /// </para> | ||
| /// </summary> | ||
| /// <param name="remote">The <see cref="Remote"/> to list from.</param> | ||
| /// <param name="options">The options for the remote request.</param> | ||
| /// <returns>The references in the <see cref="Remote"/> repository.</returns> | ||
| public virtual IEnumerable<Reference> ListReferences(Remote remote, ListRemoteOptions options) | ||
| { | ||
| Ensure.ArgumentNotNull(remote, "remote"); | ||
|
|
||
| return ListReferencesInternal(remote.Url, options); | ||
| } | ||
|
|
||
|
|
||
| /// <summary> | ||
| /// List references in a <see cref="Remote"/> repository. | ||
| /// <para> | ||
|
|
@@ -71,7 +96,12 @@ public virtual IEnumerable<Reference> ListReferences(Remote remote, ProxyOptions | |
| { | ||
| Ensure.ArgumentNotNull(remote, "remote"); | ||
|
|
||
| return ListReferencesInternal(remote.Url, null, proxyOptions); | ||
| var options = new ListRemoteOptions() | ||
| { | ||
| ProxyOptions = proxyOptions | ||
| }; | ||
|
|
||
| return ListReferencesInternal(remote.Url, options); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -91,7 +121,13 @@ public virtual IEnumerable<Reference> ListReferences(Remote remote, CredentialsH | |
| Ensure.ArgumentNotNull(remote, "remote"); | ||
| Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); | ||
|
|
||
| return ListReferencesInternal(remote.Url, credentialsProvider, new ProxyOptions()); | ||
| var options = new ListRemoteOptions() | ||
| { | ||
| ProxyOptions = new ProxyOptions(), | ||
| CredentialsProvider = credentialsProvider | ||
| }; | ||
|
|
||
| return ListReferencesInternal(remote.Url, options); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -112,7 +148,32 @@ public virtual IEnumerable<Reference> ListReferences(Remote remote, CredentialsH | |
| Ensure.ArgumentNotNull(remote, "remote"); | ||
| Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); | ||
|
|
||
| return ListReferencesInternal(remote.Url, credentialsProvider, proxyOptions); | ||
| var options = new ListRemoteOptions() | ||
| { | ||
| ProxyOptions = proxyOptions, | ||
| CredentialsProvider = credentialsProvider | ||
| }; | ||
|
|
||
| return ListReferencesInternal(remote.Url, options); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// List references in a remote repository. | ||
| /// <para> | ||
| /// When the remote tips are ahead of the local ones, the retrieved | ||
| /// <see cref="DirectReference"/>s may point to non existing | ||
| /// <see cref="GitObject"/>s in the local repository. In that | ||
| /// case, <see cref="DirectReference.Target"/> will return <c>null</c>. | ||
| /// </para> | ||
| /// </summary> | ||
| /// <param name="url">The url to list from.</param> | ||
| /// <param name="options">The options for the remote request.</param> | ||
| /// <returns>The references in the remote repository.</returns> | ||
| public virtual IEnumerable<Reference> ListReferences(string url, ListRemoteOptions options) | ||
| { | ||
| Ensure.ArgumentNotNull(url, "url"); | ||
|
|
||
| return ListReferencesInternal(url, options); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -130,7 +191,12 @@ public virtual IEnumerable<Reference> ListReferences(string url) | |
| { | ||
| Ensure.ArgumentNotNull(url, "url"); | ||
|
|
||
| return ListReferencesInternal(url, null, new ProxyOptions()); | ||
| var options = new ListRemoteOptions() | ||
| { | ||
| ProxyOptions = new ProxyOptions() | ||
| }; | ||
|
|
||
| return ListReferencesInternal(url, options); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -148,8 +214,12 @@ public virtual IEnumerable<Reference> ListReferences(string url) | |
| public virtual IEnumerable<Reference> ListReferences(string url, ProxyOptions proxyOptions) | ||
| { | ||
| Ensure.ArgumentNotNull(url, "url"); | ||
| var options = new ListRemoteOptions() | ||
| { | ||
| ProxyOptions = proxyOptions | ||
| }; | ||
|
|
||
| return ListReferencesInternal(url, null, proxyOptions); | ||
| return ListReferencesInternal(url, options); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -169,7 +239,13 @@ public virtual IEnumerable<Reference> ListReferences(string url, CredentialsHand | |
| Ensure.ArgumentNotNull(url, "url"); | ||
| Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); | ||
|
|
||
| return ListReferencesInternal(url, credentialsProvider, new ProxyOptions()); | ||
| var options = new ListRemoteOptions() | ||
| { | ||
| CredentialsProvider = credentialsProvider, | ||
| ProxyOptions = new ProxyOptions() | ||
| }; | ||
|
|
||
| return ListReferencesInternal(url, options); | ||
| } | ||
|
|
||
| /// <summary> | ||
|
|
@@ -190,21 +266,26 @@ public virtual IEnumerable<Reference> ListReferences(string url, CredentialsHand | |
| Ensure.ArgumentNotNull(url, "url"); | ||
| Ensure.ArgumentNotNull(credentialsProvider, "credentialsProvider"); | ||
|
|
||
| return ListReferencesInternal(url, credentialsProvider, new ProxyOptions()); | ||
| var options = new ListRemoteOptions() | ||
| { | ||
| CredentialsProvider = credentialsProvider, | ||
| ProxyOptions = new ProxyOptions() | ||
| }; | ||
| return ListReferencesInternal(url, options); | ||
| } | ||
|
|
||
| private IEnumerable<Reference> ListReferencesInternal(string url, CredentialsHandler credentialsProvider, ProxyOptions proxyOptions) | ||
| private IEnumerable<Reference> ListReferencesInternal(string url, ListRemoteOptions options) | ||
| { | ||
| proxyOptions ??= new(); | ||
| var proxyOptions = options?.ProxyOptions ?? new(); | ||
|
|
||
| using RemoteHandle remoteHandle = BuildRemoteHandle(repository.Handle, url); | ||
| using var proxyOptionsWrapper = new GitProxyOptionsWrapper(proxyOptions.CreateGitProxyOptions()); | ||
|
|
||
| GitRemoteCallbacks gitCallbacks = new GitRemoteCallbacks { version = 1 }; | ||
|
|
||
| if (credentialsProvider != null) | ||
| if (options != null) | ||
| { | ||
| var callbacks = new RemoteCallbacks(credentialsProvider); | ||
| var callbacks = new RemoteCallbacks(options); | ||
| gitCallbacks = callbacks.GenerateCallbacks(); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bunch of changes to get it building locally