Skip to content

Commit f7325c4

Browse files
authored
Merge pull request libgit2#6503 from fxcoudert/hostandport
Pass hostkey & port to host verify callback
2 parents cfc3b37 + 43e84e2 commit f7325c4

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

src/libgit2/transports/ssh.c

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,8 @@ static int check_against_known_hosts(
651651
return ret;
652652
}
653653

654+
#define SSH_DEFAULT_PORT 22
655+
654656
/*
655657
* Perform the check for the session's certificate against known hosts if
656658
* possible and then ask the user if they have a callback.
@@ -748,23 +750,29 @@ static int check_certificate(
748750
if (check_cb != NULL) {
749751
git_cert_hostkey *cert_ptr = &cert;
750752
git_error_state previous_error = {0};
753+
const char *host_ptr = host;
754+
git_str host_and_port = GIT_STR_INIT;
755+
756+
if (port != SSH_DEFAULT_PORT) {
757+
git_str_printf(&host_and_port, "%s:%d", host, port);
758+
host_ptr = host_and_port.ptr;
759+
}
751760

752761
git_error_state_capture(&previous_error, error);
753-
error = check_cb((git_cert *) cert_ptr, cert_valid, host, check_cb_payload);
762+
error = check_cb((git_cert *) cert_ptr, cert_valid, host_ptr, check_cb_payload);
754763
if (error == GIT_PASSTHROUGH) {
755764
error = git_error_state_restore(&previous_error);
756765
} else if (error < 0 && !git_error_last()) {
757766
git_error_set(GIT_ERROR_NET, "unknown remote host key");
758767
}
759768

760769
git_error_state_free(&previous_error);
770+
git_str_dispose(&host_and_port);
761771
}
762772

763773
return error;
764774
}
765775

766-
#define SSH_DEFAULT_PORT "22"
767-
768776
static int _git_ssh_setup_conn(
769777
ssh_subtransport *t,
770778
const char *url,
@@ -788,15 +796,8 @@ static int _git_ssh_setup_conn(
788796
s->session = NULL;
789797
s->channel = NULL;
790798

791-
if (git_net_str_is_url(url))
792-
error = git_net_url_parse(&s->url, url);
793-
else
794-
error = git_net_url_parse_scp(&s->url, url);
795-
796-
if (error < 0)
797-
goto done;
798-
799-
if ((error = git_socket_stream_new(&s->io, s->url.host, s->url.port)) < 0 ||
799+
if ((error = git_net_url_parse_standard_or_scp(&s->url, url)) < 0 ||
800+
(error = git_socket_stream_new(&s->io, s->url.host, s->url.port)) < 0 ||
800801
(error = git_stream_connect(s->io)) < 0)
801802
goto done;
802803

@@ -806,8 +807,11 @@ static int _git_ssh_setup_conn(
806807
* as part of the stream connection, but that's not something that's
807808
* exposed.
808809
*/
809-
if (git__strntol32(&port, s->url.port, strlen(s->url.port), NULL, 10) < 0)
810-
port = -1;
810+
if (git__strntol32(&port, s->url.port, strlen(s->url.port), NULL, 10) < 0) {
811+
git_error_set(GIT_ERROR_NET, "invalid port to ssh: %s", s->url.port);
812+
error = -1;
813+
goto done;
814+
}
811815

812816
if ((error = _git_ssh_session_create(&session, &known_hosts, s->url.host, port, s->io)) < 0)
813817
goto done;

src/util/net.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,13 @@ int git_net_url_parse_scp(git_net_url *url, const char *given)
646646
return 0;
647647
}
648648

649+
int git_net_url_parse_standard_or_scp(git_net_url *url, const char *given)
650+
{
651+
return git_net_str_is_url(given) ?
652+
git_net_url_parse(url, given) :
653+
git_net_url_parse_scp(url, given);
654+
}
655+
649656
int git_net_url_joinpath(
650657
git_net_url *out,
651658
git_net_url *one,

src/util/net.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ extern int git_net_url_parse(git_net_url *url, const char *str);
3434
/** Parses a string containing an SCP style path into a URL structure. */
3535
extern int git_net_url_parse_scp(git_net_url *url, const char *str);
3636

37+
/**
38+
* Parses a string containing a standard URL or an SCP style path into
39+
* a URL structure.
40+
*/
41+
extern int git_net_url_parse_standard_or_scp(git_net_url *url, const char *str);
42+
3743
/** Appends a path and/or query string to the given URL */
3844
extern int git_net_url_joinpath(
3945
git_net_url *out,

tests/libgit2/online/clone.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -787,10 +787,19 @@ static int ssh_certificate_check(git_cert *cert, int valid, const char *host, vo
787787
{
788788
git_cert_hostkey *key;
789789
git_oid expected = GIT_OID_SHA1_ZERO, actual = GIT_OID_SHA1_ZERO;
790+
git_str expected_host = GIT_STR_INIT;
791+
git_net_url parsed_url = GIT_NET_URL_INIT;
790792

791793
GIT_UNUSED(valid);
792794
GIT_UNUSED(payload);
793795

796+
cl_git_pass(git_net_url_parse_standard_or_scp(&parsed_url, _remote_url));
797+
cl_git_pass(git_str_printf(&expected_host, "%s%s%s",
798+
parsed_url.host,
799+
git_net_url_is_default_port(&parsed_url) ? "" : ":",
800+
git_net_url_is_default_port(&parsed_url) ? "" : parsed_url.port));
801+
cl_assert_equal_s(expected_host.ptr, host);
802+
794803
cl_assert(_remote_ssh_fingerprint);
795804

796805
cl_git_pass(git_oid__fromstrp(&expected, _remote_ssh_fingerprint, GIT_OID_SHA1));
@@ -812,7 +821,8 @@ static int ssh_certificate_check(git_cert *cert, int valid, const char *host, vo
812821

813822
cl_assert(!memcmp(&expected, &actual, 20));
814823

815-
cl_assert_equal_s("localhost", host);
824+
git_net_url_dispose(&parsed_url);
825+
git_str_dispose(&expected_host);
816826

817827
return GIT_EUSER;
818828
}

0 commit comments

Comments
 (0)