You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
LibGit2: patch to pass hostkey & port to host verify callback (#39324)
It seems that no one actually verifies SSH host identity with libgit2
because the callback doesn't give enough information do so correctly:
- It doesn't give the actual host key fingerprint, but rather three
different hashes thereof. This means we cannot distinguish a known
hosts entry that has a different type (`ssh-rsa`, `ssh-dsa`, etc.)
from an entry with a matching type and a fingerprint mismatch: the
former should be treated as an unknown host whereas the latter is a
host key mismatch; they cannot be distinguished without this patch.
- If the user connects on a non-default port (i.e. not 22), this is not
passed to the callback in any way. Since there can be different known
host entries for different ports and they should be treated as
distinct, this also means the current API cannot be used to verify
hosts serving SSH on non-standard ports. This patch passes the port.
I will try to upstream some version of this patch to libgit2. The same
patch has already been applied to the LibGit2 JLL.
Fixes#38777.
Might fixJuliaLang/Pkg.jl#2334.
msg ="Please run `ssh-keyscan $host >> $(files[1])` in order to add the server to your known hosts file and then try again."
417
408
else
418
409
msg ="Please connect once using `ssh $host` in order to add the server to your known hosts file and then try again. You may not be allowed to log in (wrong user and/or no login allowed), but ssh will prompt you to add a host key for the server which will allow libgit2 to verify the server."
419
410
end
420
411
verify_host_error("SSH host verification: the server `$host` is not a known host. $msg")
verify_host_error("SSH host verification: the identity of the server `$host` does not match its known hosts record. Someone could be trying to man-in-the-middle your connection. It is also possible that the server has changed its key, in which case you should check with the server administrator and if they confirm that the key has been changed, update your known hosts file.")
423
-
elseif check == Consts.SSH_HOST_BAD_HASH
424
-
verify_host_error("SSH host verification: no secure certificate hash available for `$host`, cannot verify server identity.")
425
414
else
426
415
@error("unexpected SSH known host check result", check)
427
416
end
@@ -431,31 +420,6 @@ function certificate_callback(
431
420
return Consts.CERT_REJECT
432
421
end
433
422
434
-
## SSH known host checking
435
-
#
436
-
# We can't use libssh2_knownhost_check because libgit2, for no good reason,
437
-
# doesn't give us a host fingerprint that we can use for that and instead gives
438
-
# us multiple hashes of that fingerprint instead. Moreover, since a host can
439
-
# have multiple fingerprints in the known hosts file with different encryption
440
-
# types (gitlab.com does this, for example), we need to iterate through all the
441
-
# known hosts entries and manually check if any of them is a match.
442
-
#
443
-
# The fact that libgit2 won't give us a fingerprint also means that we cannot,
444
-
# even if we wanted to, prompt the user for whether to add the fingerprint to
445
-
# the known hosts file, since we don't have the fingerprint that should be
446
-
# added. The only option is to instruct the user how to add it themselves.
447
-
#
448
-
# Check logic: if a host appears in a known hosts file at all then one of the
449
-
# keys in that file must match or we declare a mismatch; if the host name
450
-
# doesn't appear in the file at all, however, we will continue searching files.
451
-
#
452
-
# This allows adding a host to the system known hosts file to fully override
453
-
# that host appearing in a bundled known hosts file. It is necessary to allow
454
-
# any of multiple entries in a single file to match, however, to allow for the
455
-
# possiblity that the file contains multiple fingerprints for the same host. If
456
-
# libgit2 gave us the fucking fingerprint then we could search for only an entry
457
-
# with the correct type, but we can't do that without the actual fingerprint.
458
-
459
423
struct KnownHost
460
424
magic ::Cuint
461
425
node ::Ptr{Cvoid}
@@ -465,12 +429,27 @@ struct KnownHost
465
429
end
466
430
467
431
functionssh_knownhost_check(
468
-
files ::AbstractVector{<:AbstractString},
469
-
host ::AbstractString,
470
-
hashes ::KeyHashes,
432
+
files ::AbstractVector{<:AbstractString},
433
+
host ::AbstractString,
434
+
cert ::CertHostKey,
435
+
)
436
+
key =collect(cert.data)[1:cert.len]
437
+
returnssh_knownhost_check(files, host, key)
438
+
end
439
+
440
+
functionssh_knownhost_check(
441
+
files ::AbstractVector{<:AbstractString},
442
+
host ::AbstractString,
443
+
key ::String,
471
444
)
472
-
hashes.sha1 === hashes.sha256 ===nothing&&
473
-
return Consts.SSH_HOST_BAD_HASH
445
+
if (m =match(r"^(.+):(\d+)$", host)) !==nothing
446
+
host = m.captures[1]
447
+
port =parse(Int, m.captures[2])
448
+
else
449
+
port =22# default SSH port
450
+
end
451
+
mask = Consts.LIBSSH2_KNOWNHOST_TYPE_PLAIN |
452
+
Consts.LIBSSH2_KNOWNHOST_KEYENC_RAW
474
453
session =@ccall"libssh2".libssh2_session_init_ex(
475
454
C_NULL::Ptr{Cvoid},
476
455
C_NULL::Ptr{Cvoid},
@@ -492,46 +471,32 @@ function ssh_knownhost_check(
0 commit comments