diff options
Diffstat (limited to 'serverloop.c')
-rw-r--r-- | serverloop.c | 88 |
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 | ||
83 | extern ServerOptions options; | 84 | extern ServerOptions options; |
84 | 85 | ||
@@ -1150,11 +1151,82 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
1150 | } | 1151 | } |
1151 | 1152 | ||
1152 | static int | 1153 | static int |
1154 | server_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 | |||
1223 | static int | ||
1153 | server_input_global_request(int type, u_int32_t seq, void *ctxt) | 1224 | server_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 | ||