From 2b45e61f74767c5877800a3fd721288109b5d94f Mon Sep 17 00:00:00 2001 From: Norbert Pocs Date: Wed, 16 Nov 2022 16:51:02 +0100 Subject: [PATCH] Add flags for escape expand operation Calling `ssh_options_apply` more times can result in an unwanted behaviour of expanding the escape characters more times. Adding flags to check if the expansion was already done on the current string variables. Signed-off-by: Norbert Pocs Reviewed-by: Jakub Jelen (cherry picked from commit 1bd499febbc29591b2e028d0cec9c4dd3c98d869) --- include/libssh/session.h | 7 +++ src/options.c | 103 +++++++++++++++++++++++---------------- src/session.c | 2 + 3 files changed, 69 insertions(+), 43 deletions(-) diff --git a/include/libssh/session.h b/include/libssh/session.h index e22b0d67..cf219c2a 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -93,6 +93,12 @@ enum ssh_pending_call_e { #define SSH_OPT_FLAG_KBDINT_AUTH 0x4 #define SSH_OPT_FLAG_GSSAPI_AUTH 0x8 +/* Escape expansion of different variables */ +#define SSH_OPT_EXP_FLAG_KNOWNHOSTS 0x1 +#define SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS 0x2 +#define SSH_OPT_EXP_FLAG_PROXYCOMMAND 0x4 +#define SSH_OPT_EXP_FLAG_IDENTITY 0x8 + /* extensions flags */ /* negotiation enabled */ #define SSH_EXT_NEGOTIATION 0x01 @@ -232,6 +238,7 @@ struct ssh_session_struct { char *gss_client_identity; int gss_delegate_creds; int flags; + int exp_flags; int nodelay; bool config_processed; uint8_t options_seen[SOC_MAX]; diff --git a/src/options.c b/src/options.c index bc920e68..bd0481e2 100644 --- a/src/options.c +++ b/src/options.c @@ -687,6 +687,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, ssh_set_error_oom(session); return -1; } + session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_KNOWNHOSTS; } break; case SSH_OPTIONS_GLOBAL_KNOWNHOSTS: @@ -708,6 +709,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, ssh_set_error_oom(session); return -1; } + session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS; } break; case SSH_OPTIONS_TIMEOUT: @@ -950,6 +952,7 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, return -1; } session->opts.ProxyCommand = q; + session->opts.exp_flags &= ~SSH_OPT_EXP_FLAG_PROXYCOMMAND; } } break; @@ -1508,53 +1511,67 @@ int ssh_options_apply(ssh_session session) } } - if (session->opts.knownhosts == NULL) { - tmp = ssh_path_expand_escape(session, "%d/known_hosts"); - } else { - tmp = ssh_path_expand_escape(session, session->opts.knownhosts); - } - if (tmp == NULL) { - return -1; - } - free(session->opts.knownhosts); - session->opts.knownhosts = tmp; - - if (session->opts.global_knownhosts == NULL) { - tmp = strdup("/etc/ssh/ssh_known_hosts"); - } else { - tmp = ssh_path_expand_escape(session, session->opts.global_knownhosts); - } - if (tmp == NULL) { - return -1; - } - free(session->opts.global_knownhosts); - session->opts.global_knownhosts = tmp; - - if (session->opts.ProxyCommand != NULL) { - char *p = NULL; - size_t plen = strlen(session->opts.ProxyCommand) + - 5 /* strlen("exec ") */; - - if (strncmp(session->opts.ProxyCommand, "exec ", 5) != 0) { - p = malloc(plen + 1 /* \0 */); - if (p == NULL) { - return -1; - } - - rc = snprintf(p, plen + 1, "exec %s", session->opts.ProxyCommand); - if ((size_t)rc != plen) { - free(p); - return -1; - } + if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_KNOWNHOSTS) == 0) { + if (session->opts.knownhosts == NULL) { + tmp = ssh_path_expand_escape(session, "%d/known_hosts"); + } else { + tmp = ssh_path_expand_escape(session, session->opts.knownhosts); } - - tmp = ssh_path_expand_escape(session, p); - free(p); if (tmp == NULL) { return -1; } - free(session->opts.ProxyCommand); - session->opts.ProxyCommand = tmp; + free(session->opts.knownhosts); + session->opts.knownhosts = tmp; + session->opts.exp_flags |= SSH_OPT_EXP_FLAG_KNOWNHOSTS; + } + + if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS) == 0) { + if (session->opts.global_knownhosts == NULL) { + tmp = strdup("/etc/ssh/ssh_known_hosts"); + } else { + tmp = ssh_path_expand_escape(session, + session->opts.global_knownhosts); + } + if (tmp == NULL) { + return -1; + } + free(session->opts.global_knownhosts); + session->opts.global_knownhosts = tmp; + session->opts.exp_flags |= SSH_OPT_EXP_FLAG_GLOBAL_KNOWNHOSTS; + } + + + if ((session->opts.exp_flags & SSH_OPT_EXP_FLAG_PROXYCOMMAND) == 0) { + if (session->opts.ProxyCommand != NULL) { + char *p = NULL; + size_t plen = strlen(session->opts.ProxyCommand) + + 5 /* strlen("exec ") */; + + if (strncmp(session->opts.ProxyCommand, "exec ", 5) != 0) { + p = malloc(plen + 1 /* \0 */); + if (p == NULL) { + return -1; + } + + rc = snprintf(p, plen + 1, "exec %s", session->opts.ProxyCommand); + if ((size_t)rc != plen) { + free(p); + return -1; + } + tmp = ssh_path_expand_escape(session, p); + free(p); + } else { + tmp = ssh_path_expand_escape(session, + session->opts.ProxyCommand); + } + + if (tmp == NULL) { + return -1; + } + free(session->opts.ProxyCommand); + session->opts.ProxyCommand = tmp; + session->opts.exp_flags |= SSH_OPT_EXP_FLAG_PROXYCOMMAND; + } } for (tmp = ssh_list_pop_head(char *, session->opts.identity_non_exp); diff --git a/src/session.c b/src/session.c index f94f719f..51c832c5 100644 --- a/src/session.c +++ b/src/session.c @@ -114,6 +114,8 @@ ssh_session ssh_new(void) SSH_OPT_FLAG_KBDINT_AUTH | SSH_OPT_FLAG_GSSAPI_AUTH; + session->opts.exp_flags = 0; + session->opts.identity = ssh_list_new(); if (session->opts.identity == NULL) { goto err;