summaryrefslogtreecommitdiff
path: root/serverloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'serverloop.c')
-rw-r--r--serverloop.c88
1 files changed, 84 insertions, 4 deletions
diff --git a/serverloop.c b/serverloop.c
index 48bb3f631..5633ceb41 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: serverloop.c,v 1.176 2015/01/20 23:14:00 deraadt Exp $ */ 1/* $OpenBSD: serverloop.c,v 1.177 2015/02/16 22:13:32 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -79,6 +79,7 @@
79#include "auth-options.h" 79#include "auth-options.h"
80#include "serverloop.h" 80#include "serverloop.h"
81#include "roaming.h" 81#include "roaming.h"
82#include "ssherr.h"
82 83
83extern ServerOptions options; 84extern ServerOptions options;
84 85
@@ -1150,11 +1151,82 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
1150} 1151}
1151 1152
1152static int 1153static int
1154server_input_hostkeys_prove(struct sshbuf **respp)
1155{
1156 struct ssh *ssh = active_state; /* XXX */
1157 struct sshbuf *resp = NULL;
1158 struct sshbuf *sigbuf = NULL;
1159 struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL;
1160 int r, ndx, success = 0;
1161 const u_char *blob;
1162 u_char *sig = 0;
1163 size_t blen, slen;
1164
1165 if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL)
1166 fatal("%s: sshbuf_new", __func__);
1167
1168 while (ssh_packet_remaining(ssh) > 0) {
1169 sshkey_free(key);
1170 key = NULL;
1171 if ((r = sshpkt_get_string_direct(ssh, &blob, &blen)) != 0 ||
1172 (r = sshkey_from_blob(blob, blen, &key)) != 0) {
1173 error("%s: couldn't parse key: %s",
1174 __func__, ssh_err(r));
1175 goto out;
1176 }
1177 /*
1178 * Better check that this is actually one of our hostkeys
1179 * before attempting to sign anything with it.
1180 */
1181 if ((ndx = ssh->kex->host_key_index(key, 1, ssh)) == -1) {
1182 error("%s: unknown host %s key",
1183 __func__, sshkey_type(key));
1184 goto out;
1185 }
1186 /*
1187 * XXX refactor: make kex->sign just use an index rather
1188 * than passing in public and private keys
1189 */
1190 if ((key_prv = get_hostkey_by_index(ndx)) == NULL &&
1191 (key_pub = get_hostkey_public_by_index(ndx, ssh)) == NULL) {
1192 error("%s: can't retrieve hostkey %d", __func__, ndx);
1193 goto out;
1194 }
1195 sshbuf_reset(sigbuf);
1196 free(sig);
1197 sig = NULL;
1198 if ((r = sshbuf_put_string(sigbuf,
1199 ssh->kex->session_id, ssh->kex->session_id_len)) != 0 ||
1200 (r = sshbuf_put_cstring(sigbuf,
1201 "hostkeys-prove@openssh.com")) != 0 ||
1202 (r = sshkey_puts(key, sigbuf)) != 0 ||
1203 (r = ssh->kex->sign(key_prv, key_pub, &sig, &slen,
1204 sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), 0)) != 0 ||
1205 (r = sshbuf_put_string(resp, sig, slen)) != 0) {
1206 error("%s: couldn't prepare signature: %s",
1207 __func__, ssh_err(r));
1208 goto out;
1209 }
1210 }
1211 /* Success */
1212 *respp = resp;
1213 resp = NULL; /* don't free it */
1214 success = 1;
1215 out:
1216 free(sig);
1217 sshbuf_free(resp);
1218 sshbuf_free(sigbuf);
1219 sshkey_free(key);
1220 return success;
1221}
1222
1223static int
1153server_input_global_request(int type, u_int32_t seq, void *ctxt) 1224server_input_global_request(int type, u_int32_t seq, void *ctxt)
1154{ 1225{
1155 char *rtype; 1226 char *rtype;
1156 int want_reply; 1227 int want_reply;
1157 int success = 0, allocated_listen_port = 0; 1228 int r, success = 0, allocated_listen_port = 0;
1229 struct sshbuf *resp = NULL;
1158 1230
1159 rtype = packet_get_string(NULL); 1231 rtype = packet_get_string(NULL);
1160 want_reply = packet_get_char(); 1232 want_reply = packet_get_char();
@@ -1191,6 +1263,10 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
1191 &allocated_listen_port, &options.fwd_opts); 1263 &allocated_listen_port, &options.fwd_opts);
1192 } 1264 }
1193 free(fwd.listen_host); 1265 free(fwd.listen_host);
1266 if ((resp = sshbuf_new()) == NULL)
1267 fatal("%s: sshbuf_new", __func__);
1268 if ((r = sshbuf_put_u32(resp, allocated_listen_port)) != 0)
1269 fatal("%s: sshbuf_put_u32: %s", __func__, ssh_err(r));
1194 } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { 1270 } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
1195 struct Forward fwd; 1271 struct Forward fwd;
1196 1272
@@ -1234,16 +1310,20 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
1234 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { 1310 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
1235 no_more_sessions = 1; 1311 no_more_sessions = 1;
1236 success = 1; 1312 success = 1;
1313 } else if (strcmp(rtype, "hostkeys-prove@openssh.com") == 0) {
1314 success = server_input_hostkeys_prove(&resp);
1237 } 1315 }
1238 if (want_reply) { 1316 if (want_reply) {
1239 packet_start(success ? 1317 packet_start(success ?
1240 SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); 1318 SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE);
1241 if (success && allocated_listen_port > 0) 1319 if (success && resp != NULL)
1242 packet_put_int(allocated_listen_port); 1320 ssh_packet_put_raw(active_state, sshbuf_ptr(resp),
1321 sshbuf_len(resp));
1243 packet_send(); 1322 packet_send();
1244 packet_write_wait(); 1323 packet_write_wait();
1245 } 1324 }
1246 free(rtype); 1325 free(rtype);
1326 sshbuf_free(resp);
1247 return 0; 1327 return 0;
1248} 1328}
1249 1329