int kex_send_kexinit(struct ssh *ssh) { u_char *cookie; struct kex *kex = ssh->kex; int r; if (kex == NULL) return SSH_ERR_INTERNAL_ERROR; if (kex->flags & KEX_INIT_SENT) return 0; kex->done = 0; /* generate a random cookie */ if (sshbuf_len(kex->my) < KEX_COOKIE_LEN) return SSH_ERR_INVALID_FORMAT; if ((cookie = sshbuf_mutable_ptr(kex->my)) == NULL) return SSH_ERR_INTERNAL_ERROR; arc4random_buf(cookie, KEX_COOKIE_LEN); if ((r = sshpkt_start(ssh, SSH2_MSG_KEXINIT)) != 0) return r; if ((r = sshpkt_put(ssh, sshbuf_ptr(kex->my), sshbuf_len(kex->my))) != 0) return r; if ((r = sshpkt_send(ssh)) != 0) return r; debug("SSH2_MSG_KEXINIT sent"); kex->flags |= KEX_INIT_SENT; return 0; }
void ssh_packet_put_raw(struct ssh *ssh, const void *buf, u_int len) { int r; if ((r = sshpkt_put(ssh, buf, len)) != 0) fatal("%s: %s", __func__, ssh_err(r)); }
/* * Computes the proper response to a RSA challenge, and sends the response to * the server. */ static void respond_to_rsa_challenge(struct ssh *ssh, BIGNUM * challenge, RSA * prv) { u_char buf[32], response[16]; MD5_CTX md; int r, len; /* Decrypt the challenge using the private key. */ /* XXX think about Bleichenbacher, too */ if ((r = rsa_private_decrypt(challenge, challenge, prv)) != 0) { ssh_packet_disconnect(ssh, "%s: rsa_private_decrypt: %s", __func__, ssh_err(r)); } /* Compute the response. */ /* The response is MD5 of decrypted challenge plus session id. */ len = BN_num_bytes(challenge); if (len <= 0 || (u_int)len > sizeof(buf)) ssh_packet_disconnect(ssh, "respond_to_rsa_challenge: bad challenge length %d", len); memset(buf, 0, sizeof(buf)); BN_bn2bin(challenge, buf + sizeof(buf) - len); MD5_Init(&md); MD5_Update(&md, buf, 32); MD5_Update(&md, session_id, 16); MD5_Final(response, &md); debug("Sending response to host key RSA challenge."); /* Send the response back to the server. */ if ((r = sshpkt_start(ssh, SSH_CMSG_AUTH_RSA_RESPONSE)) != 0 || (r = sshpkt_put(ssh, &response, sizeof(response))) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); ssh_packet_write_wait(ssh); memset(buf, 0, sizeof(buf)); memset(response, 0, sizeof(response)); memset(&md, 0, sizeof(md)); }
/* * Checks if the user has an authentication agent, and if so, tries to * authenticate using the agent. */ static int try_agent_authentication(struct ssh *ssh) { int r, type, agent_fd, ret = 0; u_char response[16]; size_t i; BIGNUM *challenge; struct ssh_identitylist *idlist = NULL; /* Get connection to the agent. */ if ((r = ssh_get_authentication_socket(&agent_fd)) != 0) { if (r != SSH_ERR_AGENT_NOT_PRESENT) debug("%s: ssh_get_authentication_socket: %s", __func__, ssh_err(r)); return 0; } if ((challenge = BN_new()) == NULL) fatal("try_agent_authentication: BN_new failed"); /* Loop through identities served by the agent. */ if ((r = ssh_fetch_identitylist(agent_fd, 1, &idlist)) != 0) { if (r != SSH_ERR_AGENT_NO_IDENTITIES) debug("%s: ssh_fetch_identitylist: %s", __func__, ssh_err(r)); goto out; } for (i = 0; i < idlist->nkeys; i++) { /* Try this identity. */ debug("Trying RSA authentication via agent with '%.100s'", idlist->comments[i]); /* * Tell the server that we are willing to authenticate * using this key. */ if ((r = sshpkt_start(ssh, SSH_CMSG_AUTH_RSA)) != 0 || (r = sshpkt_put_bignum1(ssh, idlist->keys[i]->rsa->n)) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); ssh_packet_write_wait(ssh); /* Wait for server's response. */ type = ssh_packet_read(ssh); /* The server sends failure if it doesn't like our key or does not support RSA authentication. */ if (type == SSH_SMSG_FAILURE) { debug("Server refused our key."); continue; } /* Otherwise it should have sent a challenge. */ if (type != SSH_SMSG_AUTH_RSA_CHALLENGE) ssh_packet_disconnect(ssh, "Protocol error during RSA " "authentication: %d", type); if ((r = sshpkt_get_bignum1(ssh, challenge)) != 0 || (r = sshpkt_get_end(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); debug("Received RSA challenge from server."); /* Ask the agent to decrypt the challenge. */ if ((r = ssh_decrypt_challenge(agent_fd, idlist->keys[i], challenge, session_id, response)) != 0) { /* * The agent failed to authenticate this identifier * although it advertised it supports this. Just * return a wrong value. */ logit("Authentication agent failed to decrypt " "challenge: %s", ssh_err(r)); memset(response, 0, sizeof(response)); } debug("Sending response to RSA challenge."); /* Send the decrypted challenge back to the server. */ if ((r = sshpkt_start(ssh, SSH_CMSG_AUTH_RSA_RESPONSE)) != 0 || (r = sshpkt_put(ssh, &response, sizeof(response))) != 0 || (r = sshpkt_send(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); ssh_packet_write_wait(ssh); /* Wait for response from the server. */ type = ssh_packet_read(ssh); /* * The server returns success if it accepted the * authentication. */ if (type == SSH_SMSG_SUCCESS) { debug("RSA authentication accepted by server."); ret = 1; break; } else if (type != SSH_SMSG_FAILURE) ssh_packet_disconnect(ssh, "Protocol error waiting RSA auth " "response: %d", type); } if (ret != 1) debug("RSA authentication using agent refused."); out: ssh_free_identitylist(idlist); ssh_close_authentication_socket(agent_fd); BN_clear_free(challenge); return ret; }
static int server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) { char *rtype = NULL; u_char want_reply; int r, success = 0, allocated_listen_port = 0; struct sshbuf *resp = NULL; if ((r = sshpkt_get_cstring(ssh, &rtype, NULL)) != 0 || (r = sshpkt_get_u8(ssh, &want_reply)) != 0) goto out; debug("server_input_global_request: rtype %s want_reply %d", rtype, want_reply); /* -R style forwarding */ if (strcmp(rtype, "tcpip-forward") == 0) { struct authctxt *authctxt = ssh->authctxt; struct Forward fwd; if (authctxt->pw == NULL || !authctxt->valid) fatal("server_input_global_request: no/invalid user"); memset(&fwd, 0, sizeof(fwd)); if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &fwd.listen_port)) != 0) goto out; debug("server_input_global_request: tcpip-forward listen %s port %d", fwd.listen_host, fwd.listen_port); /* check permissions */ if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || no_port_forwarding_flag || (!want_reply && fwd.listen_port == 0) || (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED && authctxt->pw->pw_uid != 0)) { success = 0; ssh_packet_send_debug(ssh, "Server has disabled port forwarding."); } else { /* Start listening on the port */ success = channel_setup_remote_fwd_listener(ssh, &fwd, &allocated_listen_port, &options.fwd_opts); } free(fwd.listen_host); if ((resp = sshbuf_new()) == NULL) fatal("%s: sshbuf_new", __func__); if (allocated_listen_port != 0 && (r = sshbuf_put_u32(resp, allocated_listen_port)) != 0) fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r)); } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); if ((r = sshpkt_get_cstring(ssh, &fwd.listen_host, NULL)) != 0 || (r = sshpkt_get_u32(ssh, &fwd.listen_port)) != 0) goto out; debug("%s: cancel-tcpip-forward addr %s port %d", __func__, fwd.listen_host, fwd.listen_port); success = channel_cancel_rport_listener(&fwd); free(fwd.listen_host); } else if (strcmp(rtype, "*****@*****.**") == 0) { struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0) goto out; debug("server_input_global_request: streamlocal-forward listen path %s", fwd.listen_path); /* check permissions */ if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0 || no_port_forwarding_flag) { success = 0; ssh_packet_send_debug(ssh, "Server has disabled port forwarding."); } else { /* Start listening on the socket */ success = channel_setup_remote_fwd_listener(ssh, &fwd, NULL, &options.fwd_opts); } free(fwd.listen_path); } else if (strcmp(rtype, "*****@*****.**") == 0) { struct Forward fwd; memset(&fwd, 0, sizeof(fwd)); if ((r = sshpkt_get_cstring(ssh, &fwd.listen_path, NULL)) != 0) goto out; debug("%s: cancel-streamlocal-forward path %s", __func__, fwd.listen_path); success = channel_cancel_rport_listener(&fwd); free(fwd.listen_path); } else if (strcmp(rtype, "*****@*****.**") == 0) { no_more_sessions = 1; success = 1; } else if (strcmp(rtype, "*****@*****.**") == 0) { success = server_input_hostkeys_prove(&resp); } if (want_reply) { if ((r = sshpkt_start(ssh, success ? SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE)) != 0 || (success && resp != NULL && (r = sshpkt_put(ssh, sshbuf_ptr(resp), sshbuf_len(resp))) != 0) || (r = sshpkt_send(ssh)) != 0) goto out; ssh_packet_write_wait(ssh); } r = 0; out: free(rtype); sshbuf_free(resp); return r; }