mirror of
https://github.com/libssh2/libssh2.git
synced 2025-08-10 06:23:02 +03:00
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:
@@ -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
|
||||||
|
27
src/agent.c
27
src/agent.c
@@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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
|
||||||
rc = _libssh2_key_sign_algorithm(session,
|
* it is our first auth attempt, otherwise fallback to
|
||||||
&session->userauth_pblc_method,
|
* the key default algo */
|
||||||
&session->userauth_pblc_method_len);
|
if(auth_attempts == 1) {
|
||||||
|
rc = _libssh2_key_sign_algorithm(session,
|
||||||
|
&session->userauth_pblc_method,
|
||||||
|
&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;
|
||||||
|
Reference in New Issue
Block a user