static ssh_session create_ssh_connection(const char* hostname, const unsigned int port, const char* username, const char* password, const char* sshkey_path, const char* sshkey_passphrase) { ssh_session sshs; /* Open session and set options */ sshs = ssh_new(); if (sshs == NULL) { errmsg_print("Can't create ssh session"); return NULL; } if (!hostname) return NULL; if (ssh_options_set(sshs, SSH_OPTIONS_HOST, hostname)) { errmsg_print("Can't set the hostname: %s\n", hostname); goto failure; } if (port != 0) { if (ssh_options_set(sshs, SSH_OPTIONS_PORT, &port)) { errmsg_print("Can't set the port: %d\n", port); goto failure; } } if (!username) username = g_get_user_name(); if (ssh_options_set(sshs, SSH_OPTIONS_USER, username)) { errmsg_print("Can't set the username: %s\n", username); goto failure; } verbose_print("Opening ssh connection to %s@%s:%u\n", username, hostname, port); /* Connect to server */ if (ssh_connect(sshs) != SSH_OK) { errmsg_print("Error connecting to %s@%s:%u (%s)\n", username, hostname, port, ssh_get_error(sshs)); goto failure; } #ifdef HAVE_LIBSSH_USERAUTH_AGENT verbose_print("Connecting using ssh-agent..."); /* Try to authenticate using ssh agent */ if (ssh_userauth_agent(sshs, NULL) == SSH_AUTH_SUCCESS) { verbose_print("done\n"); return sshs; } verbose_print("failed\n"); #endif /* If a public key path has been provided, try to authenticate using it */ if (sshkey_path) { ssh_key pkey = ssh_key_new(); int ret; verbose_print("Connecting using public key in %s...", sshkey_path); ret = ssh_pki_import_privkey_file(sshkey_path, sshkey_passphrase, NULL, NULL, &pkey); if (ret == SSH_OK) { if (ssh_userauth_publickey(sshs, NULL, pkey) == SSH_AUTH_SUCCESS) { verbose_print("done\n"); ssh_key_free(pkey); return sshs; } } ssh_key_free(pkey); verbose_print("failed (%s)\n", ssh_get_error(sshs)); } /* Try to authenticate using standard public key */ verbose_print("Connecting using standard public key..."); if (ssh_userauth_publickey_auto(sshs, NULL, NULL) == SSH_AUTH_SUCCESS) { verbose_print("done\n"); return sshs; } verbose_print("failed\n"); /* If a password has been provided and all previous attempts failed, try to use it */ if (password) { verbose_print("Connecting using password..."); if (ssh_userauth_password(sshs, username, password) == SSH_AUTH_SUCCESS) { verbose_print("done\n"); return sshs; } verbose_print("failed\n"); } errmsg_print("Can't find a valid authentication. Disconnecting.\n"); /* All authentication failed. Disconnect and return */ ssh_disconnect(sshs); failure: ssh_free(sshs); return NULL; }
static void torture_pki_write_privkey_dsa(void **state) { ssh_key origkey; ssh_key privkey; int rc; (void) state; /* unused */ ssh_set_log_level(5); rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY, NULL, NULL, NULL, &origkey); assert_true(rc == 0); unlink(LIBSSH_DSA_TESTKEY); rc = ssh_pki_export_privkey_file(origkey, "", NULL, NULL, LIBSSH_DSA_TESTKEY); assert_true(rc == 0); rc = ssh_pki_import_privkey_file(LIBSSH_DSA_TESTKEY, NULL, NULL, NULL, &privkey); assert_true(rc == 0); rc = ssh_key_cmp(origkey, privkey, SSH_KEY_CMP_PRIVATE); assert_true(rc == 0); ssh_key_free(origkey); ssh_key_free(privkey); }
void ssh_bind_free(ssh_bind sshbind){ int i; if (sshbind == NULL) { return; } if (sshbind->bindfd >= 0) { CLOSE_SOCKET(sshbind->bindfd); } sshbind->bindfd = SSH_INVALID_SOCKET; /* options */ SAFE_FREE(sshbind->banner); SAFE_FREE(sshbind->bindaddr); SAFE_FREE(sshbind->dsakey); SAFE_FREE(sshbind->rsakey); SAFE_FREE(sshbind->ecdsakey); SAFE_FREE(sshbind->ed25519key); ssh_key_free(sshbind->dsa); sshbind->dsa = NULL; ssh_key_free(sshbind->rsa); sshbind->rsa = NULL; ssh_key_free(sshbind->ecdsa); sshbind->ecdsa = NULL; ssh_key_free(sshbind->ed25519); sshbind->ed25519 = NULL; for (i = 0; i < 10; i++) { if (sshbind->wanted_methods[i]) { SAFE_FREE(sshbind->wanted_methods[i]); } } SAFE_FREE(sshbind); }
/* Free the smob. */ size_t free_key_smob (SCM arg1) { struct key_data *data = _scm_to_key_data (arg1); if (scm_is_false (data->parent)) { /* It's safe to free the key only if it was not derived from some other object and thereby does not share any resources with it. If the key does have a parent then all the resources will be freed along with it. */ ssh_key_free (data->ssh_key); } return 0; }
int ssh_get_key_params(ssh_session session, ssh_key *privkey){ ssh_key pubkey; ssh_string pubkey_blob; int rc; switch(session->srv.hostkey) { case SSH_KEYTYPE_DSS: *privkey = session->srv.dsa_key; break; case SSH_KEYTYPE_RSA: *privkey = session->srv.rsa_key; break; case SSH_KEYTYPE_ECDSA: *privkey = session->srv.ecdsa_key; break; case SSH_KEYTYPE_ED25519: *privkey = session->srv.ed25519_key; break; case SSH_KEYTYPE_RSA1: case SSH_KEYTYPE_UNKNOWN: default: *privkey = NULL; } rc = ssh_pki_export_privkey_to_pubkey(*privkey, &pubkey); if (rc < 0) { ssh_set_error(session, SSH_FATAL, "Could not get the public key from the private key"); return -1; } rc = ssh_pki_export_pubkey_blob(pubkey, &pubkey_blob); ssh_key_free(pubkey); if (rc < 0) { ssh_set_error_oom(session); return -1; } rc = ssh_dh_import_next_pubkey_blob(session, pubkey_blob); ssh_string_free(pubkey_blob); if (rc != 0) { ssh_set_error(session, SSH_FATAL, "Could not import server public key"); return -1; } return SSH_OK; }
ssh_private_key ssh_pki_convert_key_to_privatekey(const ssh_key key) { ssh_private_key privkey; privkey = malloc(sizeof(struct ssh_private_key_struct)); if (privkey == NULL) { ssh_key_free(key); return NULL; } privkey->type = key->type; privkey->dsa_priv = key->dsa; privkey->rsa_priv = key->rsa; return privkey; }
int ssh_guac_client_free_handler(guac_client* client) { ssh_guac_client_data* guac_client_data = (ssh_guac_client_data*) client->data; /* Close SSH channel */ if (guac_client_data->term_channel != NULL) { libssh2_channel_send_eof(guac_client_data->term_channel); libssh2_channel_close(guac_client_data->term_channel); } /* Free terminal */ guac_terminal_free(guac_client_data->term); pthread_join(guac_client_data->client_thread, NULL); /* Free channels */ libssh2_channel_free(guac_client_data->term_channel); /* Clean up SFTP */ if (guac_client_data->sftp_session) libssh2_sftp_shutdown(guac_client_data->sftp_session); if (guac_client_data->sftp_ssh_session) { libssh2_session_disconnect(guac_client_data->sftp_ssh_session, "Bye"); libssh2_session_free(guac_client_data->sftp_ssh_session); } /* Free session */ if (guac_client_data->session != NULL) libssh2_session_free(guac_client_data->session); /* Free auth key */ if (guac_client_data->key != NULL) ssh_key_free(guac_client_data->key); /* Free clipboard */ guac_common_clipboard_free(guac_client_data->clipboard); /* Free cursors */ guac_ssh_cursor_free(client, guac_client_data->ibar_cursor); guac_ssh_cursor_free(client, guac_client_data->blank_cursor); /* Free generic data struct */ free(client->data); return 0; }
static void torture_pki_import_privkey_base64_ECDSA(void **state) { int rc; char *key_str; ssh_key key; const char *passphrase = LIBSSH_PASSPHRASE; (void) state; /* unused */ key_str = read_file(LIBSSH_ECDSA_TESTKEY); assert_true(key_str != NULL); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); free(key_str); ssh_key_free(key); }
static int auth_publickey(ssh_session session, const char *user, struct ssh_key_struct *pubkey, char signature_state, void *userdata) { struct session_data_struct *sdata = (struct session_data_struct *) userdata; (void) user; (void) session; if (signature_state == SSH_PUBLICKEY_STATE_NONE) { return SSH_AUTH_SUCCESS; } if (signature_state != SSH_PUBLICKEY_STATE_VALID) { return SSH_AUTH_DENIED; } // valid so far. Now look through authorized keys for a match if (authorizedkeys[0]) { ssh_key key = NULL; int result; struct stat buf; if (stat(authorizedkeys, &buf) == 0) { result = ssh_pki_import_pubkey_file( authorizedkeys, &key ); if ((result != SSH_OK) || (key==NULL)) { fprintf(stderr, "Unable to import public key file %s\n", authorizedkeys); } else { result = ssh_key_cmp( key, pubkey, SSH_KEY_CMP_PUBLIC ); ssh_key_free(key); if (result == 0) { sdata->authenticated = 1; return SSH_AUTH_SUCCESS; } } } } // no matches sdata->authenticated = 0; return SSH_AUTH_DENIED; }
static void torture_pki_import_privkey_base64_NULL_str(void **state) { int rc; char *key_str; ssh_key key = NULL; const char *passphrase = LIBSSH_PASSPHRASE; (void) state; /* unused */ key_str = read_file(LIBSSH_RSA_TESTKEY); assert_true(key_str != NULL); /* test if it returns -1 if key_str is NULL */ rc = ssh_pki_import_privkey_base64(NULL, passphrase, NULL, NULL, &key); assert_true(rc == -1); free(key_str); ssh_key_free(key); }
/** * @brief Generates a keypair. * * @param[in] type Type of key to create * * @param[in] parameter Parameter to the creation of key: * rsa : length of the key in bits (e.g. 1024, 2048, 4096) * dsa : length of the key in bits (e.g. 1024, 2048, 3072) * ecdsa : bits of the key (e.g. 256, 384, 512) * @param[out] pkey A pointer to store the allocated private key. You need * to free the memory. * * @return SSH_OK on success, SSH_ERROR on error. * * @warning Generating a key pair may take some time. */ int ssh_pki_generate(enum ssh_keytypes_e type, int parameter, ssh_key *pkey){ int rc; ssh_key key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; switch(type){ case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: rc = pki_key_generate_rsa(key, parameter); if(rc == SSH_ERROR) goto error; break; case SSH_KEYTYPE_DSS: rc = pki_key_generate_dss(key, parameter); if(rc == SSH_ERROR) goto error; break; case SSH_KEYTYPE_ECDSA: #ifdef HAVE_ECC rc = pki_key_generate_ecdsa(key, parameter); if(rc == SSH_ERROR) goto error; break; #endif case SSH_KEYTYPE_UNKNOWN: goto error; } *pkey = key; return SSH_OK; error: ssh_key_free(key); return SSH_ERROR; }
/** * @brief Free a SSH message. * * @param[in] msg The message to release the memory. */ void ssh_message_free(ssh_message msg){ if (msg == NULL) { return; } switch(msg->type) { case SSH_REQUEST_AUTH: SAFE_FREE(msg->auth_request.username); if (msg->auth_request.password) { memset(msg->auth_request.password, 0, strlen(msg->auth_request.password)); SAFE_FREE(msg->auth_request.password); } ssh_key_free(msg->auth_request.pubkey); break; case SSH_REQUEST_CHANNEL_OPEN: SAFE_FREE(msg->channel_request_open.originator); SAFE_FREE(msg->channel_request_open.destination); break; case SSH_REQUEST_CHANNEL: SAFE_FREE(msg->channel_request.TERM); SAFE_FREE(msg->channel_request.modes); SAFE_FREE(msg->channel_request.var_name); SAFE_FREE(msg->channel_request.var_value); SAFE_FREE(msg->channel_request.command); SAFE_FREE(msg->channel_request.subsystem); break; case SSH_REQUEST_SERVICE: SAFE_FREE(msg->service_request.service); break; case SSH_REQUEST_GLOBAL: SAFE_FREE(msg->global_request.bind_address); break; } ZERO_STRUCTP(msg); SAFE_FREE(msg); }
static void torture_pki_publickey_rsa_base64(void **state) { enum ssh_keytypes_e type; char *b64_key, *key_buf, *p; const char *q; ssh_key key; int rc; (void) state; /* unused */ key_buf = read_file(LIBSSH_RSA_TESTKEY ".pub"); assert_true(key_buf != NULL); q = p = key_buf; while (*p != ' ') p++; *p = '\0'; type = ssh_key_type_from_name(q); assert_true(((type == SSH_KEYTYPE_RSA) || (type == SSH_KEYTYPE_RSA1))); q = ++p; while (*p != ' ') p++; *p = '\0'; rc = ssh_pki_import_pubkey_base64(q, type, &key); assert_true(rc == 0); rc = ssh_pki_export_pubkey_base64(key, &b64_key); assert_true(rc == 0); assert_string_equal(q, b64_key); free(b64_key); free(key_buf); ssh_key_free(key); }
static gint remmina_ssh_auth_pubkey (RemminaSSH *ssh) { gint ret; ssh_key priv_key; if (ssh->authenticated) return 1; if (ssh->privkeyfile == NULL) { ssh->error = g_strdup_printf(_("SSH public key authentication failed: %s"), _("SSH Key file not yet set.")); return 0; } if ( ssh_pki_import_privkey_file( ssh->privkeyfile, (ssh->password ? ssh->password : ""), NULL, NULL, &priv_key ) != SSH_OK ) { if (ssh->password == NULL || ssh->password[0] == '\0') return -1; remmina_ssh_set_error (ssh, _("SSH public key authentication failed: %s")); return 0; } ret = ssh_userauth_publickey (ssh->session, NULL, priv_key); ssh_key_free(priv_key); if (ret != SSH_AUTH_SUCCESS) { remmina_ssh_set_error (ssh, _("SSH public key authentication failed: %s")); return 0; } ssh->authenticated = TRUE; return 1; }
static void torture_pki_import_privkey_base64_RSA(void **state) { int rc; char *key_str; ssh_key key; const char *passphrase = LIBSSH_PASSPHRASE; enum ssh_keytypes_e type; (void) state; /* unused */ key_str = read_file(LIBSSH_RSA_TESTKEY); assert_true(key_str != NULL); rc = ssh_pki_import_privkey_base64(key_str, passphrase, NULL, NULL, &key); assert_true(rc == 0); type = ssh_key_type(key); assert_true(type == SSH_KEYTYPE_RSA); rc = ssh_key_is_public(key); assert_true(rc == 1); free(key_str); ssh_key_free(key); }
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 */
static int ssh_bind_import_keys(ssh_bind sshbind) { int rc; if (sshbind->ecdsakey == NULL && sshbind->dsakey == NULL && sshbind->rsakey == NULL) { ssh_set_error(sshbind, SSH_FATAL, "ECDSA, DSA, or RSA host key file must be set"); return SSH_ERROR; } #ifdef HAVE_ECC if (sshbind->ecdsa == NULL && sshbind->ecdsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->ecdsakey, NULL, NULL, NULL, &sshbind->ecdsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private ECDSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->ecdsa) != SSH_KEYTYPE_ECDSA) { ssh_set_error(sshbind, SSH_FATAL, "The ECDSA host key has the wrong type"); ssh_key_free(sshbind->ecdsa); sshbind->ecdsa = NULL; return SSH_ERROR; } } #endif if (sshbind->dsa == NULL && sshbind->dsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->dsakey, NULL, NULL, NULL, &sshbind->dsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private DSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->dsa) != SSH_KEYTYPE_DSS) { ssh_set_error(sshbind, SSH_FATAL, "The DSA host key has the wrong type: %d", ssh_key_type(sshbind->dsa)); ssh_key_free(sshbind->dsa); sshbind->dsa = NULL; return SSH_ERROR; } } if (sshbind->rsa == NULL && sshbind->rsakey != NULL) { rc = ssh_pki_import_privkey_file(sshbind->rsakey, NULL, NULL, NULL, &sshbind->rsa); if (rc == SSH_ERROR || rc == SSH_EOF) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private RSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA && ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA1) { ssh_set_error(sshbind, SSH_FATAL, "The RSA host key has the wrong type"); ssh_key_free(sshbind->rsa); sshbind->rsa = NULL; return SSH_ERROR; } } return SSH_OK; }
ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { ssh_key key = NULL; mbedtls_pk_context *rsa = NULL; mbedtls_pk_context *ecdsa = NULL; ed25519_privkey *ed25519 = NULL; enum ssh_keytypes_e type; int valid; /* mbedtls pk_parse_key expects strlen to count the 0 byte */ size_t b64len = strlen(b64_key) + 1; unsigned char tmp[MAX_PASSPHRASE_SIZE] = {0}; type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); return NULL; } switch (type) { case SSH_KEYTYPE_RSA: rsa = malloc(sizeof(mbedtls_pk_context)); if (rsa == NULL) { return NULL; } mbedtls_pk_init(rsa); if (passphrase == NULL) { if (auth_fn) { valid = auth_fn("Passphrase for private key:", (char *) tmp, MAX_PASSPHRASE_SIZE, 0, 0, auth_data); if (valid < 0) { return NULL; } /* TODO fix signedness and strlen */ valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); } else { valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, NULL, 0); } } else { valid = mbedtls_pk_parse_key(rsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); } if (valid != 0) { char error_buf[100]; mbedtls_strerror(valid, error_buf, 100); SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); goto fail; } break; case SSH_KEYTYPE_ECDSA: ecdsa = malloc(sizeof(mbedtls_pk_context)); if (ecdsa == NULL) { return NULL; } mbedtls_pk_init(ecdsa); if (passphrase == NULL) { if (auth_fn) { valid = auth_fn("Passphrase for private key:", (char *) tmp, MAX_PASSPHRASE_SIZE, 0, 0, auth_data); if (valid < 0) { return NULL; } valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, tmp, strnlen((const char *) tmp, MAX_PASSPHRASE_SIZE)); } else { valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, NULL, 0); } } else { valid = mbedtls_pk_parse_key(ecdsa, (const unsigned char *) b64_key, b64len, (const unsigned char *) passphrase, strnlen(passphrase, MAX_PASSPHRASE_SIZE)); } if (valid != 0) { char error_buf[100]; mbedtls_strerror(valid, error_buf, 100); SSH_LOG(SSH_LOG_WARN,"Parsing private key %s", error_buf); goto fail; } break; case SSH_KEYTYPE_ED25519: /* Cannot open ed25519 keys with libmbedcrypto */ default: SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->rsa = rsa; if (ecdsa != NULL) { mbedtls_ecp_keypair *keypair = mbedtls_pk_ec(*ecdsa); key->ecdsa = malloc(sizeof(mbedtls_ecdsa_context)); if (key->ecdsa == NULL) { goto fail; } mbedtls_ecdsa_init(key->ecdsa); mbedtls_ecdsa_from_keypair(key->ecdsa, keypair); mbedtls_pk_free(ecdsa); SAFE_FREE(ecdsa); } else { key->ecdsa = NULL; } key->ed25519_privkey = ed25519; rsa = NULL; ecdsa = NULL; if (key->type == SSH_KEYTYPE_ECDSA) { key->ecdsa_nid = pki_key_ecdsa_to_nid(key->ecdsa); key->type_c = pki_key_ecdsa_nid_to_name(key->ecdsa_nid); } return key; fail: ssh_key_free(key); if (rsa != NULL) { mbedtls_pk_free(rsa); SAFE_FREE(rsa); } if (ecdsa != NULL) { mbedtls_pk_free(ecdsa); SAFE_FREE(ecdsa); } return NULL; }
static int pki_import_pubkey_buffer(ssh_buffer buffer, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; switch (type) { case SSH_KEYTYPE_DSS: { ssh_string p; ssh_string q; ssh_string g; ssh_string pubkey; p = ssh_buffer_get_ssh_string(buffer); if (p == NULL) { goto fail; } q = ssh_buffer_get_ssh_string(buffer); if (q == NULL) { ssh_string_burn(p); ssh_string_free(p); goto fail; } g = ssh_buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); goto fail; } pubkey = ssh_buffer_get_ssh_string(buffer); if (pubkey == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); goto fail; } rc = pki_pubkey_build_dss(key, p, q, g, pubkey); #ifdef DEBUG_CRYPTO ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p)); ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q)); ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g)); #endif ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); ssh_string_burn(pubkey); ssh_string_free(pubkey); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { ssh_string e; ssh_string n; e = ssh_buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } n = ssh_buffer_get_ssh_string(buffer); if (n == NULL) { ssh_string_burn(e); ssh_string_free(e); goto fail; } rc = pki_pubkey_build_rsa(key, e, n); #ifdef DEBUG_CRYPTO ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e)); ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n)); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_ECDSA: #ifdef HAVE_ECC { ssh_string e; ssh_string i; int nid; i = ssh_buffer_get_ssh_string(buffer); if (i == NULL) { goto fail; } nid = pki_key_ecdsa_nid_from_name(ssh_string_get_char(i)); ssh_string_free(i); if (nid == -1) { goto fail; } e = ssh_buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } rc = pki_pubkey_build_ecdsa(key, nid, e); ssh_string_burn(e); ssh_string_free(e); if (rc < 0) { goto fail; } /* Update key type */ key->type_c = ssh_pki_key_ecdsa_name(key); } break; #endif case SSH_KEYTYPE_ED25519: { ssh_string pubkey = ssh_buffer_get_ssh_string(buffer); if (ssh_string_len(pubkey) != ED25519_PK_LEN) { SSH_LOG(SSH_LOG_WARN, "Invalid public key length"); ssh_string_burn(pubkey); ssh_string_free(pubkey); goto fail; } key->ed25519_pubkey = malloc(ED25519_PK_LEN); if (key->ed25519_pubkey == NULL) { ssh_string_burn(pubkey); ssh_string_free(pubkey); goto fail; } memcpy(key->ed25519_pubkey, ssh_string_data(pubkey), ED25519_PK_LEN); ssh_string_burn(pubkey); ssh_string_free(pubkey); } break; case SSH_KEYTYPE_DSS_CERT01: case SSH_KEYTYPE_RSA_CERT01: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unknown public key protocol %d", type); goto fail; } *pkey = key; return SSH_OK; fail: ssh_key_free(key); return SSH_ERROR; }
int ssh_pki_import_pubkey_base64(ssh_session session, const char *b64_key, enum ssh_keytypes_e type, ssh_key *pkey) { ssh_buffer buffer; ssh_key key; int rc; key = ssh_key_new(); if (key == NULL) { return SSH_ERROR; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PUBLIC; buffer = base64_to_bin(b64_key); switch (type) { case SSH_KEYTYPE_DSS: { ssh_string p; ssh_string q; ssh_string g; ssh_string pubkey; p = buffer_get_ssh_string(buffer); if (p == NULL) { goto fail; } q = buffer_get_ssh_string(buffer); if (q == NULL) { ssh_string_burn(p); ssh_string_free(p); goto fail; } g = buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); goto fail; } pubkey = buffer_get_ssh_string(buffer); if (g == NULL) { ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); goto fail; } rc = pki_pubkey_build_dss(key, p, q, g, pubkey); #ifdef DEBUG_CRYPTO ssh_print_hexa("p", ssh_string_data(p), ssh_string_len(p)); ssh_print_hexa("q", ssh_string_data(q), ssh_string_len(q)); ssh_print_hexa("g", ssh_string_data(g), ssh_string_len(g)); #endif ssh_string_burn(p); ssh_string_free(p); ssh_string_burn(q); ssh_string_free(q); ssh_string_burn(g); ssh_string_free(g); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: { ssh_string e; ssh_string n; e = buffer_get_ssh_string(buffer); if (e == NULL) { goto fail; } n = buffer_get_ssh_string(buffer); if (n == NULL) { ssh_string_burn(e); ssh_string_free(e); goto fail; } rc = pki_pubkey_build_rsa(key, e, n); #ifdef DEBUG_CRYPTO ssh_print_hexa("e", ssh_string_data(e), ssh_string_len(e)); ssh_print_hexa("n", ssh_string_data(n), ssh_string_len(n)); #endif ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); if (rc == SSH_ERROR) { goto fail; } } break; case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: ssh_set_error(session, SSH_FATAL, "Unknown public key protocol %d", type); goto fail; } ssh_buffer_free(buffer); *pkey = key; return SSH_OK; fail: ssh_buffer_free(buffer); ssh_key_free(key); return SSH_ERROR; }
ssh_key pki_private_key_from_base64(const char *b64_key, const char *passphrase, ssh_auth_callback auth_fn, void *auth_data) { gcry_sexp_t dsa = NULL; gcry_sexp_t rsa = NULL; ssh_key key = NULL; enum ssh_keytypes_e type; int valid; /* needed for gcrypt initialization */ if (ssh_init() < 0) { return NULL; } type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { SSH_LOG(SSH_LOG_WARN, "Unknown or invalid private key."); return NULL; } switch (type) { case SSH_KEYTYPE_DSS: if (passphrase == NULL) { if (auth_fn) { valid = b64decode_dsa_privatekey(b64_key, &dsa, auth_fn, auth_data, "Passphrase for private key:"); } else { valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, NULL, NULL); } } else { valid = b64decode_dsa_privatekey(b64_key, &dsa, NULL, (void *) passphrase, NULL); } if (!valid) { SSH_LOG(SSH_LOG_WARN, "Parsing private key"); goto fail; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: if (passphrase == NULL) { if (auth_fn) { valid = b64decode_rsa_privatekey(b64_key, &rsa, auth_fn, auth_data, "Passphrase for private key:"); } else { valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, NULL, NULL); } } else { valid = b64decode_rsa_privatekey(b64_key, &rsa, NULL, (void *)passphrase, NULL); } if (!valid) { SSH_LOG(SSH_LOG_WARN, "Parsing private key"); goto fail; } break; case SSH_KEYTYPE_ED25519: /* Cannot open ed25519 keys with libgcrypt */ case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: default: SSH_LOG(SSH_LOG_WARN, "Unkown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->dsa = dsa; key->rsa = rsa; return key; fail: ssh_key_free(key); gcry_sexp_release(dsa); gcry_sexp_release(rsa); return NULL; }
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; }
void crypto_free(struct ssh_crypto_struct *crypto){ int i; if (crypto == NULL) { return; } ssh_key_free(crypto->server_pubkey); cipher_free(crypto->in_cipher); cipher_free(crypto->out_cipher); bignum_safe_free(crypto->e); bignum_safe_free(crypto->f); bignum_safe_free(crypto->x); bignum_safe_free(crypto->y); bignum_safe_free(crypto->k); #ifdef HAVE_ECDH SAFE_FREE(crypto->ecdh_client_pubkey); SAFE_FREE(crypto->ecdh_server_pubkey); if(crypto->ecdh_privkey != NULL){ #ifdef HAVE_OPENSSL_ECC EC_KEY_free(crypto->ecdh_privkey); #elif defined HAVE_GCRYPT_ECC gcry_sexp_release(crypto->ecdh_privkey); #endif crypto->ecdh_privkey = NULL; } #endif if(crypto->session_id != NULL){ memset(crypto->session_id, '\0', crypto->digest_len); SAFE_FREE(crypto->session_id); } if(crypto->secret_hash != NULL){ memset(crypto->secret_hash, '\0', crypto->digest_len); SAFE_FREE(crypto->secret_hash); } #ifdef WITH_ZLIB if (crypto->compress_out_ctx && (deflateEnd(crypto->compress_out_ctx) != 0)) { inflateEnd(crypto->compress_out_ctx); } SAFE_FREE(crypto->compress_out_ctx); if (crypto->compress_in_ctx && (deflateEnd(crypto->compress_in_ctx) != 0)) { inflateEnd(crypto->compress_in_ctx); } SAFE_FREE(crypto->compress_in_ctx); #endif /* WITH_ZLIB */ if(crypto->encryptIV) SAFE_FREE(crypto->encryptIV); if(crypto->decryptIV) SAFE_FREE(crypto->decryptIV); if(crypto->encryptMAC) SAFE_FREE(crypto->encryptMAC); if(crypto->decryptMAC) SAFE_FREE(crypto->decryptMAC); if(crypto->encryptkey){ memset(crypto->encryptkey, 0, crypto->digest_len); SAFE_FREE(crypto->encryptkey); } if(crypto->decryptkey){ memset(crypto->decryptkey, 0, crypto->digest_len); SAFE_FREE(crypto->decryptkey); } for (i = 0; i < SSH_KEX_METHODS; i++) { SAFE_FREE(crypto->client_kex.methods[i]); SAFE_FREE(crypto->server_kex.methods[i]); SAFE_FREE(crypto->kex_methods[i]); } explicit_bzero(crypto, sizeof(struct ssh_crypto_struct)); SAFE_FREE(crypto); }
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; }
static int dh_handshake_server(ssh_session session) { ssh_key privkey; //ssh_string pubkey_blob = NULL; ssh_string sig_blob; ssh_string f; if (dh_generate_y(session) < 0) { ssh_set_error(session, SSH_FATAL, "Could not create y number"); return -1; } if (dh_generate_f(session) < 0) { ssh_set_error(session, SSH_FATAL, "Could not create f number"); return -1; } f = dh_get_f(session); if (f == NULL) { ssh_set_error(session, SSH_FATAL, "Could not get the f number"); return -1; } if (ssh_get_key_params(session,&privkey) != SSH_OK){ ssh_string_free(f); return -1; } if (dh_build_k(session) < 0) { ssh_set_error(session, SSH_FATAL, "Could not import the public key"); ssh_string_free(f); return -1; } if (make_sessionid(session) != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); ssh_string_free(f); return -1; } sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); ssh_string_free(f); return -1; } /* Free private keys as they should not be readable after this point */ if (session->srv.rsa_key) { ssh_key_free(session->srv.rsa_key); session->srv.rsa_key = NULL; } if (session->srv.dsa_key) { ssh_key_free(session->srv.dsa_key); session->srv.dsa_key = NULL; } #ifdef HAVE_ECC if (session->srv.ecdsa_key) { ssh_key_free(session->srv.ecdsa_key); session->srv.ecdsa_key = NULL; } #endif if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY) < 0 || buffer_add_ssh_string(session->out_buffer, session->next_crypto->server_pubkey) < 0 || buffer_add_ssh_string(session->out_buffer, f) < 0 || buffer_add_ssh_string(session->out_buffer, sig_blob) < 0) { ssh_set_error(session, SSH_FATAL, "Not enough space"); buffer_reinit(session->out_buffer); ssh_string_free(f); ssh_string_free(sig_blob); return -1; } ssh_string_free(f); ssh_string_free(sig_blob); if (packet_send(session) == SSH_ERROR) { return -1; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { buffer_reinit(session->out_buffer); return -1; } if (packet_send(session) == SSH_ERROR) { return -1; } ssh_log(session, SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent"); session->dh_handshake_state=DH_STATE_NEWKEYS_SENT; return 0; }
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){ /* ECDH keys */ ssh_string q_c_string = NULL; ssh_string q_s_string = NULL; EC_KEY *ecdh_key=NULL; const EC_GROUP *group; const EC_POINT *ecdh_pubkey; bignum_CTX ctx; /* SSH host keys (rsa,dsa,ecdsa) */ ssh_key privkey; ssh_string sig_blob = NULL; int len; int rc; enter_function(); /* Extract the client pubkey from the init packet */ q_c_string = buffer_get_ssh_string(packet); if (q_c_string == NULL) { ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet"); goto error; } session->next_crypto->ecdh_client_pubkey = q_c_string; /* Build server's keypair */ ctx = BN_CTX_new(); ecdh_key = EC_KEY_new_by_curve_name(NISTP256); group = EC_KEY_get0_group(ecdh_key); EC_KEY_generate_key(ecdh_key); ecdh_pubkey=EC_KEY_get0_public_key(ecdh_key); len = EC_POINT_point2oct(group,ecdh_pubkey,POINT_CONVERSION_UNCOMPRESSED, NULL,0,ctx); q_s_string=ssh_string_new(len); EC_POINT_point2oct(group,ecdh_pubkey,POINT_CONVERSION_UNCOMPRESSED, ssh_string_data(q_s_string),len,ctx); BN_CTX_free(ctx); session->next_crypto->ecdh_privkey = ecdh_key; session->next_crypto->ecdh_server_pubkey = q_s_string; buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY); /* build k and session_id */ if (ecdh_build_k(session) < 0) { ssh_set_error(session, SSH_FATAL, "Cannot build k number"); goto error; } if (ssh_get_key_params(session, &privkey) == SSH_ERROR) goto error; if (make_sessionid(session) != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); goto error; } /* add host's public key */ buffer_add_ssh_string(session->out_buffer, session->next_crypto->server_pubkey); /* add ecdh public key */ buffer_add_ssh_string(session->out_buffer,q_s_string); /* add signature blob */ sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey); if (sig_blob == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); goto error; } buffer_add_ssh_string(session->out_buffer, sig_blob); ssh_string_free(sig_blob); /* Free private keys as they should not be readable after this point */ if (session->srv.rsa_key) { ssh_key_free(session->srv.rsa_key); session->srv.rsa_key = NULL; } if (session->srv.dsa_key) { ssh_key_free(session->srv.dsa_key); session->srv.dsa_key = NULL; } ssh_log(session,SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent"); rc = packet_send(session); if (rc == SSH_ERROR) goto error; /* Send the MSG_NEWKEYS */ if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { goto error; } session->dh_handshake_state=DH_STATE_NEWKEYS_SENT; rc=packet_send(session); ssh_log(session, SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent"); return rc; error: return SSH_ERROR; }
int ssh_bind_listen(ssh_bind sshbind) { const char *host; socket_t fd; int rc; if (ssh_init() < 0) { ssh_set_error(sshbind, SSH_FATAL, "ssh_init() failed"); return -1; } if (sshbind->dsakey == NULL && sshbind->rsakey == NULL) { ssh_set_error(sshbind, SSH_FATAL, "DSA or RSA host key file must be set before listen()"); return SSH_ERROR; } if (sshbind->dsakey) { rc = ssh_pki_import_privkey_file(sshbind->dsakey, NULL, NULL, NULL, &sshbind->dsa); if (rc == SSH_ERROR) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private DSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->dsa) != SSH_KEYTYPE_DSS) { ssh_set_error(sshbind, SSH_FATAL, "The DSA host key has the wrong type"); ssh_key_free(sshbind->dsa); return SSH_ERROR; } } if (sshbind->rsakey) { rc = ssh_pki_import_privkey_file(sshbind->rsakey, NULL, NULL, NULL, &sshbind->rsa); if (rc == SSH_ERROR) { ssh_set_error(sshbind, SSH_FATAL, "Failed to import private RSA host key"); return SSH_ERROR; } if (ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA && ssh_key_type(sshbind->rsa) != SSH_KEYTYPE_RSA1) { ssh_set_error(sshbind, SSH_FATAL, "The RSA host key has the wrong type"); ssh_key_free(sshbind->rsa); return SSH_ERROR; } } if (sshbind->bindfd == SSH_INVALID_SOCKET) { host = sshbind->bindaddr; if (host == NULL) { host = "0.0.0.0"; } fd = bind_socket(sshbind, host, sshbind->bindport); if (fd == SSH_INVALID_SOCKET) { ssh_key_free(sshbind->dsa); ssh_key_free(sshbind->rsa); return -1; } sshbind->bindfd = fd; if (listen(fd, 10) < 0) { ssh_set_error(sshbind, SSH_FATAL, "Listening to socket %d: %s", fd, strerror(errno)); close(fd); ssh_key_free(sshbind->dsa); ssh_key_free(sshbind->rsa); return -1; } } else { SSH_LOG(sshbind, SSH_LOG_INFO, "Using app-provided bind socket"); } return 0; }
ssh_key pki_private_key_from_base64(ssh_session session, const char *b64_key, const char *passphrase) { BIO *mem = NULL; DSA *dsa = NULL; RSA *rsa = NULL; ssh_key key; enum ssh_keytypes_e type; /* needed for openssl initialization */ if (ssh_init() < 0) { return NULL; } type = pki_privatekey_type_from_string(b64_key); if (type == SSH_KEYTYPE_UNKNOWN) { ssh_set_error(session, SSH_FATAL, "Unknown or invalid private key."); return NULL; } mem = BIO_new_mem_buf((void*)b64_key, -1); switch (type) { case SSH_KEYTYPE_DSS: if (passphrase == NULL) { if (session->common.callbacks && session->common.callbacks->auth_function) { dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, pem_get_password, session); } else { /* openssl uses its own callback to get the passphrase here */ dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, NULL); } } else { dsa = PEM_read_bio_DSAPrivateKey(mem, NULL, NULL, (void *) passphrase); } BIO_free(mem); if (dsa == NULL) { ssh_set_error(session, SSH_FATAL, "Parsing private key: %s", ERR_error_string(ERR_get_error(), NULL)); return NULL; } break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: if (passphrase == NULL) { if (session->common.callbacks && session->common.callbacks->auth_function) { rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, pem_get_password, session); } else { /* openssl uses its own callback to get the passphrase here */ rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, NULL); } } else { rsa = PEM_read_bio_RSAPrivateKey(mem, NULL, NULL, (void *) passphrase); } BIO_free(mem); if (rsa == NULL) { ssh_set_error(session, SSH_FATAL, "Parsing private key: %s", ERR_error_string(ERR_get_error(),NULL)); return NULL; } break; case SSH_KEYTYPE_ECDSA: case SSH_KEYTYPE_UNKNOWN: BIO_free(mem); ssh_set_error(session, SSH_FATAL, "Unkown or invalid private key type %d", type); return NULL; } key = ssh_key_new(); if (key == NULL) { goto fail; } key->type = type; key->type_c = ssh_key_type_to_char(type); key->flags = SSH_KEY_FLAG_PRIVATE | SSH_KEY_FLAG_PUBLIC; key->dsa = dsa; key->rsa = rsa; return key; fail: ssh_key_free(key); DSA_free(dsa); RSA_free(rsa); return NULL; }
/** * @brief Deallocate a SSH session handle. * * @param[in] session The SSH session to free. * * @see ssh_disconnect() * @see ssh_new() */ void ssh_free(ssh_session session) { int i; struct ssh_iterator *it; if (session == NULL) { return; } /* * Delete all channels * * This needs the first thing we clean up cause if there is still an open * channel we call ssh_channel_close() first. So we need a working socket * and poll context for it. */ for (it = ssh_list_get_iterator(session->channels); it != NULL; it = ssh_list_get_iterator(session->channels)) { ssh_channel_do_free(ssh_iterator_value(ssh_channel,it)); ssh_list_remove(session->channels, it); } ssh_list_free(session->channels); session->channels = NULL; #ifdef WITH_PCAP if (session->pcap_ctx) { ssh_pcap_context_free(session->pcap_ctx); session->pcap_ctx = NULL; } #endif ssh_socket_free(session->socket); session->socket = NULL; if (session->default_poll_ctx) { ssh_poll_ctx_free(session->default_poll_ctx); } ssh_buffer_free(session->in_buffer); ssh_buffer_free(session->out_buffer); session->in_buffer = session->out_buffer = NULL; if (session->in_hashbuf != NULL) { ssh_buffer_free(session->in_hashbuf); } if (session->out_hashbuf != NULL) { ssh_buffer_free(session->out_hashbuf); } crypto_free(session->current_crypto); crypto_free(session->next_crypto); #ifndef _WIN32 agent_free(session->agent); #endif /* _WIN32 */ ssh_key_free(session->srv.dsa_key); ssh_key_free(session->srv.rsa_key); if (session->ssh_message_list) { ssh_message msg; for (msg = ssh_list_pop_head(ssh_message, session->ssh_message_list); msg != NULL; msg = ssh_list_pop_head(ssh_message, session->ssh_message_list)) { ssh_message_free(msg); } ssh_list_free(session->ssh_message_list); } if (session->packet_callbacks) { ssh_list_free(session->packet_callbacks); } /* options */ if (session->opts.identity) { char *id; for (id = ssh_list_pop_head(char *, session->opts.identity); id != NULL; id = ssh_list_pop_head(char *, session->opts.identity)) { SAFE_FREE(id); } ssh_list_free(session->opts.identity); }
static gint mock_ssh_server (const gchar *server_addr, gint server_port, const gchar *user, const gchar *password, gboolean multi_step) { char portname[16]; char addrname[16]; struct sockaddr_storage addr; socklen_t addrlen; ssh_bind sshbind; const char *msg; int r; gint rounds = 0; state.event = ssh_event_new (); if (state.event == NULL) g_return_val_if_reached (-1); sshbind = ssh_bind_new (); state.session = ssh_new (); if (server_addr == NULL) server_addr = "127.0.0.1"; ssh_bind_options_set (sshbind, SSH_BIND_OPTIONS_BINDADDR, server_addr); ssh_bind_options_set (sshbind, SSH_BIND_OPTIONS_BINDPORT, &server_port); ssh_bind_options_set (sshbind, SSH_BIND_OPTIONS_RSAKEY, SRCDIR "/src/ws/mock_rsa_key"); ssh_bind_options_set (sshbind, SSH_BIND_OPTIONS_DSAKEY, SRCDIR "/src/ws/mock_dsa_key"); if (ssh_bind_listen (sshbind) < 0) { g_critical ("couldn't listen on socket: %s", ssh_get_error (sshbind)); return 1; } state.bind_fd = ssh_bind_get_fd (sshbind); state.user = user; state.password = password; state.multi_step = multi_step; ssh_pki_import_pubkey_file (SRCDIR "/src/ws/test_rsa.pub", &state.pkey); state.buffer = g_byte_array_new (); /* Print out the port */ if (server_port == 0) { addrlen = sizeof (addr); if (getsockname (state.bind_fd, (struct sockaddr *)&addr, &addrlen) < 0) { g_critical ("couldn't get local address: %s", g_strerror (errno)); return 1; } r = getnameinfo ((struct sockaddr *)&addr, addrlen, addrname, sizeof (addrname), portname, sizeof (portname), NI_NUMERICHOST | NI_NUMERICSERV); if (r != 0) { g_critical ("couldn't get local port: %s", gai_strerror (r)); return 1; } /* Caller wants to know the port */ g_print ("%s\n", portname); } /* Close stdout (once above info is printed) */ close (1); ssh_set_message_callback (state.session, authenticate_callback, &rounds); r = ssh_bind_accept (sshbind, state.session); if (r == SSH_ERROR) { g_critical ("accepting connection failed: %s", ssh_get_error (sshbind)); return 1; } state.session_fd = ssh_get_fd (state.session); if (ssh_handle_key_exchange (state.session)) { msg = ssh_get_error (state.session); if (!strstr (msg, "_DISCONNECT")) g_critical ("key exchange failed: %s", msg); return 1; } if (ssh_event_add_session (state.event, state.session) != SSH_OK) g_return_val_if_reached (-1); do { ssh_event_dopoll (state.event, 10000); } while (ssh_is_connected (state.session)); ssh_event_remove_session (state.event, state.session); ssh_event_free (state.event); ssh_free (state.session); ssh_key_free (state.pkey); g_byte_array_free (state.buffer, TRUE); ssh_bind_free (sshbind); return 0; }