1
0
mirror of https://github.com/libssh2/libssh2.git synced 2025-11-20 02:42:09 +03:00

Agent forwarding implementation (#752)

This PR contains a series of patches that date back many years and I
believe were discussed on the mailing list, but never merged. We have
been using these in our local copy of libssh2 without issue since 2015,
if not earlier. I believe this is the full set of changes, as we tried
to use comments to mark where our copy of libssh2 differs from the
canonical version.

This also contains changes I made earlier this year, but which were not
discussed on the mailing list, to support certificates and FIDO2 keys
with agent forwarding.

Note that this is not a complete implementation of agent forwarding, as
that is outside the scope of libssh2. Clients still need to provide
their own implementation that parses ssh-agent methods after calling
libssh2_channel_read() and calls the appropriate callback messages in
libssh2. See the man page changes in this PR for more details.

Integration-patches-by: Viktor Szakats

* prefer size_t
* prefer unsigned int over u_int in public function
* add const
* docs, indent, checksrc, debug call, compiler warning fixes
This commit is contained in:
Michael Buckley
2023-04-22 01:54:20 -07:00
committed by GitHub
parent fba0b52b6a
commit bc4e619e76
12 changed files with 551 additions and 26 deletions

View File

@@ -383,6 +383,7 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
int rc;
unsigned char *method_name = NULL;
uint32_t sign_flags = 0;
ssize_t plain_len;
/* Create a request to sign the data */
if(transctx->state == agent_NB_state_init) {
@@ -478,9 +479,13 @@ agent_sign(LIBSSH2_SESSION *session, unsigned char **sig, size_t *sig_len,
memcpy(method_name, s, method_len);
s += method_len;
plain_len = plain_method((char *)session->userauth_pblc_method,
session->userauth_pblc_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)) {
if(((size_t)method_len != session->userauth_pblc_method_len &&
method_len != plain_len) ||
memcmp(method_name, session->userauth_pblc_method, method_len)) {
_libssh2_debug((session,
LIBSSH2_TRACE_KEX,
"Agent sign method %.*s",
@@ -829,6 +834,57 @@ libssh2_agent_userauth(LIBSSH2_AGENT *agent,
return rc;
}
/*
* libssh2_agent_sign
*
* Sign a payload using a system-installed ssh-agent.
*
* Returns 0 if succeeded, or a negative value for error.
*/
LIBSSH2_API int
libssh2_agent_sign(LIBSSH2_AGENT *agent,
struct libssh2_agent_publickey *identity,
unsigned char **sig,
size_t *s_len,
const unsigned char *data,
size_t d_len,
const char *method,
unsigned int method_len)
{
void *abstract = agent;
int rc;
uint32_t methodLen;
if(agent->session->userauth_pblc_state == libssh2_NB_state_idle) {
memset(&agent->transctx, 0, sizeof(agent->transctx));
agent->identity = identity->node;
}
if(identity->blob_len < sizeof(uint32_t)) {
return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
methodLen = _libssh2_ntohu32(identity->blob);
if(identity->blob_len < sizeof(uint32_t) + methodLen) {
return LIBSSH2_ERROR_BUFFER_TOO_SMALL;
}
agent->session->userauth_pblc_method_len = method_len;
agent->session->userauth_pblc_method = LIBSSH2_ALLOC(agent->session,
method_len);
memcpy(agent->session->userauth_pblc_method, method, methodLen);
rc = agent_sign(agent->session, sig, s_len, data, d_len, &abstract);
LIBSSH2_FREE(agent->session, agent->session->userauth_pblc_method);
agent->session->userauth_pblc_method = NULL;
agent->session->userauth_pblc_method_len = 0;
return rc;
}
/*
* libssh2_agent_disconnect
*