Skip to content

Commit d1c23a5

Browse files
committed
Merge branch 'therzok/sshAPI' into therzok/mdNext
2 parents a3fcb1e + 4399842 commit d1c23a5

19 files changed

+260
-4
lines changed
0 Bytes
Binary file not shown.
-32 KB
Binary file not shown.
0 Bytes
Binary file not shown.
-48 KB
Binary file not shown.

LibGit2Sharp.Tests/GlobalSettingsFixture.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System.Text.RegularExpressions;
22
using LibGit2Sharp.Tests.TestHelpers;
33
using Xunit;
4+
using System.Globalization;
5+
using System.IO;
46

57
namespace LibGit2Sharp.Tests
68
{
@@ -13,6 +15,14 @@ public void CanGetMinimumCompiledInFeatures()
1315

1416
Assert.True(features.HasFlag(BuiltInFeatures.Threads));
1517
Assert.True(features.HasFlag(BuiltInFeatures.Https));
18+
19+
bool hasSsh;
20+
using (var sr = new StreamReader(typeof(GlobalSettingsFixture).Assembly.GetManifestResourceStream("LibGit2Sharp.Tests.ssh_used.txt")))
21+
{
22+
if (!bool.TryParse(sr.ReadLine(), out hasSsh))
23+
hasSsh = false;
24+
}
25+
Assert.Equal(hasSsh, features.HasFlag(BuiltInFeatures.Ssh));
1626
}
1727

1828
[Fact]

LibGit2Sharp.Tests/LibGit2Sharp.Tests.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,4 +157,7 @@
157157
<Target Name="AfterBuild">
158158
</Target>
159159
-->
160+
<ItemGroup>
161+
<EmbeddedResource Include="ssh_used.txt" />
162+
</ItemGroup>
160163
</Project>

LibGit2Sharp.Tests/ssh_used.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
False
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
using System;
2+
using System.Runtime.Serialization;
3+
using LibGit2Sharp.Core;
4+
5+
namespace LibGit2Sharp
6+
{
7+
/// <summary>
8+
/// The exception that is thrown when an operation which requires an
9+
/// authentication fails.
10+
/// </summary>
11+
[Serializable]
12+
public class AuthenticationException : LibGit2SharpException
13+
{
14+
/// <summary>
15+
/// Initializes a new instance of the <see cref="LibGit2Sharp.AuthenticationException"/> class.
16+
/// </summary>
17+
public AuthenticationException()
18+
{
19+
}
20+
21+
/// <summary>
22+
/// Initializes a new instance of the <see cref="LibGit2Sharp.AuthenticationException"/> class with a specified error message.
23+
/// </summary>
24+
/// <param name="message">A message that describes the error.</param>
25+
public AuthenticationException(string message)
26+
: base(message)
27+
{
28+
}
29+
30+
/// <summary>
31+
/// Initializes a new instance of the <see cref="LibGit2Sharp.AuthenticationException"/> class with a specified error message and a reference to the inner exception that is the cause of this exception.
32+
/// </summary>
33+
/// <param name="message">The error message that explains the reason for the exception.</param>
34+
/// <param name="innerException">The exception that is the cause of the current exception. If the <paramref name="innerException"/> parameter is not a null reference, the current exception is raised in a catch block that handles the inner exception.</param>
35+
public AuthenticationException(string message, Exception innerException)
36+
: base(message, innerException)
37+
{
38+
}
39+
40+
/// <summary>
41+
/// Initializes a new instance of the <see cref="LibGit2Sharp.AuthenticationException"/> class with a serialized data.
42+
/// </summary>
43+
/// <param name="info">The <see cref="SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
44+
/// <param name="context">The <see cref="StreamingContext"/> that contains contextual information about the source or destination.</param>
45+
protected AuthenticationException(SerializationInfo info, StreamingContext context)
46+
: base(info, context)
47+
{
48+
}
49+
50+
internal AuthenticationException(string message, GitErrorCode code, GitErrorCategory category)
51+
: base(message, code, category)
52+
{
53+
}
54+
}
55+
}

LibGit2Sharp/Core/Ensure.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ private static readonly Dictionary<GitErrorCode, Func<string, GitErrorCode, GitE
101101
{ GitErrorCode.LockedFile, (m, r, c) => new LockedFileException(m, r, c) },
102102
{ GitErrorCode.NotFound, (m, r, c) => new NotFoundException(m, r, c) },
103103
{ GitErrorCode.Peel, (m, r, c) => new PeelException(m, r, c) },
104+
{ GitErrorCode.Auth, (m, r, c) => new AuthenticationException(m, r, c) },
104105
};
105106

106107
private static void HandleError(int result)

LibGit2Sharp/Core/GitCredentialType.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,10 @@ internal enum GitCredentialType
3232
/// TODO
3333
/// </summary>
3434
SshInteractive = (1 << 4),
35+
36+
/// <summary>
37+
/// Username only information.
38+
/// </summary>
39+
UsernameQuery = (1 << 5),
3540
}
3641
}

LibGit2Sharp/Core/NativeMethods.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,24 @@ internal static extern int git_cred_userpass_plaintext_new(
398398
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof (StrictUtf8Marshaler))] string username,
399399
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof (StrictUtf8Marshaler))] string password);
400400

401+
[DllImport(libgit2)]
402+
internal static extern int git_cred_ssh_key_new(
403+
out IntPtr cred,
404+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string username,
405+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string publickey,
406+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string privatekey,
407+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string passphrase);
408+
409+
[DllImport(libgit2)]
410+
internal static extern int git_cred_username_new(
411+
out IntPtr cred,
412+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string username);
413+
414+
[DllImport(libgit2)]
415+
internal static extern int git_cred_ssh_key_from_agent(
416+
out IntPtr cred,
417+
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalCookie = UniqueId.UniqueIdentifier, MarshalTypeRef = typeof(StrictUtf8Marshaler))] string username);
418+
401419
[DllImport(libgit2)]
402420
internal static extern int git_describe_commit(
403421
out DescribeResultSafeHandle describe,

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@
340340
<Compile Include="Core\RawContentStream.cs" />
341341
<Compile Include="Core\Handles\OdbStreamSafeHandle.cs" />
342342
<Compile Include="SupportedCredentialTypes.cs" />
343+
<Compile Include="SshUserKeyCredentials.cs" />
344+
<Compile Include="SshAgentCredentials.cs" />
345+
<Compile Include="UsernameQueryCredentials.cs" />
346+
<Compile Include="AuthenticationException.cs" />
343347
</ItemGroup>
344348
<ItemGroup>
345349
<CodeAnalysisDictionary Include="CustomDictionary.xml" />

LibGit2Sharp/RemoteCallbacks.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,14 @@ private int GitCredentialHandler(out IntPtr ptr, IntPtr cUrl, IntPtr usernameFro
256256
{
257257
types |= SupportedCredentialTypes.Default;
258258
}
259+
if (credTypes.HasFlag(GitCredentialType.SshKey))
260+
{
261+
types |= SupportedCredentialTypes.Ssh;
262+
}
263+
if (credTypes.HasFlag(GitCredentialType.UsernameQuery))
264+
{
265+
types |= SupportedCredentialTypes.UsernameQuery;
266+
}
259267

260268
var cred = CredentialsProvider(url, username, types);
261269

LibGit2Sharp/SshAgentCredentials.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
using LibGit2Sharp.Core;
3+
4+
namespace LibGit2Sharp
5+
{
6+
/// <summary>
7+
/// Class that holds SSH agent credentials for remote repository access.
8+
/// </summary>
9+
public sealed class SshAgentCredentials : Credentials
10+
{
11+
/// <summary>
12+
/// Callback to acquire a credential object.
13+
/// </summary>
14+
/// <param name="cred">The newly created credential object.</param>
15+
/// <returns>0 for success, &lt; 0 to indicate an error, &gt; 0 to indicate no credential was acquired.</returns>
16+
protected internal override int GitCredentialHandler(out IntPtr cred)
17+
{
18+
if (Username == null)
19+
{
20+
throw new InvalidOperationException("SshAgentCredentials contains a null Username.");
21+
}
22+
23+
return NativeMethods.git_cred_ssh_key_from_agent(out cred, Username);
24+
}
25+
26+
/// <summary>
27+
/// Username for SSH authentication.
28+
/// </summary>
29+
public string Username { get; set; }
30+
}
31+
}
32+

LibGit2Sharp/SshUserKeyCredentials.cs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using LibGit2Sharp.Core;
3+
4+
namespace LibGit2Sharp
5+
{
6+
/// <summary>
7+
/// Class that holds SSH username with key credentials for remote repository access.
8+
/// </summary>
9+
public sealed class SshUserKeyCredentials : Credentials
10+
{
11+
/// <summary>
12+
/// Callback to acquire a credential object.
13+
/// </summary>
14+
/// <param name="cred">The newly created credential object.</param>
15+
/// <returns>0 for success, &lt; 0 to indicate an error, &gt; 0 to indicate no credential was acquired.</returns>
16+
protected internal override int GitCredentialHandler(out IntPtr cred)
17+
{
18+
if (Username == null)
19+
{
20+
throw new InvalidOperationException("SshUserKeyCredentials contains a null Username.");
21+
}
22+
23+
if (Passphrase == null)
24+
{
25+
throw new InvalidOperationException("SshUserKeyCredentials contains a null Passphrase.");
26+
}
27+
28+
if (PublicKey == null)
29+
{
30+
throw new InvalidOperationException("SshUserKeyCredentials contains a null PublicKey.");
31+
}
32+
33+
if (PrivateKey == null)
34+
{
35+
throw new InvalidOperationException("SshUserKeyCredentials contains a null PrivateKey.");
36+
}
37+
38+
return NativeMethods.git_cred_ssh_key_new(out cred, Username, PublicKey, PrivateKey, Passphrase);
39+
}
40+
41+
/// <summary>
42+
/// Username for SSH authentication.
43+
/// </summary>
44+
public string Username { get; set; }
45+
46+
/// <summary>
47+
/// Public key file location for SSH authentication.
48+
/// </summary>
49+
public string PublicKey { get; set; }
50+
51+
/// <summary>
52+
/// Private key file location for SSH authentication.
53+
/// </summary>
54+
public string PrivateKey { get; set; }
55+
56+
/// <summary>
57+
/// Passphrase for SSH authentication.
58+
/// </summary>
59+
public string Passphrase { get; set; }
60+
}
61+
}

LibGit2Sharp/SupportedCredentialTypes.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,15 @@ public enum SupportedCredentialTypes
1818
/// Ask Windows to provide its default credentials for the current user (e.g. NTLM)
1919
/// </summary>
2020
Default = (1 << 1),
21+
22+
/// <summary>
23+
/// SSH with username and public/private key. (SshUserKeyCredentials, SshAgentCredentials)
24+
/// </summary>
25+
Ssh = (1 << 2),
26+
27+
/// <summary>
28+
/// Queries the server with the specified username, then later returns the supported credential types.
29+
/// </summary>
30+
UsernameQuery = (1 << 3),
2131
}
2232
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using LibGit2Sharp.Core;
3+
4+
namespace LibGit2Sharp
5+
{
6+
/// <summary>
7+
/// Class that holds username query credentials for remote repository access.
8+
/// </summary>
9+
public sealed class UsernameQueryCredentials : Credentials
10+
{
11+
/// <summary>
12+
/// Callback to acquire a credential object.
13+
/// </summary>
14+
/// <param name="cred">The newly created credential object.</param>
15+
/// <returns>0 for success, &lt; 0 to indicate an error, &gt; 0 to indicate no credential was acquired.</returns>
16+
protected internal override int GitCredentialHandler(out IntPtr cred)
17+
{
18+
if (Username == null)
19+
{
20+
throw new InvalidOperationException("UsernameQueryCredentials contains a null Username.");
21+
}
22+
23+
return NativeMethods.git_cred_username_new(out cred, Username);
24+
}
25+
26+
/// <summary>
27+
/// Username for querying the server for supported authentication.
28+
/// </summary>
29+
public string Username { get; set; }
30+
}
31+
}

UpdateLibgit2ToSha.ps1

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,17 @@
1111
If set, run the libgit2 tests on the desired version.
1212
.PARAMETER debug
1313
If set, build the "Debug" configuration of libgit2, rather than "RelWithDebInfo" (default).
14+
.PARAMETER ssh
15+
If set embeds SSH at the path pointed to by the value.
1416
#>
1517

1618
Param(
1719
[string]$sha = 'HEAD',
1820
[string]$vs = '10',
1921
[string]$libgit2Name = '',
2022
[switch]$test,
21-
[switch]$debug
23+
[switch]$debug,
24+
[string]$ssh = ''
2225
)
2326

2427
Set-StrictMode -Version Latest
@@ -28,12 +31,19 @@ $libgit2sharpDirectory = Split-Path $MyInvocation.MyCommand.Path
2831
$libgit2Directory = Join-Path $libgit2sharpDirectory "libgit2"
2932
$x86Directory = Join-Path $libgit2sharpDirectory "Lib\NativeBinaries\x86"
3033
$x64Directory = Join-Path $libgit2sharpDirectory "Lib\NativeBinaries\amd64"
34+
$sshFile = Join-Path $libgit2sharpDirectory "LibGit2Sharp.Tests\ssh_used.txt"
3135

3236
$build_clar = 'OFF'
3337
if ($test.IsPresent) { $build_clar = 'ON' }
3438
$configuration = "RelWithDebInfo"
3539
if ($debug.IsPresent) { $configuration = "Debug" }
3640

41+
if (![string]::IsNullOrEmpty($libgit2Name)) {
42+
$embed_ssh = '-DEMBED_SSH_PATH="$ssh"'
43+
} else {
44+
$embed_ssh = ''
45+
}
46+
3747
function Run-Command([scriptblock]$Command, [switch]$Fatal, [switch]$Quiet) {
3848
$output = ""
3949
if ($Quiet) {
@@ -144,7 +154,7 @@ function Assert-Consistent-Naming($expected, $path) {
144154
Run-Command -Quiet { & remove-item build -recurse -force }
145155
Run-Command -Quiet { & mkdir build }
146156
cd build
147-
Run-Command -Quiet -Fatal { & $cmake -G "Visual Studio $vs" -D ENABLE_TRACE=ON -D "BUILD_CLAR=$build_clar" -D "LIBGIT2_FILENAME=$binaryFilename" -DSTDCALL=ON .. }
157+
Run-Command -Quiet -Fatal { & $cmake -G "Visual Studio $vs" -D THREADSAFE=ON -D ENABLE_TRACE=ON -D "BUILD_CLAR=$build_clar" -D "LIBGIT2_FILENAME=$binaryFilename" -DSTDCALL=ON $embed_ssh .. }
148158
Run-Command -Quiet -Fatal { & $cmake --build . --config $configuration }
149159
if ($test.IsPresent) { Run-Command -Quiet -Fatal { & $ctest -V . } }
150160
cd $configuration
@@ -157,7 +167,7 @@ function Assert-Consistent-Naming($expected, $path) {
157167
cd ..
158168
Run-Command -Quiet { & mkdir build64 }
159169
cd build64
160-
Run-Command -Quiet -Fatal { & $cmake -G "Visual Studio $vs Win64" -D THREADSAFE=ON -D ENABLE_TRACE=ON -D "BUILD_CLAR=$build_clar" -D "LIBGIT2_FILENAME=$binaryFilename" -DSTDCALL=ON ../.. }
170+
Run-Command -Quiet -Fatal { & $cmake -G "Visual Studio $vs Win64" -D THREADSAFE=ON -D ENABLE_TRACE=ON -D "BUILD_CLAR=$build_clar" -D "LIBGIT2_FILENAME=$binaryFilename" -DSTDCALL=ON $embed_ssh ../.. }
161171
Run-Command -Quiet -Fatal { & $cmake --build . --config $configuration }
162172
if ($test.IsPresent) { Run-Command -Quiet -Fatal { & $ctest -V . } }
163173
cd $configuration
@@ -180,6 +190,7 @@ namespace LibGit2Sharp.Core
180190

181191
sc -Encoding ASCII (Join-Path $libgit2sharpDirectory "Libgit2sharp\Core\NativeDllName.cs") $dllNameClass
182192
sc -Encoding ASCII (Join-Path $libgit2sharpDirectory "Libgit2sharp\libgit2_hash.txt") $sha
193+
sc -Encoding ASCII (Join-Path $libgit2sharpDirectory "Libgit2sharp.Tests\ssh_used.txt") (![string]::IsNullOrEmpty($ssh))
183194

184195
$buildProperties = @"
185196
<?xml version="1.0" encoding="utf-8"?>

build.libgit2sharp.sh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
LIBGIT2SHA=`cat ./LibGit2Sharp/libgit2_hash.txt`
44
SHORTSHA=${LIBGIT2SHA:0:7}
55
EXTRADEFINE="$1"
6+
USESSH=${1-OFF}
7+
SSH_FILE="LibGit2Sharp.Tests/ssh_used.txt"
68

79
rm -rf libgit2/build
810
mkdir libgit2/build
@@ -11,13 +13,17 @@ export _BINPATH=`pwd`
1113

1214
cmake -DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo \
1315
-DBUILD_CLAR:BOOL=OFF \
14-
-DUSE_SSH=OFF \
16+
-DUSE_SSH=$USESSH \
1517
-DENABLE_TRACE=ON \
1618
-DLIBGIT2_FILENAME=git2-$SHORTSHA \
1719
-DCMAKE_OSX_ARCHITECTURES="i386;x86_64" \
1820
..
1921
cmake --build .
2022

23+
shopt -s nocasematch
24+
[[ USESSH == "ON" ]] && echo "True" > $SSH_FILE || echo "False" > $SSH_FILE
25+
shopt -u nocasematch
26+
2127
export LD_LIBRARY_PATH=$_BINPATH:$LD_LIBRARY_PATH
2228
export DYLD_LIBRARY_PATH=$_BINPATH:$DYLD_LIBRARY_PATH
2329

0 commit comments

Comments
 (0)