summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/serverloop.c')
-rw-r--r--crypto/openssh/serverloop.c122
1 files changed, 104 insertions, 18 deletions
diff --git a/crypto/openssh/serverloop.c b/crypto/openssh/serverloop.c
index a24a06f..f45baa5 100644
--- a/crypto/openssh/serverloop.c
+++ b/crypto/openssh/serverloop.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.172 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: serverloop.c,v 1.178 2015/02/20 22:17:21 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -38,8 +38,8 @@
#include "includes.h"
__RCSID("$FreeBSD$");
+#include <sys/param.h> /* MIN MAX */
#include <sys/types.h>
-#include <sys/param.h>
#include <sys/wait.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_TIME_H
@@ -80,11 +80,11 @@ __RCSID("$FreeBSD$");
#include "auth-options.h"
#include "serverloop.h"
#include "roaming.h"
+#include "ssherr.h"
extern ServerOptions options;
/* XXX */
-extern Kex *xxx_kex;
extern Authctxt *the_authctxt;
extern int use_privsep;
@@ -546,7 +546,7 @@ drain_output(void)
static void
process_buffered_input_packets(void)
{
- dispatch_run(DISPATCH_NONBLOCK, NULL, compat20 ? xxx_kex : NULL);
+ dispatch_run(DISPATCH_NONBLOCK, NULL, active_state);
}
/*
@@ -852,7 +852,7 @@ server_loop2(Authctxt *authctxt)
for (;;) {
process_buffered_input_packets();
- rekeying = (xxx_kex != NULL && !xxx_kex->done);
+ rekeying = (active_state->kex != NULL && !active_state->kex->done);
if (!rekeying && packet_not_very_much_data_to_write())
channel_output_poll();
@@ -875,8 +875,8 @@ server_loop2(Authctxt *authctxt)
channel_after_select(readset, writeset);
if (packet_need_rekeying()) {
debug("need rekeying");
- xxx_kex->done = 0;
- kex_send_kexinit(xxx_kex);
+ active_state->kex->done = 0;
+ kex_send_kexinit(active_state);
}
}
process_input(readset);
@@ -896,7 +896,7 @@ server_loop2(Authctxt *authctxt)
session_destroy_all(NULL);
}
-static void
+static int
server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
{
debug("Got %d/%u for keepalive", type, seq);
@@ -906,9 +906,10 @@ server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
* the bogus CHANNEL_REQUEST we send for keepalives.
*/
packet_set_alive_timeouts(0);
+ return 0;
}
-static void
+static int
server_input_stdin_data(int type, u_int32_t seq, void *ctxt)
{
char *data;
@@ -917,15 +918,16 @@ server_input_stdin_data(int type, u_int32_t seq, void *ctxt)
/* Stdin data from the client. Append it to the buffer. */
/* Ignore any data if the client has closed stdin. */
if (fdin == -1)
- return;
+ return 0;
data = packet_get_string(&data_len);
packet_check_eom();
buffer_append(&stdin_buffer, data, data_len);
explicit_bzero(data, data_len);
free(data);
+ return 0;
}
-static void
+static int
server_input_eof(int type, u_int32_t seq, void *ctxt)
{
/*
@@ -936,9 +938,10 @@ server_input_eof(int type, u_int32_t seq, void *ctxt)
debug("EOF received for stdin.");
packet_check_eom();
stdin_eof = 1;
+ return 0;
}
-static void
+static int
server_input_window_size(int type, u_int32_t seq, void *ctxt)
{
u_int row = packet_get_int();
@@ -950,6 +953,7 @@ server_input_window_size(int type, u_int32_t seq, void *ctxt)
packet_check_eom();
if (fdin != -1)
pty_change_window_size(fdin, row, col, xpixel, ypixel);
+ return 0;
}
static Channel *
@@ -1094,7 +1098,7 @@ server_request_session(void)
return c;
}
-static void
+static int
server_input_channel_open(int type, u_int32_t seq, void *ctxt)
{
Channel *c = NULL;
@@ -1144,14 +1148,86 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
packet_send();
}
free(ctype);
+ return 0;
}
-static void
+static int
+server_input_hostkeys_prove(struct sshbuf **respp)
+{
+ struct ssh *ssh = active_state; /* XXX */
+ struct sshbuf *resp = NULL;
+ struct sshbuf *sigbuf = NULL;
+ struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
+ int r, ndx, success = 0;
+ const u_char *blob;
+ u_char *sig = 0;
+ size_t blen, slen;
+
+ if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+
+ while (ssh_packet_remaining(ssh) > 0) {
+ sshkey_free(key);
+ key = NULL;
+ if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 ||
+ (r = sshkey_from_blob(blob, blen, &key)) != 0) {
+ error("%s: couldn't parse key: %s",
+ __func__, ssh_err(r));
+ goto out;
+ }
+ /*
+ * Better check that this is actually one of our hostkeys
+ * before attempting to sign anything with it.
+ */
+ if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) {
+ error("%s: unknown host %s key",
+ __func__, sshkey_type(key));
+ goto out;
+ }
+ /*
+ * XXX refactor: make kex->sign just use an index rather
+ * than passing in public and private keys
+ */
+ if ((key_prv = get_hostkey_by_index(ndx)) == NULL &&
+ (key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) {
+ error("%s: can't retrieve hostkey %d", __func__, ndx);
+ goto out;
+ }
+ sshbuf_reset(sigbuf);
+ free(sig);
+ sig = NULL;
+ if ((r = sshbuf_put_cstring(sigbuf,
+ "hostkeys-prove-00@openssh.com")) != 0 ||
+ (r = sshbuf_put_string(sigbuf,
+ ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
+ (r = sshkey_puts(key, sigbuf)) != 0 ||
+ (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen,
+ sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), 0)) != 0 ||
+ (r = sshbuf_put_string(resp, sig, slen)) != 0) {
+ error("%s: couldn't prepare signature: %s",
+ __func__, ssh_err(r));
+ goto out;
+ }
+ }
+ /* Success */
+ *respp = resp;
+ resp = NULL; /* don't free it */
+ success = 1;
+ out:
+ free(sig);
+ sshbuf_free(resp);
+ sshbuf_free(sigbuf);
+ sshkey_free(key);
+ return success;
+}
+
+static int
server_input_global_request(int type, u_int32_t seq, void *ctxt)
{
char *rtype;
int want_reply;
- int success = 0, allocated_listen_port = 0;
+ int r, success = 0, allocated_listen_port = 0;
+ struct sshbuf *resp = NULL;
rtype = packet_get_string(NULL);
want_reply = packet_get_char();
@@ -1188,6 +1264,10 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
&allocated_listen_port, &options.fwd_opts);
}
free(fwd.listen_host);
+ if ((resp = sshbuf_new()) == NULL)
+ fatal("%s: sshbuf_new", __func__);
+ if ((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;
@@ -1231,19 +1311,24 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
} else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
no_more_sessions = 1;
success = 1;
+ } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) {
+ success = server_input_hostkeys_prove(&resp);
}
if (want_reply) {
packet_start(success ?
SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
- if (success && allocated_listen_port > 0)
- packet_put_int(allocated_listen_port);
+ if (success && resp != NULL)
+ ssh_packet_put_raw(active_state, sshbuf_ptr(resp),
+ sshbuf_len(resp));
packet_send();
packet_write_wait();
}
free(rtype);
+ sshbuf_free(resp);
+ return 0;
}
-static void
+static int
server_input_channel_req(int type, u_int32_t seq, void *ctxt)
{
Channel *c;
@@ -1273,6 +1358,7 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt)
packet_send();
}
free(rtype);
+ return 0;
}
static void
OpenPOWER on IntegriCloud