diff options
Diffstat (limited to 'libssh/auth.c')
-rw-r--r-- | libssh/auth.c | 251 |
1 files changed, 115 insertions, 136 deletions
diff --git a/libssh/auth.c b/libssh/auth.c index b89f57d0..c73afb05 100644 --- a/libssh/auth.c +++ b/libssh/auth.c @@ -35,6 +35,7 @@ #include "libssh/buffer.h" #include "libssh/agent.h" #include "libssh/keyfiles.h" +#include "libssh/misc.h" #include "libssh/packet.h" #include "libssh/session.h" #include "libssh/keys.h" @@ -902,42 +903,6 @@ error: return rc; } -#ifdef _MSC_VER -static const char privKey_1[] = "SSH_DIR/identity"; -static const char pubKey_1[] = "SSH_DIR/identity.pub"; -static const char privKey_2[] = "SSH_DIR/id_dsa"; -static const char pubKey_2[] = "SSH_DIR/id_dsa.pub"; -static const char privKey_3[] = "SSH_DIR/id_rsa"; -static const char pubKey_3[] = "SSH_DIR/id_rsa.pub"; -/** Used different var to allow const char[] declaration */ -static struct ssh_keys_struct keytab[] = { - { privKey_1, pubKey_1}, - { privKey_2, pubKey_2}, - { privKey_3, pubKey_3}, - {0} -}; -#else -/* This requires GCC extensions */ -static struct ssh_keys_struct keytab[] = { - { - .privatekey = "SSH_DIR/identity", - .publickey = "SSH_DIR/identity.pub" - }, - { - .privatekey = "SSH_DIR/id_dsa", - .publickey = "SSH_DIR/id_dsa.pub", - }, - { - .privatekey = "SSH_DIR/id_rsa", - .publickey = "SSH_DIR/id_rsa.pub", - }, - { - .privatekey = NULL, - .publickey = NULL - } -}; -#endif - /** * @brief Tries to automatically authenticate with public key and "none" * @@ -961,13 +926,10 @@ static struct ssh_keys_struct keytab[] = { * @see ssh_options_set() */ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { - struct ssh_public_key_struct *publickey; - ssh_string pubkey; + struct ssh_iterator *it; ssh_private_key privkey; - char *privkeyfile = NULL; - char *id = NULL; - size_t size; - unsigned int i = 0; + ssh_public_key pubkey; + ssh_string pubkey_string; int type = 0; int rc; @@ -983,41 +945,40 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { /* Try authentication with ssh-agent first */ #ifndef _WIN32 if (agent_is_running(session)) { + char *privkey_file = NULL; + ssh_log(session, SSH_LOG_RARE, "Trying to authenticate with SSH agent keys as user: %s", session->username); - for (publickey = agent_get_first_ident(session, &privkeyfile); - publickey != NULL; - publickey = agent_get_next_ident(session, &privkeyfile)) { + for (pubkey = agent_get_first_ident(session, &privkey_file); + pubkey != NULL; + pubkey = agent_get_next_ident(session, &privkey_file)) { - ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkeyfile); + ssh_log(session, SSH_LOG_RARE, "Trying identity %s", privkey_file); - pubkey = publickey_to_string(publickey); - if (pubkey) { - rc = ssh_userauth_offer_pubkey(session, NULL, publickey->type, pubkey); - string_free(pubkey); + pubkey_string = publickey_to_string(pubkey); + if (pubkey_string) { + rc = ssh_userauth_offer_pubkey(session, NULL, pubkey->type, pubkey_string); + string_free(pubkey_string); if (rc == SSH_AUTH_ERROR) { - SAFE_FREE(id); - SAFE_FREE(privkeyfile); - publickey_free(publickey); + SAFE_FREE(privkey_file); + publickey_free(pubkey); leave_function(); return rc; } else if (rc != SSH_AUTH_SUCCESS) { ssh_log(session, SSH_LOG_PROTOCOL, "Public key refused by server"); - SAFE_FREE(id); - SAFE_FREE(privkeyfile); - publickey_free(publickey); + SAFE_FREE(privkey_file); + publickey_free(pubkey); continue; } ssh_log(session, SSH_LOG_PROTOCOL, "Public key accepted"); /* pubkey accepted by server ! */ - rc = ssh_userauth_agent_pubkey(session, NULL, publickey); + rc = ssh_userauth_agent_pubkey(session, NULL, pubkey); if (rc == SSH_AUTH_ERROR) { - SAFE_FREE(id); - SAFE_FREE(privkeyfile); - publickey_free(publickey); + SAFE_FREE(privkey_file); + publickey_free(pubkey); leave_function(); return rc; @@ -1025,100 +986,129 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { ssh_log(session, SSH_LOG_RARE, "Server accepted public key but refused the signature ;" " It might be a bug of libssh"); - SAFE_FREE(id); - SAFE_FREE(privkeyfile); - publickey_free(publickey); + SAFE_FREE(privkey_file); + publickey_free(pubkey); continue; } /* auth success */ ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success", - privkeyfile); - SAFE_FREE(id); - SAFE_FREE(privkeyfile); - publickey_free(publickey); + privkey_file); + SAFE_FREE(privkey_file); + publickey_free(pubkey); leave_function(); return SSH_AUTH_SUCCESS; } /* if pubkey */ - SAFE_FREE(id); - SAFE_FREE(privkeyfile); - publickey_free(publickey); + SAFE_FREE(privkey_file); + publickey_free(pubkey); } /* for each privkey */ } /* if agent is running */ #endif - size = ARRAY_SIZE(keytab); - if (session->identity) { - ssh_log(session, SSH_LOG_PROTOCOL, - "Trying identity file %s", session->identity); + for (it = ssh_list_get_iterator(session->identity); + it != NULL; + it = it->next) { + char *privkey_file = NULL; + int privkey_open = 0; - id = malloc(strlen(session->identity) + 1 + 4); - if (id == NULL) { - leave_function(); - return SSH_AUTH_ERROR; + privkey_file = dir_expand_dup(session, it->data, 1); + if (privkey_file == NULL) { + continue; } - sprintf(id, "%s.pub", session->identity); - keytab[size - 1].privatekey = session->identity; - keytab[size - 1].publickey = id; - } + 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); + if (rc == 1) { + char *publickey_file; + size_t len; - for (i = 0, pubkey = try_publickey_from_file(session, keytab[i], - &privkeyfile, &type); - i < size; - pubkey = try_publickey_from_file(session, keytab[i++], - &privkeyfile, &type)) { - if (pubkey == NULL) { + privkey = privatekey_from_file(session, privkey_file, type, passphrase); + if (privkey == NULL) { + 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; + } + privkey_open = 1; + + pubkey = publickey_from_privatekey(privkey); + if (pubkey == NULL) { + SAFE_FREE(privkey_file); + privatekey_free(privkey); + ssh_set_error_oom(session); + leave_function(); + return SSH_AUTH_ERROR; + } + + pubkey_string = publickey_to_string(pubkey); + 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; + } + + 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; + } + snprintf(publickey_file, len, "%s.pub", privkey_file); + rc = ssh_publickey_to_file(session, publickey_file, pubkey_string, type); + if (rc < 0) { + ssh_log(session, SSH_LOG_PACKET, + "Could not write public key to file: %s", publickey_file); + } + SAFE_FREE(publickey_file); + } else if (rc < 0) { + SAFE_FREE(privkey_file); continue; } - rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey); + rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string); if (rc == SSH_AUTH_ERROR){ - if (id != NULL) { - keytab[size - 1].privatekey = NULL; - keytab[size - 1].publickey = NULL; - SAFE_FREE(id); - } - string_free(pubkey); - SAFE_FREE(privkeyfile); + SAFE_FREE(privkey_file); + string_free(pubkey_string); ssh_log(session, SSH_LOG_RARE, "Publickey authentication error"); leave_function(); return rc; } else { if (rc != SSH_AUTH_SUCCESS){ ssh_log(session, SSH_LOG_PROTOCOL, "Publickey refused by server"); - string_free(pubkey); - pubkey = NULL; - SAFE_FREE(privkeyfile); - privkeyfile = NULL; + SAFE_FREE(privkey_file); + string_free(pubkey_string); continue; } } /* Public key accepted by server! */ - ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", privkeyfile); - privkey = privatekey_from_file(session, privkeyfile, type, passphrase); - if (privkey == NULL) { - ssh_log(session, SSH_LOG_RARE, - "Reading private key %s failed (bad passphrase ?)", - privkeyfile); - string_free(pubkey); - pubkey = NULL; - SAFE_FREE(privkeyfile); - privkeyfile = NULL; - continue; /* continue the loop with other pubkey */ + if (!privkey_open) { + ssh_log(session, SSH_LOG_PROTOCOL, "Trying to read privatekey %s", + privkey_file); + privkey = privatekey_from_file(session, privkey_file, type, passphrase); + if (privkey == NULL) { + 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 */ + } } - rc = ssh_userauth_pubkey(session, NULL, pubkey, privkey); + rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey); if (rc == SSH_AUTH_ERROR) { - if (id != NULL) { - keytab[size - 1].privatekey = NULL; - keytab[size - 1].publickey = NULL; - SAFE_FREE(id); - } - string_free(pubkey); - SAFE_FREE(privkeyfile); + SAFE_FREE(privkey_file); + string_free(pubkey_string); privatekey_free(privkey); leave_function(); return rc; @@ -1126,10 +1116,8 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { if (rc != SSH_AUTH_SUCCESS){ ssh_log(session, SSH_LOG_RARE, "The server accepted the public key but refused the signature"); - string_free(pubkey); - pubkey = NULL; - SAFE_FREE(privkeyfile); - privkeyfile = NULL; + SAFE_FREE(privkey_file); + string_free(pubkey_string); privatekey_free(privkey); continue; } @@ -1137,28 +1125,19 @@ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { /* auth success */ ssh_log(session, SSH_LOG_PROTOCOL, - "Successfully authenticated using %s", privkeyfile); - string_free(pubkey); + "Successfully authenticated using %s", privkey_file); + SAFE_FREE(privkey_file); + string_free(pubkey_string); privatekey_free(privkey); - SAFE_FREE(privkeyfile); - if (id != NULL) { - keytab[size - 1].privatekey = NULL; - keytab[size - 1].publickey = NULL; - SAFE_FREE(id); - } leave_function(); return SSH_AUTH_SUCCESS; } + /* at this point, pubkey is NULL and so is privkeyfile */ ssh_log(session, SSH_LOG_PROTOCOL, "Tried every public key, none matched"); ssh_set_error(session,SSH_NO_ERROR,"No public key matched"); - if (id) { - keytab[size - 1].privatekey = NULL; - keytab[size - 1].publickey = NULL; - SAFE_FREE(id); - } leave_function(); return SSH_AUTH_DENIED; |