1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-08-10 06:23:02 +03:00

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)
This commit is contained in:
Will Cosgrove
2022-01-14 11:55:18 -08:00
committed by GitHub
parent 50a1262772
commit de7a74aff2
3 changed files with 62 additions and 9 deletions

View File

@@ -508,6 +508,7 @@ typedef struct _LIBSSH2_POLLFD {
#define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48 #define LIBSSH2_ERROR_KEYFILE_AUTH_FAILED -48
#define LIBSSH2_ERROR_RANDGEN -49 #define LIBSSH2_ERROR_RANDGEN -49
#define LIBSSH2_ERROR_MISSING_USERAUTH_BANNER -50 #define LIBSSH2_ERROR_MISSING_USERAUTH_BANNER -50
#define LIBSSH2_ERROR_ALGO_UNSUPPORTED -51
/* this is a define to provide the old (<= 1.2.7) name */ /* this is a define to provide the old (<= 1.2.7) name */
#define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV #define LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_BANNER_RECV

View File

@@ -379,6 +379,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
ssize_t method_len; ssize_t method_len;
unsigned char *s; unsigned char *s;
int rc; int rc;
unsigned char *method_name = NULL;
uint32_t sign_flags = 0; uint32_t sign_flags = 0;
/* Create a request to sign the data */ /* 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; rc = LIBSSH2_ERROR_AGENT_PROTOCOL;
goto error; 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; 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 */ /* Read the signature */
len -= 4; len -= 4;
if(len < 0) { if(len < 0) {
@@ -489,12 +510,18 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
memcpy(*sig, s, *sig_len); memcpy(*sig, s, *sig_len);
error: error:
if(method_name)
LIBSSH2_FREE(session, method_name);
LIBSSH2_FREE(session, transctx->request); LIBSSH2_FREE(session, transctx->request);
transctx->request = NULL; transctx->request = NULL;
LIBSSH2_FREE(session, transctx->response); LIBSSH2_FREE(session, transctx->response);
transctx->response = NULL; transctx->response = NULL;
transctx->state = agent_NB_state_init;
return _libssh2_error(session, rc, "agent sign failure"); return _libssh2_error(session, rc, "agent sign failure");
} }

View File

@@ -1283,9 +1283,6 @@ _libssh2_key_sign_algorithm(LIBSSH2_SESSION *session,
if(key_method) { if(key_method) {
memcpy(*key_method, match, match_len); memcpy(*key_method, match, match_len);
*key_method_len = match_len; *key_method_len = match_len;
_libssh2_debug(session, LIBSSH2_TRACE_KEX,
"Signing using %.*s", match_len, match);
} }
else { else {
*key_method_len = 0; *key_method_len = 0;
@@ -1321,6 +1318,10 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
}; };
int rc; int rc;
unsigned char *s; unsigned char *s;
int auth_attempts = 0;
retry_auth:
auth_attempts++;
if(session->userauth_pblc_state == libssh2_NB_state_idle) { if(session->userauth_pblc_state == libssh2_NB_state_idle) {
@@ -1364,13 +1365,26 @@ _libssh2_userauth_publickey(LIBSSH2_SESSION *session,
session->userauth_pblc_method_len); session->userauth_pblc_method_len);
} }
/* upgrade key key signing algo needed */ /* 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, rc = _libssh2_key_sign_algorithm(session,
&session->userauth_pblc_method, &session->userauth_pblc_method,
&session->userauth_pblc_method_len); &session->userauth_pblc_method_len);
if(rc) if(rc)
return 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) + * 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, return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN,
"Would block"); "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) { else if(rc) {
LIBSSH2_FREE(session, session->userauth_pblc_method); LIBSSH2_FREE(session, session->userauth_pblc_method);
session->userauth_pblc_method = NULL; session->userauth_pblc_method = NULL;