diff options
Diffstat (limited to 'ssh-common.c')
-rw-r--r-- | ssh-common.c | 388 |
1 files changed, 0 insertions, 388 deletions
diff --git a/ssh-common.c b/ssh-common.c deleted file mode 100644 index bfa48b5..0000000 --- a/ssh-common.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com> - This file is part of gluster-block. - - This file is licensed to you under your choice of the GNU Lesser - General Public License, version 3 or any later version (LGPLv3 or - later), or the GNU General Public License, version 2 (GPLv2), in all - cases as published by the Free Software Foundation. -*/ - - -# define _GNU_SOURCE - -# include <stdio.h> -# include <stdlib.h> -# include <string.h> -# include <stdbool.h> -# include <errno.h> -# include <uuid/uuid.h> - -# include "utils.h" -# include "ssh-common.h" - - - -static int -glusterBlockSSHAuthKbdint(ssh_session blksession, const char *password) -{ - int err; - const char *ret; - const char *answer; - char buffer[128]; - size_t i; - int n; - - err = ssh_userauth_kbdint(blksession, NULL, NULL); - while (err == SSH_AUTH_INFO) { - ret = ssh_userauth_kbdint_getname(blksession); - if (ret && strlen(ret) > 0) - MSG("%s", ret); - - ret = ssh_userauth_kbdint_getinstruction(blksession); - if (ret && strlen(ret) > 0) - MSG("%s", ret); - - n = ssh_userauth_kbdint_getnprompts(blksession); - for (i = 0; i < n; i++) { - char echo; - - ret = ssh_userauth_kbdint_getprompt(blksession, i, &echo); - if (!ret) - break; - - if (echo) { - char *p; - - MSG("%s", ret); - - if (!fgets(buffer, sizeof(buffer), stdin)) - return SSH_AUTH_ERROR; - - buffer[sizeof(buffer) - 1] = '\0'; - if ((p = strchr(buffer, '\n'))) - *p = '\0'; - - if (ssh_userauth_kbdint_setanswer(blksession, i, buffer) < 0) - return SSH_AUTH_ERROR; - - memset(buffer, 0, strlen(buffer)); - } else { - if (password && strstr(ret, "Password:")) { - answer = password; - } else { - buffer[0] = '\0'; - - if (ssh_getpass(ret, buffer, sizeof(buffer), 0, 0) < 0) - return SSH_AUTH_ERROR; - - answer = buffer; - } - err = ssh_userauth_kbdint_setanswer(blksession, i, answer); - memset(buffer, 0, sizeof(buffer)); - if (err < 0) - return SSH_AUTH_ERROR; - } - } - err = ssh_userauth_kbdint(blksession, NULL, NULL); - } - - return err; -} - - -static int -glusterBlockSSHAuthConsole(ssh_session blksession) -{ - int rc; - int method; - char *banner; - char password[128] = {0}; - - // Try to authenticate - rc = ssh_userauth_none(blksession, NULL); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } - - method = ssh_userauth_list(blksession, NULL); - - while (rc != SSH_AUTH_SUCCESS) { - - // Try to authenticate through the "gssapi-with-mic" method. - if (method & SSH_AUTH_METHOD_GSSAPI_MIC) { - rc = ssh_userauth_gssapi(blksession); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } else if (rc == SSH_AUTH_SUCCESS) { - break; - } - } - - // Try to authenticate with public key first - if (method & SSH_AUTH_METHOD_PUBLICKEY) { - rc = ssh_userauth_publickey_auto(blksession, NULL, NULL); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } else if (rc == SSH_AUTH_SUCCESS) { - break; - } - } - - // Try to authenticate with keyboard interactive"; - if (method & SSH_AUTH_METHOD_INTERACTIVE) { - rc = glusterBlockSSHAuthKbdint(blksession, NULL); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } else if (rc == SSH_AUTH_SUCCESS) { - break; - } - } - - if (ssh_getpass("Password: ", password, sizeof(password), - 0, 0) < 0) - return SSH_AUTH_ERROR; - - // Try to authenticate with password - if (method & SSH_AUTH_METHOD_PASSWORD) { - rc = ssh_userauth_password(blksession, NULL, password); - if (rc == SSH_AUTH_ERROR) { - ERROR("%s", ssh_get_error(blksession)); - return rc; - } else if (rc == SSH_AUTH_SUCCESS) { - break; - } - } - - memset(password, 0, sizeof(password)); - } - - banner = ssh_get_issue_banner(blksession); - if (banner) { - ERROR("%s", banner); - ssh_string_free_char(banner); - } - - return rc; -} - - -static int -glusterBlockSSHVerifyKnownHost(ssh_session blksession) -{ - ssh_key srv_pubkey; - unsigned char *hash = NULL; - char *hexa; - char buf[10]; - size_t hlen; - int rc; - int ret; - - rc = ssh_get_publickey(blksession, &srv_pubkey); - if (rc < 0) - return -1; - - rc = ssh_get_publickey_hash(srv_pubkey, - SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen); - ssh_key_free(srv_pubkey); - if (rc < 0) - return -1; - - switch (ssh_is_server_known(blksession)) { - - case SSH_SERVER_KNOWN_OK: - break; /* ok we have password less access */ - - case SSH_SERVER_KNOWN_CHANGED: - ERROR("%s", "Host key for server changed : server's one is new :"); - ssh_print_hexa("Public key hash", hash, hlen); - ssh_clean_pubkey_hash(&hash); - ERROR("%s", "For security reason, connection will be stopped"); - return -1; - - case SSH_SERVER_FOUND_OTHER: - ERROR("%s", "The host key for this server was not found, but an other " - "type of key exists."); - ERROR("%s", "An attacker might change the default server key to " - "confuse your client into thinking the key does not exist" - "\nWe advise you to rerun the client with -d or -r for " - "more safety."); - return -1; - - case SSH_SERVER_FILE_NOT_FOUND: - ERROR("%s", "Could not find known host file. If you accept the host " - "key here, the file will be automatically created."); - /* fallback to SSH_SERVER_NOT_KNOWN behavior */ - - case SSH_SERVER_NOT_KNOWN: - hexa = ssh_get_hexa(hash, hlen); - ERROR("The server is unknown. Do you trust the host key ?\n" - "Public key hash: %s", hexa); - ssh_string_free_char(hexa); - if (!fgets(buf, sizeof(buf), stdin)) { - ret = -1; - goto fail; - } - if (strncasecmp(buf, "yes", 3) != 0) { - ret = -1; - goto fail; - } - ERROR("%s", "This new key will be written on disk for further usage. " - "do you agree ?"); - if (!fgets(buf, sizeof(buf), stdin)) { - ret = -1; - goto fail; - } - if (strncasecmp(buf, "yes", 3) == 0) { - if (ssh_write_knownhost(blksession) < 0) { - ERROR("%s", strerror(errno)); - ret = -1; - goto fail; - } - } - break; - - case SSH_SERVER_ERROR: - ERROR("%s", ssh_get_error(blksession)); - ret = -1; - goto fail; - } - - ret = 0; - - fail: - ssh_clean_pubkey_hash(&hash); - - return ret; -} - - -static ssh_session -glusterBlockSSHConnect(const char *host, const char *user, int verbosity) -{ - int auth = 0; - ssh_session blksession; - - blksession = ssh_new(); - if (!blksession) - return NULL; - - if (user) { - if (ssh_options_set(blksession, SSH_OPTIONS_USER, user) < 0) - goto sfree; - } - - if (ssh_options_set(blksession, SSH_OPTIONS_HOST, host) < 0) - goto sfree; - - ssh_options_set(blksession, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); - if (ssh_connect(blksession)) { - ERROR("Connection failed : %s", ssh_get_error(blksession)); - goto sdnt; - } - - if (glusterBlockSSHVerifyKnownHost(blksession)<0) - goto sdnt; - - auth = glusterBlockSSHAuthConsole(blksession); - if (auth == SSH_AUTH_SUCCESS) { - return blksession; - } else if (auth == SSH_AUTH_DENIED) { - ERROR("%s", "Authentication failed"); - } else { - ERROR("while authenticating : %s", ssh_get_error(blksession)); - } - - sdnt: - ssh_disconnect(blksession); - - sfree: - ssh_free(blksession); - - return NULL; -} - - -char * -glusterBlockSSHRun(char *host, char *cmd, bool console) -{ - FILE *fd = NULL; - int ret; - int nbytes; - int rc; - uuid_t out; - char uuid[256]; - char *file; - char buffer[256]; - ssh_session blksession; - ssh_channel blkchannel; - - blksession = glusterBlockSSHConnect(host, NULL/*user*/, 0); - if (!blksession) { - ssh_finalize(); - return NULL; - } - - blkchannel = ssh_channel_new(blksession); - if (!blkchannel) { - ret = 1; - goto chfail; - } - - rc = ssh_channel_open_session(blkchannel); - if (rc < 0) { - ret = 1; - goto fail; - } - - rc = ssh_channel_request_exec(blkchannel, cmd); - if (rc < 0) { - ret = 1; - goto fail; - } - - if (!console) { - uuid_generate(out); - uuid_unparse(out, uuid); - asprintf(&file, "/tmp/%s", uuid); - fd = fopen(file, "w"); - } - - nbytes = ssh_channel_read(blkchannel, buffer, sizeof(buffer), 0); - while (nbytes > 0) { - if (fwrite(buffer, 1, nbytes, fd ? fd : stdout) != (unsigned int) nbytes) { - ret = 1; - goto fail; - } - nbytes = ssh_channel_read(blkchannel, buffer, sizeof(buffer), 0); - } - - if (nbytes < 0) { - ret = 1; - goto fail; - } - - ssh_channel_send_eof(blkchannel); - ret = 0; - - if (console && ret == 0) - file = "stdout"; /* just to differentiate b/w success and failure */ - - fail: - if (!console) - fclose(fd); - - ssh_channel_close(blkchannel); - ssh_channel_free(blkchannel); - - chfail: - ssh_disconnect(blksession); - ssh_free(blksession); - ssh_finalize(); - - return (!ret) ? file : NULL; -} |