From 9d7fc9d50b895650f1ec301021b4a202a0fcb3cb Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Tue, 11 May 2010 02:08:29 +0200 Subject: [PATCH] Use the new expand functions. This implements escape chars for IdentityFile in ssh_config and reads the system ssh_config. --- include/libssh/priv.h | 2 +- libssh/auth.c | 18 +---- libssh/client.c | 9 +++ libssh/keyfiles.c | 30 +++------ libssh/options.c | 152 +++++++++++++++++++++++------------------- 5 files changed, 106 insertions(+), 105 deletions(-) diff --git a/include/libssh/priv.h b/include/libssh/priv.h index dd1031d0..d9bd02e7 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -249,8 +249,8 @@ int gettimeofday(struct timeval *__p, void *__t); /* options.c */ -char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir); int ssh_options_set_algo(ssh_session session, int algo, const char *list); +int ssh_options_apply(ssh_session session); /** Free memory space */ #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) diff --git a/libssh/auth.c b/libssh/auth.c index b67d57d8..0098a401 100644 --- a/libssh/auth.c +++ b/libssh/auth.c @@ -864,16 +864,11 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { for (it = ssh_list_get_iterator(session->identity); it != NULL; it = it->next) { - char *privkey_file = NULL; + const char *privkey_file = it->data; int privkey_open = 0; privkey = NULL; - privkey_file = dir_expand_dup(session, it->data, 1); - if (privkey_file == NULL) { - continue; - } - ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkey_file); rc = ssh_try_publickey_from_file(session, privkey_file, &pubkey_string, &type); @@ -886,7 +881,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { ssh_log(session, SSH_LOG_RARE, "Reading private key %s failed (bad passphrase ?)", privkey_file); - SAFE_FREE(privkey_file); leave_function(); return SSH_AUTH_ERROR; } @@ -894,7 +888,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { pubkey = publickey_from_privatekey(privkey); if (pubkey == NULL) { - SAFE_FREE(privkey_file); privatekey_free(privkey); ssh_set_error_oom(session); leave_function(); @@ -905,7 +898,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { type = pubkey->type; publickey_free(pubkey); if (pubkey_string == NULL) { - SAFE_FREE(privkey_file); ssh_set_error_oom(session); leave_function(); return SSH_AUTH_ERROR; @@ -914,7 +906,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { len = strlen(privkey_file) + 5; publickey_file = malloc(len); if (publickey_file == NULL) { - SAFE_FREE(privkey_file); ssh_set_error_oom(session); leave_function(); return SSH_AUTH_ERROR; @@ -927,13 +918,11 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { } SAFE_FREE(publickey_file); } else if (rc < 0) { - SAFE_FREE(privkey_file); continue; } rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string); if (rc == SSH_AUTH_ERROR){ - SAFE_FREE(privkey_file); string_free(pubkey_string); ssh_log(session, SSH_LOG_RARE, "Publickey authentication error"); leave_function(); @@ -941,7 +930,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { } else { if (rc != SSH_AUTH_SUCCESS){ ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server"); - SAFE_FREE(privkey_file); string_free(pubkey_string); continue; } @@ -956,7 +944,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { ssh_log(session, SSH_LOG_RARE, "Reading private key %s failed (bad passphrase ?)", privkey_file); - SAFE_FREE(privkey_file); string_free(pubkey_string); continue; /* continue the loop with other pubkey */ } @@ -964,7 +951,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey); if (rc == SSH_AUTH_ERROR) { - SAFE_FREE(privkey_file); string_free(pubkey_string); privatekey_free(privkey); leave_function(); @@ -973,7 +959,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { if (rc != SSH_AUTH_SUCCESS){ ssh_log(session, SSH_LOG_FUNCTIONS, "The server accepted the public key but refused the signature"); - SAFE_FREE(privkey_file); string_free(pubkey_string); privatekey_free(privkey); continue; @@ -983,7 +968,6 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { /* auth success */ ssh_log(session, SSH_LOG_PROTOCOL, "Successfully authenticated using %s", privkey_file); - SAFE_FREE(privkey_file); string_free(pubkey_string); privatekey_free(privkey); diff --git a/libssh/client.c b/libssh/client.c index 56267784..3999f990 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -482,6 +482,7 @@ int ssh_connect(ssh_session session) { int ssh1 = 0; int ssh2 = 0; int fd = -1; + int ret; if (session == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid session pointer"); @@ -503,6 +504,14 @@ int ssh_connect(ssh_session session) { leave_function(); return SSH_ERROR; } + + ret = ssh_options_apply(session); + if (ret < 0) { + ssh_set_error(session, SSH_FATAL, "Couldn't apply options"); + leave_function(); + return SSH_ERROR; + } + if (session->fd != -1) { fd = session->fd; #ifndef _WIN32 diff --git a/libssh/keyfiles.c b/libssh/keyfiles.c index eaecc979..7a738e91 100644 --- a/libssh/keyfiles.c +++ b/libssh/keyfiles.c @@ -1130,8 +1130,6 @@ int ssh_try_publickey_from_file(ssh_session session, const char *keyfile, ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct keytab, char **privkeyfile, int *type) { - char *public; - char *private; const char *priv; const char *pub; char *new; @@ -1152,21 +1150,15 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k } } - /* are them readable ? */ - public=dir_expand_dup(session,pub,1); - private=dir_expand_dup(session,priv,1); - //snprintf(public, sizeof(public), "%s/%s", session->sshdir, pub); - //snprintf(private, sizeof(private), "%s/%s", session->sshdir, priv); - - ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", public); - if (!ssh_file_readaccess_ok(public)) { - ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", public); + ssh_log(session, SSH_LOG_PACKET, "Trying to open publickey %s", pub); + if (!ssh_file_readaccess_ok(pub)) { + ssh_log(session, SSH_LOG_PACKET, "Failed to open publickey %s", pub); goto error; } - ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", private); - if (!ssh_file_readaccess_ok(private)) { - ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", private); + ssh_log(session, SSH_LOG_PACKET, "Trying to open privatekey %s", priv); + if (!ssh_file_readaccess_ok(priv)) { + ssh_log(session, SSH_LOG_PACKET, "Failed to open privatekey %s", priv); goto error; } @@ -1176,26 +1168,24 @@ ssh_string try_publickey_from_file(ssh_session session, struct ssh_keys_struct k * We are sure both the private and public key file is readable. We return * the public as a string, and the private filename as an argument */ - pubkey = publickey_from_file(session, public, type); + pubkey = publickey_from_file(session, pub, type); if (pubkey == NULL) { ssh_log(session, SSH_LOG_PACKET, "Wasn't able to open public key file %s: %s", - public, + pub, ssh_get_error(session)); goto error; } - new = realloc(*privkeyfile, strlen(private) + 1); + new = realloc(*privkeyfile, strlen(priv) + 1); if (new == NULL) { string_free(pubkey); goto error; } - strcpy(new, private); + strcpy(new, priv); *privkeyfile = new; error: - SAFE_FREE(public); - SAFE_FREE(private); return pubkey; } diff --git a/libssh/options.c b/libssh/options.c index 0c881cde..033c91f2 100644 --- a/libssh/options.c +++ b/libssh/options.c @@ -162,58 +162,6 @@ int ssh_options_set_algo(ssh_session session, int algo, return 0; } -char *dir_expand_dup(ssh_session session, const char *value, int allowsshdir) { - char *new; - - if (value[0] == '~' && value[1] == '/') { - char *homedir = ssh_get_user_home_dir(); - size_t lv, lh; - - if (homedir == NULL) { - return NULL; - } - lv = strlen(value + 1); - lh = strlen(homedir); - - new = malloc(lv + lh + 1); - if (new == NULL) { - ssh_set_error_oom(session); - SAFE_FREE(homedir); - return NULL; - } - memcpy(new, homedir, lh); - SAFE_FREE(homedir); - memcpy(new + lh, value + 1, lv + 1); - return new; - } - if (allowsshdir && strncmp(value, "SSH_DIR/", 8) == 0) { - size_t lv, ls; - if (session->sshdir == NULL) { - if (ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL) < 0) - return NULL; - } - - value += 7; - lv = strlen(value); - ls = strlen(session->sshdir); - - new = malloc(lv + ls + 1); - if (new == NULL) { - ssh_set_error_oom(session); - return NULL; - } - memcpy(new, session->sshdir, ls); - memcpy(new + ls, value, lv + 1); - return new; - } - new = strdup(value); - if (new == NULL) { - ssh_set_error_oom(session); - return NULL; - } - return new; -} - /** * @brief This function can set all possible ssh options. * @@ -468,15 +416,14 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, case SSH_OPTIONS_SSH_DIR: if (value == NULL) { SAFE_FREE(session->sshdir); - /* TODO: why ~/.ssh/ instead of ~/.ssh ? */ - session->sshdir = dir_expand_dup(session, "~/.ssh/", 0); + session->sshdir = ssh_path_expand_tilde("~/.ssh/"); if (session->sshdir == NULL) { return -1; } } else { SAFE_FREE(session->sshdir); - session->sshdir = dir_expand_dup(session, value, 0); + session->sshdir = ssh_path_expand_tilde(value); if (session->sshdir == NULL) { return -1; } @@ -488,27 +435,28 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, ssh_set_error_invalid(session, __FUNCTION__); return -1; } - q = dir_expand_dup(session, value, 1); + q = strdup(value); if (q == NULL) { - return -1; + return -1; } rc = ssh_list_prepend(session->identity, q); if (rc < 0) { - SAFE_FREE(q); return -1; } break; case SSH_OPTIONS_KNOWNHOSTS: if (value == NULL) { SAFE_FREE(session->knownhosts); - session->knownhosts = dir_expand_dup(session, - "SSH_DIR/known_hosts", 1); + if (session->sshdir == NULL) { + return -1; + } + session->knownhosts = ssh_path_expand_escape(session, "%d/known_hosts"); if (session->knownhosts == NULL) { return -1; } } else { SAFE_FREE(session->knownhosts); - session->knownhosts = dir_expand_dup(session, value, 1); + session->knownhosts = strdup(value); if (session->knownhosts == NULL) { return -1; } @@ -621,7 +569,12 @@ int ssh_options_set(ssh_session session, enum ssh_options_e type, ssh_set_error_invalid(session, __FUNCTION__); return -1; } else { - session->ProxyCommand = strdup(value); + SAFE_FREE(session->ProxyCommand); + q = strdup(value); + if (q == NULL) { + return -1; + } + session->ProxyCommand = q; } break; default: @@ -1062,19 +1015,84 @@ int ssh_options_parse_config(ssh_session session, const char *filename) { return -1; } + if (session->sshdir == NULL) { + r = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL); + if (r < 0) { + ssh_set_error_oom(session); + return -1; + } + } + /* set default filename */ if (filename == NULL) { - expanded_filename = dir_expand_dup(session, "SSH_DIR/config", 1); + expanded_filename = ssh_path_expand_escape(session, "%d/config"); } else { - expanded_filename = dir_expand_dup(session, filename, 1); + expanded_filename = ssh_path_expand_escape(session, filename); } - if (expanded_filename == NULL) + if (expanded_filename == NULL) { return -1; + } r = ssh_config_parse_file(session, expanded_filename); + if (r < 0) { + goto out; + } + if (filename == NULL) { + r = ssh_config_parse_file(session, "/etc/ssh/ssh_config"); + } + +out: free(expanded_filename); return r; } -/** @} */ -/* vim: set ts=2 sw=2 et cindent: */ +int ssh_options_apply(ssh_session session) { + struct ssh_iterator *it; + char *tmp; + int rc; + + if (session->sshdir == NULL) { + rc = ssh_options_set(session, SSH_OPTIONS_SSH_DIR, NULL); + if (rc < 0) { + return -1; + } + } + + if (session->knownhosts == NULL) { + tmp = ssh_path_expand_escape(session, "%d/known_hosts"); + } else { + tmp = ssh_path_expand_escape(session, session->knownhosts); + } + if (tmp == NULL) { + return -1; + } + free(session->knownhosts); + session->knownhosts = tmp; + + if (session->ProxyCommand != NULL) { + tmp = ssh_path_expand_escape(session, session->ProxyCommand); + if (tmp == NULL) { + return -1; + } + free(session->ProxyCommand); + session->ProxyCommand = tmp; + } + + for (it = ssh_list_get_iterator(session->identity); + it != NULL; + it = it->next) { + char *id = (char *) it->data; + tmp = ssh_path_expand_escape(session, id); + if (tmp == NULL) { + return -1; + } + free(id); + it->data = tmp; + } + + return 0; +} + +/* @} */ + +/* vim: set ts=4 sw=4 et cindent: */