Skip to content

Commit 338b04c

Browse files
authored
Add support for SSH authentication using libssh2 (#8)
1 parent 9d45b66 commit 338b04c

9 files changed

Lines changed: 101 additions & 6 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
bin/
99
obj/
1010
.vs/
11+
libssh2-wincng-manifest/
12+
libssh2-wincng-installed/

Dockerfile.linux

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
66
pkg-config \
77
ca-certificates \
88
git \
9+
libssl-dev \
10+
libssh2-1-dev \
911
&& rm -rf /var/lib/apt/lists/*
1012

1113
WORKDIR /nativebinaries

Dockerfile.linux-musl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
FROM alpine:3.19
22

3-
RUN apk add --no-cache bash build-base cmake
3+
RUN apk add --no-cache bash build-base cmake openssl-dev libssh2-dev
44

55
WORKDIR /nativebinaries
66
COPY . /nativebinaries/

build.libgit2.ps1

Lines changed: 63 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ $x86Directory = Join-Path $projectDirectory "nuget.package\runtimes\win-x86\nati
2929
$x64Directory = Join-Path $projectDirectory "nuget.package\runtimes\win-x64\native"
3030
$arm64Directory = Join-Path $projectDirectory "nuget.package\runtimes\win-arm64\native"
3131
$hashFile = Join-Path $projectDirectory "nuget.package\libgit2\libgit2_hash.txt"
32-
$sha = Get-Content $hashFile
32+
$sha = Get-Content $hashFile
3333
$binaryFilename = "git2-" + $sha.Substring(0,7)
3434

3535
$build_tests = 'OFF'
@@ -101,6 +101,56 @@ function Assert-Consistent-Naming($expected, $path) {
101101
Ensure-Property $expected $dll.VersionInfo.OriginalFilename "VersionInfo.OriginalFilename" $dll.Fullname
102102
}
103103

104+
function Install-Libssh2($arch) {
105+
$triplet = "$arch-windows"
106+
107+
$vcpkg = Join-Path $Env:VCPKG_INSTALLATION_ROOT "vcpkg.exe"
108+
if (-not (Test-Path $vcpkg)) {
109+
throw "Error: vcpkg not found at $Env:VCPKG_INSTALLATION_ROOT"
110+
}
111+
112+
# Install libssh2 with the WinCNG crypto backend (no OpenSSL dependency).
113+
# 'openssl' is a default vcpkg feature for libssh2, so manifest mode is required
114+
# to override it — classic mode has no --no-default-features flag.
115+
# The overlay triplet injects -DENABLE_ECDSA_WINCNG=ON into every package's
116+
# cmake configure step (zlib ignores it; libssh2 uses it).
117+
$manifestDir = Join-Path $projectDirectory "libssh2-wincng-manifest"
118+
New-Item -ItemType Directory -Force -Path $manifestDir | Out-Null
119+
@"
120+
{
121+
"name": "libssh2-wincng",
122+
"version": "1.0.0",
123+
"dependencies": [
124+
{
125+
"name": "libssh2",
126+
"default-features": false,
127+
"features": ["zlib"]
128+
}
129+
]
130+
}
131+
"@ | Set-Content (Join-Path $manifestDir "vcpkg.json")
132+
133+
$installRoot = Join-Path $projectDirectory "libssh2-wincng-installed"
134+
$overlayTriplets = Join-Path $projectDirectory "libssh2-wincng-triplets"
135+
136+
Write-Host "Installing libssh2 (WinCNG + ECDSA) for $triplet via vcpkg..."
137+
Push-Location $manifestDir
138+
try {
139+
Run-Command -Fatal -Quiet { & $vcpkg install --vcpkg-root $Env:VCPKG_INSTALLATION_ROOT --triplet $triplet "--x-install-root=$installRoot" "--overlay-triplets=$overlayTriplets" }
140+
} finally {
141+
Pop-Location
142+
}
143+
144+
$installedDir = Join-Path $installRoot $triplet
145+
146+
return @{
147+
IncludeDir = Join-Path $installedDir "include"
148+
LibDir = Join-Path $installedDir "lib"
149+
BinDir = Join-Path $installedDir "bin"
150+
Prefix = $installedDir
151+
}
152+
}
153+
104154
try {
105155
if ((!$x86.isPresent -and !$x64.IsPresent) -and !$arm64.IsPresent) {
106156
Write-Output -Stderr "Error: usage $MyInvocation.MyCommand [-x86] [-x64] [-arm64]"
@@ -118,7 +168,8 @@ try {
118168

119169
if ($x86.IsPresent) {
120170
Write-Output "Building x86..."
121-
Run-Command -Fatal { & $cmake -A Win32 -D USE_SSH=exec -D USE_HTTPS=Schannel -D "BUILD_TESTS=$build_tests" -D "BUILD_CLI=OFF" -D "LIBGIT2_FILENAME=$binaryFilename" .. }
171+
$ssh2 = Install-Libssh2 "x86"
172+
Run-Command -Fatal { & $cmake -A Win32 -D USE_SSH=ON -D USE_HTTPS=Schannel -D "BUILD_TESTS=$build_tests" -D "BUILD_CLI=OFF" -D "LIBGIT2_FILENAME=$binaryFilename" -D "CMAKE_PREFIX_PATH=$($ssh2.Prefix)" .. }
122173
Run-Command -Fatal { & $cmake --build . --config $configuration }
123174
if ($test.IsPresent) { Run-Command -Quiet -Fatal { & $ctest -V . } }
124175
cd $configuration
@@ -127,14 +178,17 @@ try {
127178
Run-Command -Quiet { & rm $x86Directory\* -ErrorAction Ignore }
128179
Run-Command -Quiet { & mkdir -fo $x86Directory }
129180
Run-Command -Quiet -Fatal { & copy -fo * $x86Directory -Exclude *.lib }
181+
Run-Command -Quiet -Fatal { & copy -fo (Join-Path $ssh2.BinDir "*.dll") $x86Directory }
182+
if (-not (Test-Path (Join-Path $x86Directory "libssh2.dll"))) { throw "Error: libssh2.dll was not copied to $x86Directory" }
130183
cd ..
131184
}
132185

133186
if ($x64.IsPresent) {
134187
Write-Output "Building x64..."
188+
$ssh2 = Install-Libssh2 "x64"
135189
Run-Command -Quiet { & mkdir build64 }
136190
cd build64
137-
Run-Command -Fatal { & $cmake -A x64 -D USE_SSH=exec -D USE_HTTPS=Schannel -D "BUILD_TESTS=$build_tests" -D "BUILD_CLI=OFF" -D "LIBGIT2_FILENAME=$binaryFilename" ../.. }
191+
Run-Command -Fatal { & $cmake -A x64 -D USE_SSH=ON -D USE_HTTPS=Schannel -D "BUILD_TESTS=$build_tests" -D "BUILD_CLI=OFF" -D "LIBGIT2_FILENAME=$binaryFilename" -D "CMAKE_PREFIX_PATH=$($ssh2.Prefix)" ../.. }
138192
Run-Command -Fatal { & $cmake --build . --config $configuration }
139193
if ($test.IsPresent) { Run-Command -Quiet -Fatal { & $ctest -V . } }
140194
cd $configuration
@@ -143,13 +197,16 @@ try {
143197
Run-Command -Quiet { & rm $x64Directory\* -ErrorAction Ignore }
144198
Run-Command -Quiet { & mkdir -fo $x64Directory }
145199
Run-Command -Quiet -Fatal { & copy -fo * $x64Directory -Exclude *.lib }
200+
Run-Command -Quiet -Fatal { & copy -fo (Join-Path $ssh2.BinDir "*.dll") $x64Directory }
201+
if (-not (Test-Path (Join-Path $x64Directory "libssh2.dll"))) { throw "Error: libssh2.dll was not copied to $x64Directory" }
146202
}
147203

148204
if ($arm64.IsPresent) {
149205
Write-Output "Building arm64..."
206+
$ssh2 = Install-Libssh2 "arm64"
150207
Run-Command -Quiet { & mkdir buildarm64 }
151208
cd buildarm64
152-
Run-Command -Fatal { & $cmake -A ARM64 -D USE_SSH=exec -D USE_HTTPS=Schannel -D "BUILD_TESTS=$build_tests" -D "BUILD_CLI=OFF" -D "LIBGIT2_FILENAME=$binaryFilename" ../.. }
209+
Run-Command -Fatal { & $cmake -A ARM64 -D USE_SSH=ON -D USE_HTTPS=Schannel -D "BUILD_TESTS=$build_tests" -D "BUILD_CLI=OFF" -D "LIBGIT2_FILENAME=$binaryFilename" -D "CMAKE_PREFIX_PATH=$($ssh2.Prefix)" ../.. }
153210
Run-Command -Fatal { & $cmake --build . --config $configuration }
154211
if ($test.IsPresent) { Run-Command -Quiet -Fatal { & $ctest -V . } }
155212
cd $configuration
@@ -158,6 +215,8 @@ try {
158215
Run-Command -Quiet { & rm $arm64Directory\* -ErrorAction Ignore }
159216
Run-Command -Quiet { & mkdir -fo $arm64Directory }
160217
Run-Command -Quiet -Fatal { & copy -fo * $arm64Directory -Exclude *.lib }
218+
Run-Command -Quiet -Fatal { & copy -fo (Join-Path $ssh2.BinDir "*.dll") $arm64Directory }
219+
if (-not (Test-Path (Join-Path $arm64Directory "libssh2.dll"))) { throw "Error: libssh2.dll was not copied to $arm64Directory" }
161220
}
162221

163222
Write-Output "Done!"

build.libgit2.sh

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ ARCH=`uname -m`
99
PACKAGEPATH="nuget.package/runtimes"
1010
OSXARCHITECTURE=$ARCH
1111

12+
EXTRA_CMAKE_FLAGS=""
13+
1214
if [[ $OS == "Darwin" ]]; then
1315
USEHTTPS="ON"
1416
if [[ $RID == "osx-arm64" ]]; then
@@ -18,6 +20,7 @@ if [[ $OS == "Darwin" ]]; then
1820
fi
1921
else
2022
USEHTTPS="OpenSSL-Dynamic"
23+
EXTRA_CMAKE_FLAGS="-DCMAKE_BUILD_RPATH='\$ORIGIN'"
2124
fi
2225

2326
rm -rf libgit2/build
@@ -28,11 +31,12 @@ export _BINPATH=`pwd`
2831

2932
cmake -DCMAKE_BUILD_TYPE:STRING=Release \
3033
-DBUILD_TESTS:BOOL=OFF \
31-
-DUSE_SSH=exec \
34+
-DUSE_SSH=ON \
3235
-DLIBGIT2_FILENAME=git2-$SHORTSHA \
3336
-DCMAKE_OSX_ARCHITECTURES=$OSXARCHITECTURE \
3437
-DUSE_HTTPS=$USEHTTPS \
3538
-DUSE_BUNDLED_ZLIB=ON \
39+
$EXTRA_CMAKE_FLAGS \
3640
..
3741
cmake --build .
3842

@@ -53,3 +57,22 @@ rm -rf $PACKAGEPATH/$RID
5357
mkdir -p $PACKAGEPATH/$RID/native
5458

5559
cp libgit2/build/libgit2-$SHORTSHA.$LIBEXT $PACKAGEPATH/$RID/native
60+
61+
# Bundle libssh2 shared library alongside libgit2
62+
LIBGIT2_PATH="$PACKAGEPATH/$RID/native/libgit2-$SHORTSHA.$LIBEXT"
63+
64+
if [[ $OS == "Darwin" ]]; then
65+
echo "macOS: libssh2 sourced from global installation"
66+
else
67+
# Linux: find libssh2 via ldd
68+
LIBSSH2_PATH=$(ldd "$LIBGIT2_PATH" | grep libssh2 | awk '{print $3}')
69+
if [[ -z "$LIBSSH2_PATH" ]]; then
70+
echo "ERROR: libgit2 does not appear to link against libssh2"
71+
exit 1
72+
fi
73+
74+
LIBSSH2_BASENAME=$(basename "$LIBSSH2_PATH")
75+
76+
echo "Bundling $LIBSSH2_BASENAME from $LIBSSH2_PATH"
77+
cp "$LIBSSH2_PATH" "$PACKAGEPATH/$RID/native/$LIBSSH2_BASENAME"
78+
fi
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
set(VCPKG_TARGET_ARCHITECTURE arm64)
2+
include("${CMAKE_CURRENT_LIST_DIR}/wincng-options.cmake")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
set(VCPKG_CRT_LINKAGE dynamic)
2+
set(VCPKG_LIBRARY_LINKAGE dynamic)
3+
set(VCPKG_CMAKE_CONFIGURE_OPTIONS "-DENABLE_ECDSA_WINCNG=ON")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
set(VCPKG_TARGET_ARCHITECTURE x64)
2+
include("${CMAKE_CURRENT_LIST_DIR}/wincng-options.cmake")
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
set(VCPKG_TARGET_ARCHITECTURE x86)
2+
include("${CMAKE_CURRENT_LIST_DIR}/wincng-options.cmake")

0 commit comments

Comments
 (0)