int signature_verify(ssh_session session, ssh_string signature) { ssh_public_key pubkey = NULL; SIGNATURE *sign = NULL; int err; enter_function(); pubkey = publickey_from_string(session,session->next_crypto->server_pubkey); if(pubkey == NULL) { leave_function(); return -1; } if (session->wanted_methods[SSH_HOSTKEYS]) { if(!match(session->wanted_methods[SSH_HOSTKEYS],pubkey->type_c)) { ssh_set_error(session, SSH_FATAL, "Public key from server (%s) doesn't match user preference (%s)", pubkey->type_c, session->wanted_methods[SSH_HOSTKEYS]); publickey_free(pubkey); leave_function(); return -1; } } sign = signature_from_string(session, signature, pubkey, pubkey->type); if (sign == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid signature blob"); publickey_free(pubkey); leave_function(); return -1; } ssh_log(session, SSH_LOG_FUNCTIONS, "Going to verify a %s type signature", pubkey->type_c); err = sig_verify(session,pubkey,sign, session->next_crypto->session_id,SHA_DIGEST_LEN); signature_free(sign); session->next_crypto->server_pubkey_type = pubkey->type_c; publickey_free(pubkey); leave_function(); return err; }
static void torture_pubkey_generate_from_privkey(void **state) { ssh_session session = *state; ssh_private_key privkey = NULL; ssh_public_key pubkey = NULL; ssh_string pubkey_orig = NULL; ssh_string pubkey_new = NULL; char pubkey_line_orig[512] = {0}; char pubkey_line_new[512] = {0}; int type_orig = 0; int type_new = 0; int rc; /* read the publickey */ rc = ssh_try_publickey_from_file(session, LIBSSH_RSA_TESTKEY, &pubkey_orig, &type_orig); assert_true(rc == 0); assert_true(pubkey_orig != NULL); rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_orig, sizeof(pubkey_line_orig)); assert_true(rc == 0); /* remove the public key, generate it from the private key and write it. */ unlink(LIBSSH_RSA_TESTKEY ".pub"); privkey = privatekey_from_file(session, LIBSSH_RSA_TESTKEY, 0, NULL); assert_true(privkey != NULL); pubkey = publickey_from_privatekey(privkey); assert_true(pubkey != NULL); type_new = privkey->type; privatekey_free(privkey); pubkey_new = publickey_to_string(pubkey); publickey_free(pubkey); assert_true(pubkey_new != NULL); assert_true(ssh_string_len(pubkey_orig) == ssh_string_len(pubkey_new)); assert_memory_equal(ssh_string_data(pubkey_orig), ssh_string_data(pubkey_new), ssh_string_len(pubkey_orig)); rc = ssh_publickey_to_file(session, LIBSSH_RSA_TESTKEY ".pub", pubkey_new, type_new); assert_true(rc == 0); rc = torture_read_one_line(LIBSSH_RSA_TESTKEY ".pub", pubkey_line_new, sizeof(pubkey_line_new)); assert_true(rc == 0); assert_string_equal(pubkey_line_orig, pubkey_line_new); ssh_string_free(pubkey_orig); ssh_string_free(pubkey_new); }
/** * @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); } publickey_free(msg->auth_request.public_key); 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); }
ssh_public_key publickey_make_dss(ssh_session session, ssh_buffer buffer) { ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string pubkey = NULL; ssh_public_key key = NULL; key = malloc(sizeof(struct ssh_public_key_struct)); if (key == NULL) { ssh_buffer_free(buffer); return NULL; } ZERO_STRUCTP(key); key->type = SSH_KEYTYPE_DSS; key->type_c = ssh_type_to_char(key->type); p = buffer_get_ssh_string(buffer); q = buffer_get_ssh_string(buffer); g = buffer_get_ssh_string(buffer); pubkey = buffer_get_ssh_string(buffer); ssh_buffer_free(buffer); /* we don't need it anymore */ if (p == NULL || q == NULL || g == NULL || pubkey == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid DSA public key"); goto error; } #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&key->dsa_pub, NULL, "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", ssh_string_len(p), ssh_string_data(p), ssh_string_len(q), ssh_string_data(q), ssh_string_len(g), ssh_string_data(g), ssh_string_len(pubkey), ssh_string_data(pubkey)); if (key->dsa_pub == NULL) { goto error; } #elif defined HAVE_LIBCRYPTO key->dsa_pub = DSA_new(); if (key->dsa_pub == NULL) { goto error; } key->dsa_pub->p = make_string_bn(p); key->dsa_pub->q = make_string_bn(q); key->dsa_pub->g = make_string_bn(g); key->dsa_pub->pub_key = make_string_bn(pubkey); if (key->dsa_pub->p == NULL || key->dsa_pub->q == NULL || key->dsa_pub->g == NULL || key->dsa_pub->pub_key == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ #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); return key; error: 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); publickey_free(key); return NULL; }
/** * @brief Make a public_key object out of a private_key object. * * @param[in] prv The private key to generate the public key. * * @returns The generated public key, NULL on error. * * @see publickey_to_string() */ ssh_public_key publickey_from_privatekey(ssh_private_key prv) { ssh_public_key key = NULL; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sexp; const char *tmp = NULL; size_t size; ssh_string p = NULL; ssh_string q = NULL; ssh_string g = NULL; ssh_string y = NULL; ssh_string e = NULL; ssh_string n = NULL; #endif /* HAVE_LIBGCRYPT */ key = malloc(sizeof(struct ssh_public_key_struct)); if (key == NULL) { return NULL; } ZERO_STRUCTP(key); key->type = prv->type; switch(key->type) { case SSH_KEYTYPE_DSS: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(prv->dsa_priv, "p", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); p = ssh_string_new(size); if (p == NULL) { goto error; } ssh_string_fill(p,(char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv,"q",0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); q = ssh_string_new(size); if (q == NULL) { goto error; } ssh_string_fill(q,(char *) tmp,size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv, "g", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); g = ssh_string_new(size); if (g == NULL) { goto error; } ssh_string_fill(g,(char *) tmp,size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv,"y",0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); y = ssh_string_new(size); if (y == NULL) { goto error; } ssh_string_fill(y,(char *) tmp,size); gcry_sexp_release(sexp); gcry_sexp_build(&key->dsa_pub, NULL, "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", ssh_string_len(p), ssh_string_data(p), ssh_string_len(q), ssh_string_data(q), ssh_string_len(g), ssh_string_data(g), ssh_string_len(y), ssh_string_data(y)); 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(y); ssh_string_free(y); #elif defined HAVE_LIBCRYPTO key->dsa_pub = DSA_new(); if (key->dsa_pub == NULL) { goto error; } key->dsa_pub->p = BN_dup(prv->dsa_priv->p); key->dsa_pub->q = BN_dup(prv->dsa_priv->q); key->dsa_pub->g = BN_dup(prv->dsa_priv->g); key->dsa_pub->pub_key = BN_dup(prv->dsa_priv->pub_key); if (key->dsa_pub->p == NULL || key->dsa_pub->q == NULL || key->dsa_pub->g == NULL || key->dsa_pub->pub_key == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ break; case SSH_KEYTYPE_RSA: case SSH_KEYTYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(prv->rsa_priv, "n", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); n = ssh_string_new(size); if (n == NULL) { goto error; } ssh_string_fill(n, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->rsa_priv, "e", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); e = ssh_string_new(size); if (e == NULL) { goto error; } ssh_string_fill(e, (char *) tmp, size); gcry_sexp_release(sexp); gcry_sexp_build(&key->rsa_pub, NULL, "(public-key(rsa(n %b)(e %b)))", ssh_string_len(n), ssh_string_data(n), ssh_string_len(e), ssh_string_data(e)); if (key->rsa_pub == NULL) { goto error; } ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); #elif defined HAVE_LIBCRYPTO key->rsa_pub = RSA_new(); if (key->rsa_pub == NULL) { goto error; } key->rsa_pub->e = BN_dup(prv->rsa_priv->e); key->rsa_pub->n = BN_dup(prv->rsa_priv->n); if (key->rsa_pub->e == NULL || key->rsa_pub->n == NULL) { goto error; } #endif break; default: publickey_free(key); return NULL; } key->type_c = ssh_type_to_char(prv->type); return key; error: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sexp); 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(y); ssh_string_free(y); ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); #endif publickey_free(key); return NULL; }
ssh_public_key publickey_make_rsa(ssh_session session, ssh_buffer buffer, int type) { ssh_string e = NULL; ssh_string n = NULL; ssh_public_key key = NULL; key = malloc(sizeof(struct ssh_public_key_struct)); if (key == NULL) { ssh_buffer_free(buffer); return NULL; } ZERO_STRUCTP(key); key->type = type; key->type_c = ssh_type_to_char(key->type); e = buffer_get_ssh_string(buffer); n = buffer_get_ssh_string(buffer); ssh_buffer_free(buffer); /* we don't need it anymore */ if(e == NULL || n == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid RSA public key"); goto error; } #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&key->rsa_pub, NULL, "(public-key(rsa(n %b)(e %b)))", ssh_string_len(n), ssh_string_data(n), ssh_string_len(e),ssh_string_data(e)); if (key->rsa_pub == NULL) { goto error; } #elif HAVE_LIBCRYPTO key->rsa_pub = RSA_new(); if (key->rsa_pub == NULL) { goto error; } key->rsa_pub->e = make_string_bn(e); key->rsa_pub->n = make_string_bn(n); if (key->rsa_pub->e == NULL || key->rsa_pub->n == NULL) { goto error; } #endif #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); return key; error: ssh_string_burn(e); ssh_string_free(e); ssh_string_burn(n); ssh_string_free(n); publickey_free(key); return NULL; }
int ssh_get_kex1(SSH_SESSION *session) { STRING *server_exp = NULL; STRING *server_mod = NULL; STRING *host_exp = NULL; STRING *host_mod = NULL; STRING *serverkey = NULL; STRING *hostkey = NULL; STRING *enc_session = NULL; PUBLIC_KEY *srv = NULL; PUBLIC_KEY *host = NULL; u32 server_bits; u32 host_bits; u32 protocol_flags; u32 supported_ciphers_mask; u32 supported_authentications_mask; u16 bits; int rc = -1; int ko; enter_function(); ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_PUBLIC_KEY"); if (packet_wait(session, SSH_SMSG_PUBLIC_KEY, 1) != SSH_OK) { leave_function(); return -1; } ssh_log(session, SSH_LOG_PROTOCOL, "Got a SSH_SMSG_PUBLIC_KEY"); if (buffer_get_data(session->in_buffer, session->server_kex.cookie, 8) != 8) { ssh_set_error(session, SSH_FATAL, "Can't get cookie in buffer"); leave_function(); return -1; } buffer_get_u32(session->in_buffer, &server_bits); server_exp = buffer_get_mpint(session->in_buffer); if (server_exp == NULL) { goto error; } server_mod = buffer_get_mpint(session->in_buffer); if (server_mod == NULL) { goto error; } buffer_get_u32(session->in_buffer, &host_bits); host_exp = buffer_get_mpint(session->in_buffer); if (host_exp == NULL) { goto error; } host_mod = buffer_get_mpint(session->in_buffer); if (host_mod == NULL) { goto error; } buffer_get_u32(session->in_buffer, &protocol_flags); buffer_get_u32(session->in_buffer, &supported_ciphers_mask); ko = buffer_get_u32(session->in_buffer, &supported_authentications_mask); if ((ko != sizeof(u32)) || !host_mod || !host_exp || !server_mod || !server_exp) { ssh_log(session, SSH_LOG_RARE, "Invalid SSH_SMSG_PUBLIC_KEY packet"); ssh_set_error(session, SSH_FATAL, "Invalid SSH_SMSG_PUBLIC_KEY packet"); goto error; } server_bits = ntohl(server_bits); host_bits = ntohl(host_bits); protocol_flags = ntohl(protocol_flags); supported_ciphers_mask = ntohl(supported_ciphers_mask); supported_authentications_mask = ntohl(supported_authentications_mask); ssh_log(session, SSH_LOG_PROTOCOL, "Server bits: %d; Host bits: %d; Protocol flags: %.8lx; " "Cipher mask: %.8lx; Auth mask: %.8lx", server_bits, host_bits, (unsigned long int) protocol_flags, (unsigned long int) supported_ciphers_mask, (unsigned long int) supported_authentications_mask); serverkey = make_rsa1_string(server_exp, server_mod); if (serverkey == NULL) { goto error; } hostkey = make_rsa1_string(host_exp,host_mod); if (serverkey == NULL) { goto error; } if (build_session_id1(session, server_mod, host_mod) < 0) { goto error; } srv = publickey_from_string(session, serverkey); if (srv == NULL) { goto error; } host = publickey_from_string(session, hostkey); if (host == NULL) { goto error; } session->next_crypto->server_pubkey = string_copy(hostkey); if (session->next_crypto->server_pubkey == NULL) { goto error; } session->next_crypto->server_pubkey_type = "ssh-rsa1"; /* now, we must choose an encryption algo */ /* hardcode 3des */ if (!(supported_ciphers_mask & (1 << SSH_CIPHER_3DES))) { ssh_set_error(session, SSH_FATAL, "Remote server doesn't accept 3DES"); goto error; } ssh_log(session, SSH_LOG_PROTOCOL, "Sending SSH_CMSG_SESSION_KEY"); if (buffer_add_u8(session->out_buffer, SSH_CMSG_SESSION_KEY) < 0) { goto error; } if (buffer_add_u8(session->out_buffer, SSH_CIPHER_3DES) < 0) { goto error; } if (buffer_add_data(session->out_buffer, session->server_kex.cookie, 8) < 0) { goto error; } enc_session = encrypt_session_key(session, srv, host, server_bits, host_bits); if (enc_session == NULL) { goto error; } bits = string_len(enc_session) * 8 - 7; ssh_log(session, SSH_LOG_PROTOCOL, "%d bits, %zu bytes encrypted session", bits, string_len(enc_session)); bits = htons(bits); /* the encrypted mpint */ if (buffer_add_data(session->out_buffer, &bits, sizeof(u16)) < 0) { goto error; } if (buffer_add_data(session->out_buffer, enc_session->string, string_len(enc_session)) < 0) { goto error; } /* the protocol flags */ if (buffer_add_u32(session->out_buffer, 0) < 0) { goto error; } if (packet_send(session) != SSH_OK) { goto error; } /* we can set encryption */ if (crypt_set_algorithms(session)) { goto error; } session->current_crypto = session->next_crypto; session->next_crypto = NULL; ssh_log(session, SSH_LOG_PROTOCOL, "Waiting for a SSH_SMSG_SUCCESS"); if (packet_wait(session,SSH_SMSG_SUCCESS,1) != SSH_OK) { char buffer[1024] = {0}; snprintf(buffer, sizeof(buffer), "Key exchange failed: %s", ssh_get_error(session)); ssh_set_error(session, SSH_FATAL, "%s",buffer); goto error; } ssh_log(session, SSH_LOG_PROTOCOL, "received SSH_SMSG_SUCCESS\n"); rc = 0; error: string_free(host_mod); string_free(host_exp); string_free(server_mod); string_free(server_exp); string_free(serverkey); string_free(hostkey); publickey_free(srv); publickey_free(host); leave_function(); return rc; }
gboolean remmina_nx_session_open(RemminaNXSession *nx, const gchar *server, guint port, const gchar *private_key_file, RemminaNXPassphraseCallback passphrase_func, gpointer userdata) { gint ret; ssh_private_key privkey; ssh_public_key pubkey; ssh_string pubkeystr; gint keytype; gboolean encrypted; gchar *passphrase = NULL; gchar tmpfile[L_tmpnam + 1]; nx ->session = ssh_new(); ssh_options_set(nx->session, SSH_OPTIONS_HOST, server); ssh_options_set(nx->session, SSH_OPTIONS_PORT, &port); ssh_options_set(nx->session, SSH_OPTIONS_USER, "nx"); if (private_key_file && private_key_file[0]) { if (!remmina_get_keytype(private_key_file, &keytype, &encrypted)) { remmina_nx_session_set_application_error(nx, "Invalid private key file."); return FALSE; } if (encrypted && !passphrase_func(&passphrase, userdata)) { return FALSE; } privkey = privatekey_from_file(nx->session, private_key_file, keytype, (passphrase ? passphrase : "")); g_free(passphrase); } else { /* Use NoMachine's default nx private key */ if ((tmpnam(tmpfile)) == NULL || !g_file_set_contents(tmpfile, nx_default_private_key, -1, NULL)) { remmina_nx_session_set_application_error(nx, "Failed to create temporary private key file."); return FALSE; } privkey = privatekey_from_file(nx->session, tmpfile, REMMINA_SSH_TYPE_DSS, ""); g_unlink(tmpfile); } if (privkey == NULL) { remmina_nx_session_set_error(nx, "Invalid private key file: %s"); return FALSE; } pubkey = publickey_from_privatekey(privkey); pubkeystr = publickey_to_string(pubkey); publickey_free(pubkey); if (ssh_connect(nx->session)) { string_free(pubkeystr); privatekey_free(privkey); remmina_nx_session_set_error(nx, "Failed to startup SSH session: %s"); return FALSE; } ret = ssh_userauth_pubkey(nx->session, NULL, pubkeystr, privkey); string_free(pubkeystr); privatekey_free(privkey); if (ret != SSH_AUTH_SUCCESS) { remmina_nx_session_set_error(nx, "NX SSH authentication failed: %s"); return FALSE; } if ((nx->channel = channel_new(nx->session)) == NULL || channel_open_session(nx->channel)) { return FALSE; } if (channel_request_shell(nx->channel)) { return FALSE; } /* NX server starts the session with an initial 105 status */ if (!remmina_nx_session_expect_status(nx, 105)) return FALSE; /* Say hello to the NX server */ remmina_nx_session_send_command(nx, "HELLO NXCLIENT - Version %s", nx->version); if (!remmina_nx_session_expect_status(nx, 105)) return FALSE; /* Set the NX session environment */ remmina_nx_session_send_command(nx, "SET SHELL_MODE SHELL"); if (!remmina_nx_session_expect_status(nx, 105)) return FALSE; remmina_nx_session_send_command(nx, "SET AUTH_MODE PASSWORD"); if (!remmina_nx_session_expect_status(nx, 105)) return FALSE; nx->server = g_strdup(server); return TRUE; }
/** * @brief Write the current server as known in the known hosts file. * * This will create the known hosts file if it does not exist. You generaly use * it when ssh_is_server_known() answered SSH_SERVER_NOT_KNOWN. * * @param[in] session The ssh session to use. * * @return SSH_OK on success, SSH_ERROR on error. */ int ssh_write_knownhost(ssh_session session) { ssh_string pubkey; unsigned char *pubkey_64; char buffer[4096] = {0}; FILE *file; char *dir; char *host; char *hostport; size_t len = 0; if (session->host == NULL) { ssh_set_error(session, SSH_FATAL, "Can't write host in known hosts if the hostname isn't known"); return SSH_ERROR; } host = ssh_lowercase(session->host); /* If using a nonstandard port, save the host in the [host]:port format */ if(session->port != 22){ hostport = ssh_hostport(host,session->port); SAFE_FREE(host); host=hostport; hostport=NULL; } if (session->knownhosts == NULL) { if (ssh_options_apply(session) < 0) { ssh_set_error(session, SSH_FATAL, "Can't find a known_hosts file"); return SSH_ERROR; } } if(session->current_crypto==NULL) { ssh_set_error(session, SSH_FATAL, "No current crypto context"); return SSH_ERROR; } pubkey = session->current_crypto->server_pubkey; if(pubkey == NULL){ ssh_set_error(session, SSH_FATAL, "No public key present"); return SSH_ERROR; } /* Check if ~/.ssh exists and create it if not */ dir = ssh_dirname(session->knownhosts); if (dir == NULL) { ssh_set_error(session, SSH_FATAL, "%s", strerror(errno)); return -1; } if (! ssh_file_readaccess_ok(dir)) { if (ssh_mkdir(dir, 0700) < 0) { ssh_set_error(session, SSH_FATAL, "Cannot create %s directory.", dir); SAFE_FREE(dir); return -1; } } SAFE_FREE(dir); file = fopen(session->knownhosts, "a"); if (file == NULL) { ssh_set_error(session, SSH_FATAL, "Couldn't open known_hosts file %s for appending: %s", session->knownhosts, strerror(errno)); SAFE_FREE(host); return -1; } if (strcmp(session->current_crypto->server_pubkey_type, "ssh-rsa1") == 0) { /* openssh uses a different format for ssh-rsa1 keys. Be compatible --kv */ ssh_public_key key; char *e_string = NULL; char *n_string = NULL; bignum e = NULL; bignum n = NULL; int rsa_size; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sexp; #endif key = publickey_from_string(session, pubkey); if (key == NULL) { fclose(file); SAFE_FREE(host); return -1; } #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(key->rsa_pub, "e", 0); if (sexp == NULL) { publickey_free(key); fclose(file); SAFE_FREE(host); return -1; } e = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); gcry_sexp_release(sexp); if (e == NULL) { publickey_free(key); fclose(file); SAFE_FREE(host); return -1; } sexp = gcry_sexp_find_token(key->rsa_pub, "n", 0); if (sexp == NULL) { publickey_free(key); bignum_free(e); fclose(file); SAFE_FREE(host); return -1; } n = gcry_sexp_nth_mpi(sexp, 1, GCRYMPI_FMT_USG); gcry_sexp_release(sexp); if (n == NULL) { publickey_free(key); bignum_free(e); fclose(file); SAFE_FREE(host); return -1; } rsa_size = (gcry_pk_get_nbits(key->rsa_pub) + 7) / 8; #elif defined HAVE_LIBCRYPTO e = key->rsa_pub->e; n = key->rsa_pub->n; rsa_size = RSA_size(key->rsa_pub); #endif e_string = bignum_bn2dec(e); n_string = bignum_bn2dec(n); if (e_string == NULL || n_string == NULL) { #ifdef HAVE_LIBGCRYPT bignum_free(e); bignum_free(n); SAFE_FREE(e_string); SAFE_FREE(n_string); #elif defined HAVE_LIBCRYPTO OPENSSL_free(e_string); OPENSSL_free(n_string); #endif publickey_free(key); fclose(file); SAFE_FREE(host); return -1; } snprintf(buffer, sizeof(buffer), "%s %d %s %s\n", host, rsa_size << 3, e_string, n_string); #ifdef HAVE_LIBGCRYPT bignum_free(e); bignum_free(n); SAFE_FREE(e_string); SAFE_FREE(n_string); #elif defined HAVE_LIBCRYPTO OPENSSL_free(e_string); OPENSSL_free(n_string); #endif publickey_free(key); } else { pubkey_64 = bin_to_base64(pubkey->string, ssh_string_len(pubkey)); if (pubkey_64 == NULL) { fclose(file); SAFE_FREE(host); return -1; } snprintf(buffer, sizeof(buffer), "%s %s %s\n", host, session->current_crypto->server_pubkey_type, pubkey_64); SAFE_FREE(pubkey_64); } SAFE_FREE(host); len = strlen(buffer); if (fwrite(buffer, len, 1, file) != 1 || ferror(file)) { fclose(file); return -1; } fclose(file); return 0; }
static int dh_handshake_server(ssh_session session) { ssh_string f; ssh_string pubkey; ssh_string sign; ssh_public_key pub; ssh_private_key prv; 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; } switch(session->hostkeys){ case SSH_KEYTYPE_DSS: prv = session->dsa_key; break; case SSH_KEYTYPE_RSA: prv = session->rsa_key; break; default: prv = NULL; } pub = publickey_from_privatekey(prv); if (pub == NULL) { ssh_set_error(session, SSH_FATAL, "Could not get the public key from the private key"); ssh_string_free(f); return -1; } pubkey = publickey_to_string(pub); publickey_free(pub); if (pubkey == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); ssh_string_free(f); return -1; } dh_import_pubkey(session, pubkey); 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; } sign = ssh_sign_session_id(session, prv); if (sign == 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->rsa_key) { privatekey_free(session->rsa_key); session->rsa_key = NULL; } if (session->dsa_key) { privatekey_free(session->dsa_key); session->dsa_key = NULL; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY) < 0 || buffer_add_ssh_string(session->out_buffer, pubkey) < 0 || buffer_add_ssh_string(session->out_buffer, f) < 0 || buffer_add_ssh_string(session->out_buffer, sign) < 0) { ssh_set_error(session, SSH_FATAL, "Not enough space"); buffer_reinit(session->out_buffer); ssh_string_free(f); ssh_string_free(sign); return -1; } ssh_string_free(f); ssh_string_free(sign); 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; }
PUBLIC_KEY *publickey_make_dss(SSH_SESSION *session, BUFFER *buffer) { STRING *p = NULL; STRING *q = NULL; STRING *g = NULL; STRING *pubkey = NULL; PUBLIC_KEY *key = NULL; key = malloc(sizeof(PUBLIC_KEY)); if (key == NULL) { buffer_free(buffer); return NULL; } key->type = TYPE_DSS; key->type_c = ssh_type_to_char(key->type); p = buffer_get_ssh_string(buffer); q = buffer_get_ssh_string(buffer); g = buffer_get_ssh_string(buffer); pubkey = buffer_get_ssh_string(buffer); buffer_free(buffer); /* we don't need it anymore */ if (p == NULL || q == NULL || g == NULL || pubkey == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid DSA public key"); goto error; } #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&key->dsa_pub, NULL, "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", string_len(p), p->string, string_len(q), q->string, string_len(g), g->string, string_len(pubkey), pubkey->string); if (key->dsa_pub == NULL) { goto error; } #elif defined HAVE_LIBCRYPTO key->dsa_pub = DSA_new(); if (key->dsa_pub == NULL) { goto error; } key->dsa_pub->p = make_string_bn(p); key->dsa_pub->q = make_string_bn(q); key->dsa_pub->g = make_string_bn(g); key->dsa_pub->pub_key = make_string_bn(pubkey); if (key->dsa_pub->p == NULL || key->dsa_pub->q == NULL || key->dsa_pub->g == NULL || key->dsa_pub->pub_key == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ #ifdef DEBUG_CRYPTO ssh_print_hexa("p", p->string, string_len(p)); ssh_print_hexa("q", q->string, string_len(q)); ssh_print_hexa("g", g->string, string_len(g)); #endif string_burn(p); string_free(p); string_burn(q); string_free(q); string_burn(g); string_free(g); string_burn(pubkey); string_free(pubkey); return key; error: string_burn(p); string_free(p); string_burn(q); string_free(q); string_burn(g); string_free(g); string_burn(pubkey); string_free(pubkey); publickey_free(key); return NULL; }
/** \brief Makes a PUBLIC_KEY object out of a PRIVATE_KEY object * \param prv the Private key * \returns the public key * \see publickey_to_string() */ PUBLIC_KEY *publickey_from_privatekey(PRIVATE_KEY *prv) { PUBLIC_KEY *key = NULL; #ifdef HAVE_LIBGCRYPT gcry_sexp_t sexp; const char *tmp = NULL; size_t size; STRING *p = NULL; STRING *q = NULL; STRING *g = NULL; STRING *y = NULL; STRING *e = NULL; STRING *n = NULL; #endif /* HAVE_LIBGCRYPT */ key = malloc(sizeof(PUBLIC_KEY)); if (key == NULL) { return NULL; } key->type = prv->type; switch(key->type) { case TYPE_DSS: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(prv->dsa_priv, "p", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); p = string_new(size); if (p == NULL) { goto error; } string_fill(p,(char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv,"q",0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); q = string_new(size); if (q == NULL) { goto error; } string_fill(q,(char *) tmp,size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv, "g", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); g = string_new(size); if (g == NULL) { goto error; } string_fill(g,(char *) tmp,size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->dsa_priv,"y",0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp,1,&size); y = string_new(size); if (y == NULL) { goto error; } string_fill(y,(char *) tmp,size); gcry_sexp_release(sexp); gcry_sexp_build(&key->dsa_pub, NULL, "(public-key(dsa(p %b)(q %b)(g %b)(y %b)))", string_len(p), p->string, string_len(q), q->string, string_len(g), g->string, string_len(y), y->string); string_burn(p); string_free(p); string_burn(q); string_free(q); string_burn(g); string_free(g); string_burn(y); string_free(y); #elif defined HAVE_LIBCRYPTO key->dsa_pub = DSA_new(); if (key->dsa_pub == NULL) { goto error; } key->dsa_pub->p = BN_dup(prv->dsa_priv->p); key->dsa_pub->q = BN_dup(prv->dsa_priv->q); key->dsa_pub->g = BN_dup(prv->dsa_priv->g); key->dsa_pub->pub_key = BN_dup(prv->dsa_priv->pub_key); if (key->dsa_pub->p == NULL || key->dsa_pub->q == NULL || key->dsa_pub->g == NULL || key->dsa_pub->pub_key == NULL) { goto error; } #endif /* HAVE_LIBCRYPTO */ break; case TYPE_RSA: case TYPE_RSA1: #ifdef HAVE_LIBGCRYPT sexp = gcry_sexp_find_token(prv->rsa_priv, "n", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); n = string_new(size); if (n == NULL) { goto error; } string_fill(n, (char *) tmp, size); gcry_sexp_release(sexp); sexp = gcry_sexp_find_token(prv->rsa_priv, "e", 0); if (sexp == NULL) { goto error; } tmp = gcry_sexp_nth_data(sexp, 1, &size); e = string_new(size); if (e == NULL) { goto error; } string_fill(e, (char *) tmp, size); gcry_sexp_release(sexp); gcry_sexp_build(&key->rsa_pub, NULL, "(public-key(rsa(n %b)(e %b)))", string_len(n), n->string, string_len(e), e->string); if (key->rsa_pub == NULL) { goto error; } string_burn(e); string_free(e); string_burn(n); string_free(n); #elif defined HAVE_LIBCRYPTO key->rsa_pub = RSA_new(); if (key->rsa_pub == NULL) { goto error; } key->rsa_pub->e = BN_dup(prv->rsa_priv->e); key->rsa_pub->n = BN_dup(prv->rsa_priv->n); if (key->rsa_pub->e == NULL || key->rsa_pub->n == NULL) { goto error; } #endif break; } key->type_c = ssh_type_to_char(prv->type); return key; error: #ifdef HAVE_LIBGCRYPT gcry_sexp_release(sexp); string_burn(p); string_free(p); string_burn(q); string_free(q); string_burn(g); string_free(g); string_burn(y); string_free(y); string_burn(e); string_free(e); string_burn(n); string_free(n); #endif publickey_free(key); return NULL; }
PUBLIC_KEY *publickey_make_rsa(SSH_SESSION *session, BUFFER *buffer, int type) { STRING *e = NULL; STRING *n = NULL; PUBLIC_KEY *key = NULL; key = malloc(sizeof(PUBLIC_KEY)); if (key == NULL) { buffer_free(buffer); return NULL; } key->type = type; key->type_c = ssh_type_to_char(key->type); e = buffer_get_ssh_string(buffer); n = buffer_get_ssh_string(buffer); buffer_free(buffer); /* we don't need it anymore */ if(e == NULL || n == NULL) { ssh_set_error(session, SSH_FATAL, "Invalid RSA public key"); goto error; } #ifdef HAVE_LIBGCRYPT gcry_sexp_build(&key->rsa_pub, NULL, "(public-key(rsa(n %b)(e %b)))", string_len(n), n->string, string_len(e),e->string); if (key->rsa_pub == NULL) { goto error; } #elif HAVE_LIBCRYPTO key->rsa_pub = RSA_new(); if (key->rsa_pub == NULL) { goto error; } key->rsa_pub->e = make_string_bn(e); key->rsa_pub->n = make_string_bn(n); if (key->rsa_pub->e == NULL || key->rsa_pub->n == NULL) { goto error; } #endif #ifdef DEBUG_CRYPTO ssh_print_hexa("e", e->string, string_len(e)); ssh_print_hexa("n", n->string, string_len(n)); #endif string_burn(e); string_free(e); string_burn(n); string_free(n); return key; error: string_burn(e); string_free(e); string_burn(n); string_free(n); publickey_free(key); return NULL; }
static int dh_handshake_server(SSH_SESSION *session) { STRING *e; STRING *f; STRING *pubkey; STRING *sign; PUBLIC_KEY *pub; PRIVATE_KEY *prv; if (packet_wait(session, SSH2_MSG_KEXDH_INIT, 1) != SSH_OK) { return -1; } e = buffer_get_ssh_string(session->in_buffer); if (e == NULL) { ssh_set_error(session, SSH_FATAL, "No e number in client request"); return -1; } if (dh_import_e(session, e) < 0) { ssh_set_error(session, SSH_FATAL, "Cannot import e number"); string_free(e); return -1; } string_free(e); 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; } switch(session->hostkeys){ case TYPE_DSS: prv = session->dsa_key; break; case TYPE_RSA: prv = session->rsa_key; break; default: prv = NULL; } pub = publickey_from_privatekey(prv); if (pub == NULL) { ssh_set_error(session, SSH_FATAL, "Could not get the public key from the private key"); string_free(f); return -1; } pubkey = publickey_to_string(pub); publickey_free(pub); if (pubkey == NULL) { ssh_set_error(session, SSH_FATAL, "Not enough space"); string_free(f); return -1; } dh_import_pubkey(session, pubkey); if (dh_build_k(session) < 0) { ssh_set_error(session, SSH_FATAL, "Could not import the public key"); string_free(f); return -1; } if (make_sessionid(session) != SSH_OK) { ssh_set_error(session, SSH_FATAL, "Could not create a session id"); string_free(f); return -1; } sign = ssh_sign_session_id(session, prv); if (sign == NULL) { ssh_set_error(session, SSH_FATAL, "Could not sign the session id"); string_free(f); return -1; } /* Free private keys as they should not be readable after this point */ if (session->rsa_key) { privatekey_free(session->rsa_key); session->rsa_key = NULL; } if (session->dsa_key) { privatekey_free(session->dsa_key); session->dsa_key = NULL; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY) < 0 || buffer_add_ssh_string(session->out_buffer, pubkey) < 0 || buffer_add_ssh_string(session->out_buffer, f) < 0 || buffer_add_ssh_string(session->out_buffer, sign) < 0) { ssh_set_error(session, SSH_FATAL, "Not enough space"); buffer_free(session->out_buffer); string_free(f); string_free(sign); return -1; } string_free(f); string_free(sign); if (packet_send(session) != SSH_OK) { return -1; } if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) { buffer_free(session->out_buffer); return -1; } if (packet_send(session) != SSH_OK) { return -1; } ssh_log(session, SSH_LOG_PACKET, "SSH_MSG_NEWKEYS sent"); if (packet_wait(session, SSH2_MSG_NEWKEYS, 1) != SSH_OK) { return -1; } ssh_log(session, SSH_LOG_PACKET, "Got SSH_MSG_NEWKEYS"); if (generate_session_keys(session) < 0) { return -1; } /* * Once we got SSH2_MSG_NEWKEYS we can switch next_crypto and * current_crypto */ if (session->current_crypto) { crypto_free(session->current_crypto); } /* FIXME TODO later, include a function to change keys */ session->current_crypto = session->next_crypto; session->next_crypto = crypto_new(); if (session->next_crypto == NULL) { return -1; } return 0; }
/** * @brief Tries to automaticaly authenticate with public key and "none" * * It may fail, for instance it doesn't ask for a password and uses a default * asker for passphrases (in case the private key is encrypted). * * @param session The ssh session to authenticate with. * * @param passphrase Use this passphrase to unlock the privatekey. Use NULL * if you don't want to use a passphrase or the user * should be asked. * * @returns SSH_AUTH_ERROR: A serious error happened\n * SSH_AUTH_DENIED: Authentication failed: use another method\n * SSH_AUTH_PARTIAL: You've been partially authenticated, you still * have to use another method\n * SSH_AUTH_SUCCESS: Authentication success * * @see ssh_userauth_kbdint() * @see ssh_userauth_password() */ int ssh_userauth_autopubkey(ssh_session session, const char *passphrase) { struct ssh_iterator *it; ssh_private_key privkey; ssh_public_key pubkey; ssh_string pubkey_string; int type = 0; int rc; enter_function(); /* Always test none authentication */ rc = ssh_userauth_none(session, NULL); if (rc == SSH_AUTH_ERROR || rc == SSH_AUTH_SUCCESS) { leave_function(); return rc; } /* 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 (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", privkey_file); 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(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(privkey_file); publickey_free(pubkey); continue; } ssh_log(session, SSH_LOG_RARE, "Public key accepted"); /* pubkey accepted by server ! */ rc = ssh_userauth_agent_pubkey(session, NULL, pubkey); if (rc == SSH_AUTH_ERROR) { SAFE_FREE(privkey_file); publickey_free(pubkey); leave_function(); return rc; } else if (rc != SSH_AUTH_SUCCESS) { ssh_log(session, SSH_LOG_RARE, "Server accepted public key but refused the signature ;" " It might be a bug of libssh"); SAFE_FREE(privkey_file); publickey_free(pubkey); continue; } /* auth success */ ssh_log(session, SSH_LOG_PROTOCOL, "Authentication using %s success", privkey_file); SAFE_FREE(privkey_file); publickey_free(pubkey); leave_function(); return SSH_AUTH_SUCCESS; } /* if pubkey */ SAFE_FREE(privkey_file); publickey_free(pubkey); } /* for each privkey */ } /* if agent is running */ #endif for (it = ssh_list_get_iterator(session->identity); it != NULL; it = it->next) { const char *privkey_file = it->data; int privkey_open = 0; privkey = NULL; 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; 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); leave_function(); return SSH_AUTH_ERROR; } privkey_open = 1; pubkey = publickey_from_privatekey(privkey); if (pubkey == NULL) { 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) { ssh_set_error_oom(session); leave_function(); return SSH_AUTH_ERROR; } len = strlen(privkey_file) + 5; publickey_file = malloc(len); if (publickey_file == NULL) { 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) { continue; } rc = ssh_userauth_offer_pubkey(session, NULL, type, pubkey_string); if (rc == SSH_AUTH_ERROR){ 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_string); continue; } } /* Public key accepted by server! */ 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); string_free(pubkey_string); continue; /* continue the loop with other pubkey */ } } rc = ssh_userauth_pubkey(session, NULL, pubkey_string, privkey); if (rc == SSH_AUTH_ERROR) { string_free(pubkey_string); privatekey_free(privkey); leave_function(); return rc; } else { if (rc != SSH_AUTH_SUCCESS){ ssh_log(session, SSH_LOG_FUNCTIONS, "The server accepted the public key but refused the signature"); string_free(pubkey_string); privatekey_free(privkey); continue; } } /* auth success */ ssh_log(session, SSH_LOG_PROTOCOL, "Successfully authenticated using %s", privkey_file); string_free(pubkey_string); privatekey_free(privkey); leave_function(); return SSH_AUTH_SUCCESS; } /* at this point, pubkey is NULL and so is privkeyfile */ ssh_log(session, SSH_LOG_FUNCTIONS, "Tried every public key, none matched"); ssh_set_error(session,SSH_NO_ERROR,"No public key matched"); leave_function(); return SSH_AUTH_DENIED; }
static int dh_handshake_server(SSH_SESSION *session){ STRING *e,*f,*pubkey,*sign; PUBLIC_KEY *pub; PRIVATE_KEY *prv; BUFFER *buf=buffer_new(); if(packet_wait(session, SSH2_MSG_KEXDH_INIT)) // FIXME BLOCKING return -1; e=buffer_get_ssh_string(session->in_buffer); if(!e){ ssh_set_error(session,SSH_FATAL,"No e number in client request"); return -1; } dh_import_e(session,e); dh_generate_y(session); dh_generate_f(session); f=dh_get_f(session); switch(session->hostkeys){ case TYPE_DSS: prv=session->dsa_key; break; case TYPE_RSA: prv=session->rsa_key; break; default: prv=NULL; } pub=publickey_from_privatekey(prv); pubkey=publickey_to_string(pub); publickey_free(pub); dh_import_pubkey(session,pubkey); dh_build_k(session); make_sessionid(session); sign=ssh_sign_session_id(session,prv); buffer_free(buf); /* free private keys as they should not be readable past this point */ if(session->rsa_key){ private_key_free(session->rsa_key); session->rsa_key=NULL; } if(session->dsa_key){ private_key_free(session->dsa_key); session->dsa_key=NULL; } buffer_add_u8(session->out_buffer,SSH2_MSG_KEXDH_REPLY); buffer_add_ssh_string(session->out_buffer,pubkey); buffer_add_ssh_string(session->out_buffer,f); buffer_add_ssh_string(session->out_buffer,sign); free(sign); packet_send(session); free(f); packet_clear_out(session); buffer_add_u8(session->out_buffer,SSH2_MSG_NEWKEYS); packet_send(session); ssh_say(2,"SSH_MSG_NEWKEYS sent\n"); packet_wait(session,SSH2_MSG_NEWKEYS);// FIXME BLOCKING ssh_say(2,"Got SSH_MSG_NEWKEYS\n"); generate_session_keys(session); /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */ if(session->current_crypto) crypto_free(session->current_crypto); /* XXX later, include a function to change keys */ session->current_crypto=session->next_crypto; session->next_crypto=crypto_new(); return 0; }