summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2015-07-02 13:15:34 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2015-07-02 13:15:34 +0000
commitc1e0861503468de5ae00ed0e532f349ec78bec68 (patch)
tree14de9b5b2b4cbd1116ed28f9b7189c866585b230 /serverloop.c
parentc0bbca73c6f7f15d5401332151fc9f9755abaf8f (diff)
Notes
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c122
1 files changed, 104 insertions, 18 deletions
diff --git a/serverloop.c b/serverloop.c
index e92f9e27bd3a..306ac36be670 100644
--- a/serverloop.c
+++ b/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
@@ -37,8 +37,8 @@
#include "includes.h"
+#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
@@ -79,11 +79,11 @@
#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;
@@ -545,7 +545,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);
}
/*
@@ -851,7 +851,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();
@@ -874,8 +874,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);
@@ -895,7 +895,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);
@@ -905,9 +905,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;
@@ -916,15 +917,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)
{
/*
@@ -935,9 +937,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();
@@ -949,6 +952,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 *
@@ -1093,7 +1097,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;
@@ -1143,14 +1147,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();
@@ -1187,6 +1263,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;
@@ -1230,19 +1310,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;
@@ -1272,6 +1357,7 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt)
packet_send();
}
free(rtype);
+ return 0;
}
static void