From 51a53cc6d445a88a0fff10342b97e29f962989c8 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Tue, 20 Jul 2021 17:50:44 -0700 Subject: [PATCH] add support for identityagent ssh_config option This commit adds an `agent_socket` field to the session options and connects the config parser to that option. `SSH_OPTIONS_IDENTITY_AGENT` is added to allow applications to set this option for themselves. agent.c is updated to take the `agent_socket` value in preference to the `SSH_AUTH_SOCK` environment variable. Signed-off-by: Wez Furlong Reviewed-by: Andreas Schneider --- include/libssh/config.h | 1 + include/libssh/libssh.h | 1 + include/libssh/session.h | 1 + src/agent.c | 3 ++- src/config.c | 8 +++++++- src/options.c | 21 +++++++++++++++++++++ src/socket.c | 3 ++- 7 files changed, 35 insertions(+), 3 deletions(-) diff --git a/include/libssh/config.h b/include/libssh/config.h index 7d218d59..a24d11a1 100644 --- a/include/libssh/config.h +++ b/include/libssh/config.h @@ -61,6 +61,7 @@ enum ssh_config_opcode_e { SOC_PUBKEYAUTHENTICATION, SOC_PUBKEYACCEPTEDKEYTYPES, SOC_REKEYLIMIT, + SOC_IDENTITYAGENT, SOC_MAX /* Keep this one last in the list */ }; diff --git a/include/libssh/libssh.h b/include/libssh/libssh.h index deb9af9a..6a034db9 100644 --- a/include/libssh/libssh.h +++ b/include/libssh/libssh.h @@ -407,6 +407,7 @@ enum ssh_options_e { SSH_OPTIONS_REKEY_DATA, SSH_OPTIONS_REKEY_TIME, SSH_OPTIONS_RSA_MIN_SIZE, + SSH_OPTIONS_IDENTITY_AGENT, }; enum { diff --git a/include/libssh/session.h b/include/libssh/session.h index 3798f380..55a10e48 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -219,6 +219,7 @@ struct ssh_session_struct { char *ProxyCommand; char *custombanner; char *moduli_file; + char *agent_socket; unsigned long timeout; /* seconds */ unsigned long timeout_usec; unsigned int port; diff --git a/src/agent.c b/src/agent.c index 2e1d33b3..017b244f 100644 --- a/src/agent.c +++ b/src/agent.c @@ -220,7 +220,8 @@ static int agent_connect(ssh_session session) { if (session->agent->channel != NULL) return 0; - auth_sock = getenv("SSH_AUTH_SOCK"); + auth_sock = session->opts.agent_socket ? + session->opts.agent_socket : getenv("SSH_AUTH_SOCK"); if (auth_sock && *auth_sock) { if (ssh_socket_unix(session->agent->sock, auth_sock) < 0) { diff --git a/src/config.c b/src/config.c index fb143983..d005fb3b 100644 --- a/src/config.c +++ b/src/config.c @@ -104,7 +104,7 @@ static struct ssh_config_keyword_table_s ssh_config_keyword_table[] = { { "hostbasedacceptedalgorithms", SOC_UNSUPPORTED}, { "hostkeyalias", SOC_UNSUPPORTED}, { "identitiesonly", SOC_UNSUPPORTED}, - { "identityagent", SOC_UNSUPPORTED}, + { "identityagent", SOC_IDENTITYAGENT}, { "ipqos", SOC_UNSUPPORTED}, { "kbdinteractivedevices", SOC_UNSUPPORTED}, { "nohostauthenticationforlocalhost", SOC_UNSUPPORTED}, @@ -1161,6 +1161,12 @@ ssh_config_parse_line(ssh_session session, SSH_LOG(SSH_LOG_INFO, "Unknown option: %s, line: %d", keyword, count); break; + case SOC_IDENTITYAGENT: + p = ssh_config_get_str_tok(&s, NULL); + if (p && *parsing) { + ssh_options_set(session, SSH_OPTIONS_IDENTITY_AGENT, p); + } + break; default: ssh_set_error(session, SSH_FATAL, "ERROR - unimplemented opcode: %d", opcode); diff --git a/src/options.c b/src/options.c index a2cde25d..b7d54b39 100644 --- a/src/options.c +++ b/src/options.c @@ -476,6 +476,11 @@ int ssh_options_set_algo(ssh_session session, * Setting 0 will revert the value to defaults. * Default is 1024 bits or 2048 bits in FIPS mode. * (int *) + + * - SSH_OPTIONS_IDENTITY_AGENT + * Set the path to the SSH agent socket. If unset, the + * SSH_AUTH_SOCK environment is consulted. + * (const char *) * * @param value The value to set. This is a generic pointer and the * datatype which is used should be set according to the @@ -1056,6 +1061,22 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, session->opts.rsa_min_size = *x; } break; + case SSH_OPTIONS_IDENTITY_AGENT: + v = value; + SAFE_FREE(session->opts.agent_socket); + if (v == NULL) { + /* The default value will be set by the ssh_options_apply() */ + } else if (v[0] == '\0') { + ssh_set_error_invalid(session); + return -1; + } else { + session->opts.agent_socket = ssh_path_expand_tilde(v); + if (session->opts.agent_socket == NULL) { + ssh_set_error_oom(session); + return -1; + } + } + break; default: ssh_set_error(session, SSH_REQUEST_DENIED, "Unknown ssh option %d", type); return -1; diff --git a/src/socket.c b/src/socket.c index c7c6a9cc..d7f17fe8 100644 --- a/src/socket.c +++ b/src/socket.c @@ -445,7 +445,8 @@ int ssh_socket_unix(ssh_socket s, const char *path) #endif if (connect(fd, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { - ssh_set_error(s->session, SSH_FATAL, "Error from connect(): %s", + ssh_set_error(s->session, SSH_FATAL, "Error from connect(%s): %s", + path, strerror(errno)); CLOSE_SOCKET(fd); return -1;