From f643c34ee85f0542cbb8d9dc63703f61cc142238 Mon Sep 17 00:00:00 2001 From: "Bernhard R. Link" Date: Thu, 24 Sep 2009 20:36:49 +0200 Subject: [PATCH] support in ~/ and SSH_DIR/ in filenames instead of %s/ Get rid of snprintf to fixed sized buffers in setting options. Instead make locations starting with ~/ relative to the users initial working directory (as libssh does not look into the home directory but only at the initial home directory). and starting with SSH_DIR/ relative to the configured ssh directory. --- libssh/options.c | 81 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 26 deletions(-) diff --git a/libssh/options.c b/libssh/options.c index 3a6ec61f..95bc0a2d 100644 --- a/libssh/options.c +++ b/libssh/options.c @@ -236,6 +236,41 @@ static int ssh_options_set_algo(ssh_options opt, int algo, const char *list) { return 0; } +static char *dir_expand_dup(ssh_options opt, const char *value, int allowsshdir) { + char *n; + + if (value[0] == '~' && value[1] == '/') { + const char *homedir = ssh_get_user_home_dir(); + size_t lv = strlen(value + 1), lh = strlen(homedir); + + n = malloc(lv + lh + 1); + if (n == NULL) + return NULL; + memcpy(n, homedir, lh); + memcpy(n + lh + 1, value + 1, lv + 1); + return n; + } + if (allowsshdir && strncmp(value, "SSH_DIR/", 8) == 0) { + size_t lv, ls; + if (opt->ssh_dir == NULL) { + if (ssh_options_set(opt, SSH_OPTIONS_SSH_DIR, NULL) < 0) + return NULL; + } + + value += 7; + lv = strlen(value); + ls = strlen(opt->ssh_dir); + + n = malloc(lv + ls + 1); + if (n == NULL) + return NULL; + memcpy(n, opt->ssh_dir, ls); + memcpy(n + ls + 1, value, lv + 1); + return n; + } + return strdup(value); +} + /** * @brief This function can set all possible ssh options. * @@ -390,7 +425,6 @@ static int ssh_options_set_algo(ssh_options opt, int algo, const char *list) { */ int ssh_options_set(ssh_options opt, enum ssh_options_e type, const void *value) { - char buf[1024] = {0}; char *p, *q; int i; @@ -484,16 +518,16 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, break; case SSH_OPTIONS_SSH_DIR: if (value == NULL) { - snprintf(buf, sizeof(buf), "%s/.ssh/", ssh_get_user_home_dir()); - opt->ssh_dir = strdup(buf); + SAFE_FREE(opt->ssh_dir); + /* TODO: why ~/.ssh/ instead of ~/.ssh ? */ + + opt->ssh_dir = dir_expand_dup(opt, "~/.ssh/", 0); if (opt->ssh_dir == NULL) { return -1; } } else { - /* do we really want it this way? */ - snprintf(buf, sizeof(buf), value, ssh_get_user_home_dir()); SAFE_FREE(opt->ssh_dir); - opt->ssh_dir = strdup(buf); + opt->ssh_dir = dir_expand_dup(opt, value, 0); if (opt->ssh_dir == NULL) { return -1; } @@ -504,28 +538,23 @@ int ssh_options_set(ssh_options opt, enum ssh_options_e type, if (value == NULL) { return -1; } - snprintf(buf, sizeof(buf), value, ssh_get_user_home_dir()); SAFE_FREE(opt->identity); - opt->identity = strdup(buf); + opt->identity = dir_expand_dup(opt, value, 1); if (opt->identity == NULL) { return -1; } break; case SSH_OPTIONS_KNOWNHOSTS: if (value == NULL) { - if (ssh_options_set(opt, SSH_OPTIONS_SSH_DIR, NULL) < 0) { - return -1; - } - - snprintf(buf, sizeof(buf), "%s/known_hosts", opt->ssh_dir); - opt->known_hosts_file = strdup(buf); + SAFE_FREE(opt->known_hosts_file); + opt->known_hosts_file = dir_expand_dup(opt, + "SSH_DIR/known_hosts", 1); if (opt->known_hosts_file == NULL) { return -1; } } else { - snprintf(buf, sizeof(buf), value, ssh_get_user_home_dir()); SAFE_FREE(opt->known_hosts_file); - opt->known_hosts_file = strdup(buf); + opt->known_hosts_file = dir_expand_dup(opt, value, 1); if (opt->known_hosts_file == NULL) { return -1; } @@ -1287,25 +1316,25 @@ int ssh_options_set_auth_callback(ssh_options opt, ssh_auth_callback cb, * @see ssh_options_set_host() */ int ssh_options_parse_config(ssh_options opt, const char *filename) { - char buffer[1024] = {0}; + char *expanded_filename; + int r; if (opt == NULL || opt->host == NULL) { return -1; } - if (opt->ssh_dir == NULL) { - if (ssh_options_default_ssh_dir(opt) < 0) { - return -1; - } - } - /* set default filename */ if (filename == NULL) { - snprintf(buffer, 1024, "%s/config", opt->ssh_dir); - filename = buffer; + expanded_filename = dir_expand_dup(opt, "SSH_DIR/config", 1); + } else { + expanded_filename = dir_expand_dup(opt, filename, 1); } + if (expanded_filename == NULL) + return -1; - return ssh_config_parse_file(opt, filename); + r = ssh_config_parse_file(opt, filename); + free(expanded_filename); + return r; } /** @} */