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;