int verify_knownhost(ssh_session session){ char *hexa; int state; unsigned char *hash = NULL; int hlen; state=ssh_is_server_known(session); hlen = ssh_get_pubkey_hash(session, &hash); if (hlen < 0) { return -1; } switch(state){ case SSH_SERVER_KNOWN_OK: break; /* ok */ case SSH_SERVER_KNOWN_CHANGED: fprintf(stderr,"Host key for server changed : server's one is now :\n"); ssh_print_hexa("Public key hash",hash, hlen); ssh_clean_pubkey_hash(&hash); fprintf(stderr,"For security reason, connection will be stopped\n"); return -1; case SSH_SERVER_FOUND_OTHER: fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n"); fprintf(stderr,"An attacker might change the default server key to confuse your client" "into thinking the key does not exist\n" "We advise you to rerun the client with -d or -r for more safety.\n"); return -1; case SSH_SERVER_FILE_NOT_FOUND: fprintf(stderr,"Could not find known host file. If you accept the host key here,\n"); fprintf(stderr,"the file will be automatically created.\n"); /* fallback to SSH_SERVER_NOT_KNOWN behavior */ case SSH_SERVER_NOT_KNOWN: hexa = ssh_get_hexa(hash, hlen); if (ssh_write_knownhost(session) < 0) { ssh_clean_pubkey_hash(&hash); fprintf(stderr, "error %s\n", strerror(errno)); return -1; } break; case SSH_SERVER_ERROR: ssh_clean_pubkey_hash(&hash); fprintf(stderr,"%s",ssh_get_error(session)); return -1; } ssh_clean_pubkey_hash(&hash); return 0; }
static const gchar * verify_knownhost (CockpitSshData *data) { const gchar *ret = "unknown-hostkey"; ssh_key key = NULL; unsigned char *hash = NULL; const char *type = NULL; int state; gsize len; data->host_key = get_knownhosts_line (data->session); if (data->host_key == NULL) { ret = "internal-error"; goto done; } if (ssh_get_publickey (data->session, &key) != SSH_OK) { g_warning ("Couldn't look up ssh host key"); ret = "internal-error"; goto done; } type = ssh_key_type_to_char (ssh_key_type (key)); if (type == NULL) { g_warning ("Couldn't lookup host key type"); ret = "internal-error"; goto done; } if (ssh_get_publickey_hash (key, SSH_PUBLICKEY_HASH_MD5, &hash, &len) < 0) { g_warning ("Couldn't hash ssh public key"); ret = "internal-error"; goto done; } else { data->host_fingerprint = ssh_get_hexa (hash, len); ssh_clean_pubkey_hash (&hash); } if (data->expect_key) { /* Only check that the host key matches this specifically */ if (g_str_equal (data->host_key, data->expect_key)) { g_debug ("%s: host key matched expected", data->logname); ret = NULL; /* success */ } else { /* A empty expect_key is used by the frontend to force failure. Don't warn about it. */ if (data->expect_key[0]) g_message ("%s: host key did not match expected", data->logname); } } else { if (ssh_options_set (data->session, SSH_OPTIONS_KNOWNHOSTS, data->knownhosts_file) != SSH_OK) { g_warning ("Couldn't set knownhosts file location"); ret = "internal-error"; goto done; } state = ssh_is_server_known (data->session); if (state == SSH_SERVER_KNOWN_OK) { g_debug ("%s: verified host key", data->logname); ret = NULL; /* success */ goto done; } else if (state == SSH_SERVER_ERROR) { if (g_atomic_int_get (data->connecting)) g_warning ("%s: couldn't check host key: %s", data->logname, ssh_get_error (data->session)); ret = "internal-error"; goto done; } switch (state) { case SSH_SERVER_KNOWN_OK: case SSH_SERVER_ERROR: g_assert_not_reached (); break; case SSH_SERVER_KNOWN_CHANGED: g_message ("%s: %s host key for server has changed to: %s", data->logname, type, data->host_fingerprint); break; case SSH_SERVER_FOUND_OTHER: g_message ("%s: host key for this server changed key type: %s", data->logname, type); break; case SSH_SERVER_FILE_NOT_FOUND: g_debug ("Couldn't find the known hosts file"); /* fall through */ case SSH_SERVER_NOT_KNOWN: g_message ("%s: %s host key for server is not known: %s", data->logname, type, data->host_fingerprint); break; } } done: if (key) ssh_key_free (key); return ret; }
gint remmina_ssh_auth_gui (RemminaSSH *ssh, RemminaInitDialog *dialog, gboolean threaded) { gchar *tips; gchar *keyname; gint ret; size_t len; guchar *pubkey; ssh_key server_pubkey; /* Check if the server's public key is known */ ret = ssh_is_server_known (ssh->session); switch (ret) { case SSH_SERVER_KNOWN_OK: break; case SSH_SERVER_NOT_KNOWN: case SSH_SERVER_FILE_NOT_FOUND: case SSH_SERVER_KNOWN_CHANGED: case SSH_SERVER_FOUND_OTHER: if ( ssh_get_publickey(ssh->session, &server_pubkey) != SSH_OK ) { remmina_ssh_set_error(ssh, "ssh_get_publickey() has failed: %s"); return 0; } if ( ssh_get_publickey_hash(server_pubkey, SSH_PUBLICKEY_HASH_MD5, &pubkey, &len) != 0 ) { ssh_key_free(server_pubkey); remmina_ssh_set_error(ssh, "ssh_get_publickey_hash() has failed: %s"); return 0; } ssh_key_free(server_pubkey); keyname = ssh_get_hexa (pubkey, len); if (threaded) gdk_threads_enter(); if (ret == SSH_SERVER_NOT_KNOWN || ret == SSH_SERVER_FILE_NOT_FOUND) { ret = remmina_init_dialog_serverkey_unknown (dialog, keyname); } else { ret = remmina_init_dialog_serverkey_changed (dialog, keyname); } if (threaded) { gdk_flush();gdk_threads_leave();} ssh_string_free_char(keyname); ssh_clean_pubkey_hash (&pubkey); if (ret != GTK_RESPONSE_OK) return -1; ssh_write_knownhost (ssh->session); break; case SSH_SERVER_ERROR: default: remmina_ssh_set_error (ssh, "SSH known host checking failed: %s"); return 0; } /* Try empty password or existing password first */ ret = remmina_ssh_auth (ssh, NULL); if (ret > 0) return 1; /* Requested for a non-empty password */ if (ret < 0) { if (!dialog) return -1; switch (ssh->auth) { case SSH_AUTH_PASSWORD: tips = _("Authenticating %s's password to SSH server %s..."); keyname = _("SSH password"); break; case SSH_AUTH_PUBLICKEY: tips = _("Authenticating %s's identity to SSH server %s..."); keyname = _("SSH private key passphrase"); break; default: return FALSE; } if (ssh->auth != SSH_AUTH_AUTO_PUBLICKEY) { if (threaded) gdk_threads_enter(); remmina_init_dialog_set_status (dialog, tips, ssh->user, ssh->server); ret = remmina_init_dialog_authpwd (dialog, keyname, FALSE); if (threaded) { gdk_flush();gdk_threads_leave();} if (ret != GTK_RESPONSE_OK) return -1; } ret = remmina_ssh_auth (ssh, dialog->password); } if (ret <= 0) { return 0; } return 1; }
int verify_knownhost(ssh_session session) { char *hexa; int state; char buf[10]; unsigned char *hash = NULL; size_t hlen; ssh_key srv_pubkey; int rc; state=ssh_is_server_known(session); rc = ssh_get_server_publickey(session, &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(state) { case SSH_SERVER_KNOWN_OK: /* Server found */ break; case SSH_SERVER_KNOWN_CHANGED: fprintf(stderr,"Host key for server changed : server's one is now :\n"); ssh_print_hexa("Public key hash",hash, hlen); ssh_clean_pubkey_hash(&hash); fprintf(stderr,"For security reason, connection will be stopped\n"); return -1; case SSH_SERVER_FOUND_OTHER: fprintf(stderr,"The host key for this server was not found but an other type of key exists.\n"); fprintf(stderr,"An attacker might change the default server key to confuse your client" "into thinking the key does not exist\n" "We advise you to rerun the client with -d or -r for more safety.\n"); return -1; case SSH_SERVER_FILE_NOT_FOUND: fprintf(stderr,"Could not find known host file. If you accept the host key here,\n"); fprintf(stderr,"the file will be automatically created.\n"); /* fallback to SSH_SERVER_NOT_KNOWN behavior */ case SSH_SERVER_NOT_KNOWN: hexa = ssh_get_hexa(hash, hlen); fprintf(stderr,"The server is unknown. Do you trust the host key ?\n"); fprintf(stderr, "Public key hash: %s\n", hexa); ssh_string_free_char(hexa); if (fgets(buf, sizeof(buf), stdin) == NULL) { ssh_clean_pubkey_hash(&hash); return -1; } if(strncasecmp(buf,"yes",3)!=0) { ssh_clean_pubkey_hash(&hash); return -1; } fprintf(stderr,"This new key will be written on disk for further usage. do you agree ?\n"); if (fgets(buf, sizeof(buf), stdin) == NULL) { ssh_clean_pubkey_hash(&hash); return -1; } if(strncasecmp(buf,"yes",3)==0) { if (ssh_write_knownhost(session) < 0) { ssh_clean_pubkey_hash(&hash); fprintf(stderr, "error %s\n", strerror(errno)); return -1; } } break; case SSH_SERVER_ERROR: ssh_clean_pubkey_hash(&hash); fprintf(stderr,"%s",ssh_get_error(session)); return -1; } ssh_clean_pubkey_hash(&hash); return 0; } /* int verify_knownhost */