libssh2/backport-Legacy-Agent-support-for-rsa2-key-upgrading-downgrad.patch
renmingshuai 094d32ebc3 backport some upstream patches
(cherry picked from commit 495b3e6ae9e25b1e305daed917b41dd1578d6002)
2023-03-30 10:08:09 +08:00

173 lines
5.9 KiB
Diff

From de7a74aff24c47b2f2e9815f0a98598195d602e4 Mon Sep 17 00:00:00 2001
From: Will Cosgrove <will@panic.com>
Date: Fri, 14 Jan 2022 11:55:18 -0800
Subject: [PATCH] Legacy Agent support for rsa2 key upgrading/downgrading #659
(#662)
Files: libssh2.h, agent.c, userauth.c
Notes:
Part 2 of the fix for #659. This adds rsa key downgrading for agents that don't support sha2 upgrading. It also adds better trace output for debugging/logging around key upgrading.
Credit:
Will Cosgrove (signed off by Michael Buckley)
Conflict:NA
Reference:https://github.com/libssh2/commit/de7a74aff24c47b2f2e9815f0a98598195d602e4
---
include/libssh2.h | 1 +
src/agent.c | 27 +++++++++++++++++++++++++++
src/userauth.c | 43 ++++++++++++++++++++++++++++++++++---------
3 files changed, 62 insertions(+), 9 deletions(-)
diff --git a/include/libssh2.h b/include/libssh2.h
index 20ba548..15dda6f 100644
--- a/include/libssh2.h
+++ b/include/libssh2.h
@@ -508,5 +508,6 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48
#define LIBSSH2_ERROR_RANDGEN -49
+#define LIBSSH2_ERROR_ALGO_UNSUPPORTED -51
/* this is a define to provide the old (<= 1.2.7) name */
#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV
diff --git a/src/agent.c b/src/agent.c
index bce7175..4ed79ac 100644
--- a/src/agent.c
+++ b/src/agent.c
@@ -379,6 +379,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
ssize_t method_len;
unsigned char *s;
int rc;
+ unsigned char *method_name = NULL;
uint32_t sign_flags = 0;
/* Create a request to sign the data */
@@ -465,8 +466,28 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error;
}
+
+ /* method name */
+ method_name = LIBSSH2_ALLOC(session, method_len);
+ if(!method_name) {
+ rc = LIBSSH2_ERROR_ALLOC;
+ goto error;
+ }
+ memcpy(method_name, s, method_len);
s += method_len;
+ /* check to see if we match requested */
+ if((size_t)method_len != session->userauth_pblc_method_len ||
+ memcmp(method_name, session->userauth_pblc_method, method_len)) {
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_KEX,
+ "Agent sign method %.*s",
+ method_len, method_name);
+
+ rc = LIBSSH2_ERROR_ALGO_UNSUPPORTED;
+ goto error;
+ }
+
/* Read the signature */
len -= 4;
if(len < 0) {
@@ -489,12 +510,18 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
memcpy(*sig, s, *sig_len);
error:
+
+ if(method_name)
+ LIBSSH2_FREE(session, method_name);
+
LIBSSH2_FREE(session, transctx->request);
transctx->request = NULL;
LIBSSH2_FREE(session, transctx->response);
transctx->response = NULL;
+ transctx->state = agent_NB_state_init;
+
return _libssh2_error(session, rc, "agent sign failure");
}
diff --git a/src/userauth.c b/src/userauth.c
index 84285bf..59b76ca 100644
--- a/src/userauth.c
+++ b/src/userauth.c
@@ -1283,9 +1283,6 @@ _libssh2_key_sign_algorithm(LIBSSH2_SESSION *session,
if(key_method) {
memcpy(*key_method, match, match_len);
*key_method_len = match_len;
-
- _libssh2_debug(session, LIBSSH2_TRACE_KEX,
- "Signing using %.*s", match_len, match);
}
else {
*key_method_len = 0;
@@ -1321,6 +1318,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
};
int rc;
unsigned char *s;
+ int auth_attempts = 0;
+
+ retry_auth:
+ auth_attempts++;
if(session->userauth_pblc_state == libssh2_NB_state_idle) {
@@ -1364,13 +1365,26 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_method_len);
}
- /* upgrade key key signing algo needed */
- rc = _libssh2_key_sign_algorithm(session,
- &session->userauth_pblc_method,
- &session->userauth_pblc_method_len);
+ /* upgrade key signing algo if it is supported and
+ * it is our first auth attempt, otherwise fallback to
+ * the key default algo */
+ if(auth_attempts == 1) {
+ rc = _libssh2_key_sign_algorithm(session,
+ &session->userauth_pblc_method,
+ &session->userauth_pblc_method_len);
- if(rc)
- return rc;
+ if(rc)
+ return rc;
+ }
+
+ if(session->userauth_pblc_method_len &&
+ session->userauth_pblc_method) {
+ _libssh2_debug(session,
+ LIBSSH2_TRACE_KEX,
+ "Signing using %.*s",
+ session->userauth_pblc_method_len,
+ session->userauth_pblc_method);
+ }
/*
* 45 = packet_type(1) + username_len(4) + servicename_len(4) +
@@ -1528,6 +1542,17 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block");
}
+ else if(rc == LIBSSH2_ERROR_ALGO_UNSUPPORTED && auth_attempts == 1) {
+ /* try again with the default key algo */
+ LIBSSH2_FREE(session, session->userauth_pblc_method);
+ session->userauth_pblc_method = NULL;
+ LIBSSH2_FREE(session, session->userauth_pblc_packet);
+ session->userauth_pblc_packet = NULL;
+ session->userauth_pblc_state = libssh2_NB_state_idle;
+
+ rc = LIBSSH2_ERROR_NONE;
+ goto retry_auth;
+ }
else if(rc) {
LIBSSH2_FREE(session, session->userauth_pblc_method);
session->userauth_pblc_method = NULL;
--
2.23.0