diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 126 |
1 files changed, 89 insertions, 37 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index d29f630f2..da1bd3847 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.230 2015/12/04 00:24:55 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.231 2015/12/04 16:41:28 markus Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -157,14 +157,16 @@ void | |||
157 | ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | 157 | ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) |
158 | { | 158 | { |
159 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; | 159 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; |
160 | char *s; | ||
160 | struct kex *kex; | 161 | struct kex *kex; |
161 | int r; | 162 | int r; |
162 | 163 | ||
163 | xxx_host = host; | 164 | xxx_host = host; |
164 | xxx_hostaddr = hostaddr; | 165 | xxx_hostaddr = hostaddr; |
165 | 166 | ||
166 | myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( | 167 | if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) |
167 | options.kex_algorithms); | 168 | fatal("%s: kex_names_cat", __func__); |
169 | myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s); | ||
168 | myproposal[PROPOSAL_ENC_ALGS_CTOS] = | 170 | myproposal[PROPOSAL_ENC_ALGS_CTOS] = |
169 | compat_cipher_proposal(options.ciphers); | 171 | compat_cipher_proposal(options.ciphers); |
170 | myproposal[PROPOSAL_ENC_ALGS_STOC] = | 172 | myproposal[PROPOSAL_ENC_ALGS_STOC] = |
@@ -221,6 +223,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | |||
221 | debug("Roaming not allowed by server"); | 223 | debug("Roaming not allowed by server"); |
222 | options.use_roaming = 0; | 224 | options.use_roaming = 0; |
223 | } | 225 | } |
226 | /* remove ext-info from the KEX proposals for rekeying */ | ||
227 | myproposal[PROPOSAL_KEX_ALGS] = | ||
228 | compat_kex_proposal(options.kex_algorithms); | ||
229 | if ((r = kex_prop2buf(kex->my, myproposal)) != 0) | ||
230 | fatal("kex_prop2buf: %s", ssh_err(r)); | ||
224 | 231 | ||
225 | session_id2 = kex->session_id; | 232 | session_id2 = kex->session_id; |
226 | session_id2_len = kex->session_id_len; | 233 | session_id2_len = kex->session_id_len; |
@@ -284,6 +291,8 @@ struct cauthmethod { | |||
284 | int *batch_flag; /* flag in option struct that disables method */ | 291 | int *batch_flag; /* flag in option struct that disables method */ |
285 | }; | 292 | }; |
286 | 293 | ||
294 | int input_userauth_service_accept(int, u_int32_t, void *); | ||
295 | int input_userauth_ext_info(int, u_int32_t, void *); | ||
287 | int input_userauth_success(int, u_int32_t, void *); | 296 | int input_userauth_success(int, u_int32_t, void *); |
288 | int input_userauth_success_unexpected(int, u_int32_t, void *); | 297 | int input_userauth_success_unexpected(int, u_int32_t, void *); |
289 | int input_userauth_failure(int, u_int32_t, void *); | 298 | int input_userauth_failure(int, u_int32_t, void *); |
@@ -359,30 +368,12 @@ void | |||
359 | ssh_userauth2(const char *local_user, const char *server_user, char *host, | 368 | ssh_userauth2(const char *local_user, const char *server_user, char *host, |
360 | Sensitive *sensitive) | 369 | Sensitive *sensitive) |
361 | { | 370 | { |
371 | struct ssh *ssh = active_state; | ||
362 | Authctxt authctxt; | 372 | Authctxt authctxt; |
363 | int type; | 373 | int r; |
364 | 374 | ||
365 | if (options.challenge_response_authentication) | 375 | if (options.challenge_response_authentication) |
366 | options.kbd_interactive_authentication = 1; | 376 | options.kbd_interactive_authentication = 1; |
367 | |||
368 | packet_start(SSH2_MSG_SERVICE_REQUEST); | ||
369 | packet_put_cstring("ssh-userauth"); | ||
370 | packet_send(); | ||
371 | debug("SSH2_MSG_SERVICE_REQUEST sent"); | ||
372 | packet_write_wait(); | ||
373 | type = packet_read(); | ||
374 | if (type != SSH2_MSG_SERVICE_ACCEPT) | ||
375 | fatal("Server denied authentication request: %d", type); | ||
376 | if (packet_remaining() > 0) { | ||
377 | char *reply = packet_get_string(NULL); | ||
378 | debug2("service_accept: %s", reply); | ||
379 | free(reply); | ||
380 | } else { | ||
381 | debug2("buggy server: service_accept w/o service"); | ||
382 | } | ||
383 | packet_check_eom(); | ||
384 | debug("SSH2_MSG_SERVICE_ACCEPT received"); | ||
385 | |||
386 | if (options.preferred_authentications == NULL) | 377 | if (options.preferred_authentications == NULL) |
387 | options.preferred_authentications = authmethods_get(); | 378 | options.preferred_authentications = authmethods_get(); |
388 | 379 | ||
@@ -404,21 +395,63 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, | |||
404 | if (authctxt.method == NULL) | 395 | if (authctxt.method == NULL) |
405 | fatal("ssh_userauth2: internal error: cannot send userauth none request"); | 396 | fatal("ssh_userauth2: internal error: cannot send userauth none request"); |
406 | 397 | ||
407 | /* initial userauth request */ | 398 | if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 || |
408 | userauth_none(&authctxt); | 399 | (r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 || |
400 | (r = sshpkt_send(ssh)) != 0) | ||
401 | fatal("%s: %s", __func__, ssh_err(r)); | ||
409 | 402 | ||
410 | dispatch_init(&input_userauth_error); | 403 | ssh_dispatch_init(ssh, &input_userauth_error); |
411 | dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); | 404 | ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info); |
412 | dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); | 405 | ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept); |
413 | dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); | 406 | ssh_dispatch_run(ssh, DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ |
414 | dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ | ||
415 | 407 | ||
416 | pubkey_cleanup(&authctxt); | 408 | pubkey_cleanup(&authctxt); |
417 | dispatch_range(SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); | 409 | ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_MIN, SSH2_MSG_USERAUTH_MAX, NULL); |
418 | 410 | ||
419 | debug("Authentication succeeded (%s).", authctxt.method->name); | 411 | debug("Authentication succeeded (%s).", authctxt.method->name); |
420 | } | 412 | } |
421 | 413 | ||
414 | /* ARGSUSED */ | ||
415 | int | ||
416 | input_userauth_service_accept(int type, u_int32_t seqnr, void *ctxt) | ||
417 | { | ||
418 | Authctxt *authctxt = ctxt; | ||
419 | struct ssh *ssh = active_state; | ||
420 | int r; | ||
421 | |||
422 | if (ssh_packet_remaining(ssh) > 0) { | ||
423 | char *reply; | ||
424 | |||
425 | if ((r = sshpkt_get_cstring(ssh, &reply, NULL)) != 0) | ||
426 | goto out; | ||
427 | debug2("service_accept: %s", reply); | ||
428 | free(reply); | ||
429 | } else { | ||
430 | debug2("buggy server: service_accept w/o service"); | ||
431 | } | ||
432 | if ((r = sshpkt_get_end(ssh)) != 0) | ||
433 | goto out; | ||
434 | debug("SSH2_MSG_SERVICE_ACCEPT received"); | ||
435 | |||
436 | /* initial userauth request */ | ||
437 | userauth_none(authctxt); | ||
438 | |||
439 | ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_error); | ||
440 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success); | ||
441 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure); | ||
442 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); | ||
443 | r = 0; | ||
444 | out: | ||
445 | return r; | ||
446 | } | ||
447 | |||
448 | /* ARGSUSED */ | ||
449 | int | ||
450 | input_userauth_ext_info(int type, u_int32_t seqnr, void *ctxt) | ||
451 | { | ||
452 | return kex_input_ext_info(type, seqnr, active_state); | ||
453 | } | ||
454 | |||
422 | void | 455 | void |
423 | userauth(Authctxt *authctxt, char *authlist) | 456 | userauth(Authctxt *authctxt, char *authlist) |
424 | { | 457 | { |
@@ -970,29 +1003,48 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, void *ctxt) | |||
970 | return 0; | 1003 | return 0; |
971 | } | 1004 | } |
972 | 1005 | ||
1006 | static const char * | ||
1007 | identity_sign_encode(struct identity *id) | ||
1008 | { | ||
1009 | struct ssh *ssh = active_state; | ||
1010 | |||
1011 | if (id->key->type == KEY_RSA) { | ||
1012 | switch (ssh->kex->rsa_sha2) { | ||
1013 | case 256: | ||
1014 | return "rsa-sha2-256"; | ||
1015 | case 512: | ||
1016 | return "rsa-sha2-512"; | ||
1017 | } | ||
1018 | } | ||
1019 | return key_ssh_name(id->key); | ||
1020 | } | ||
1021 | |||
973 | static int | 1022 | static int |
974 | identity_sign(struct identity *id, u_char **sigp, size_t *lenp, | 1023 | identity_sign(struct identity *id, u_char **sigp, size_t *lenp, |
975 | const u_char *data, size_t datalen, u_int compat) | 1024 | const u_char *data, size_t datalen, u_int compat) |
976 | { | 1025 | { |
977 | Key *prv; | 1026 | Key *prv; |
978 | int ret; | 1027 | int ret; |
1028 | const char *alg; | ||
1029 | |||
1030 | alg = identity_sign_encode(id); | ||
979 | 1031 | ||
980 | /* the agent supports this key */ | 1032 | /* the agent supports this key */ |
981 | if (id->agent_fd != -1) | 1033 | if (id->agent_fd != -1) |
982 | return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, | 1034 | return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, |
983 | data, datalen, compat); | 1035 | data, datalen, alg, compat); |
984 | 1036 | ||
985 | /* | 1037 | /* |
986 | * we have already loaded the private key or | 1038 | * we have already loaded the private key or |
987 | * the private key is stored in external hardware | 1039 | * the private key is stored in external hardware |
988 | */ | 1040 | */ |
989 | if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)) | 1041 | if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT)) |
990 | return (sshkey_sign(id->key, sigp, lenp, data, datalen, | 1042 | return (sshkey_sign(id->key, sigp, lenp, data, datalen, alg, |
991 | compat)); | 1043 | compat)); |
992 | /* load the private key from the file */ | 1044 | /* load the private key from the file */ |
993 | if ((prv = load_identity_file(id)) == NULL) | 1045 | if ((prv = load_identity_file(id)) == NULL) |
994 | return (-1); /* XXX return decent error code */ | 1046 | return (-1); /* XXX return decent error code */ |
995 | ret = sshkey_sign(prv, sigp, lenp, data, datalen, compat); | 1047 | ret = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat); |
996 | sshkey_free(prv); | 1048 | sshkey_free(prv); |
997 | return (ret); | 1049 | return (ret); |
998 | } | 1050 | } |
@@ -1039,7 +1091,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | |||
1039 | } else { | 1091 | } else { |
1040 | buffer_put_cstring(&b, authctxt->method->name); | 1092 | buffer_put_cstring(&b, authctxt->method->name); |
1041 | buffer_put_char(&b, have_sig); | 1093 | buffer_put_char(&b, have_sig); |
1042 | buffer_put_cstring(&b, key_ssh_name(id->key)); | 1094 | buffer_put_cstring(&b, identity_sign_encode(id)); |
1043 | } | 1095 | } |
1044 | buffer_put_string(&b, blob, bloblen); | 1096 | buffer_put_string(&b, blob, bloblen); |
1045 | 1097 | ||
@@ -1139,7 +1191,7 @@ send_pubkey_test(Authctxt *authctxt, Identity *id) | |||
1139 | packet_put_cstring(authctxt->method->name); | 1191 | packet_put_cstring(authctxt->method->name); |
1140 | packet_put_char(have_sig); | 1192 | packet_put_char(have_sig); |
1141 | if (!(datafellows & SSH_BUG_PKAUTH)) | 1193 | if (!(datafellows & SSH_BUG_PKAUTH)) |
1142 | packet_put_cstring(key_ssh_name(id->key)); | 1194 | packet_put_cstring(identity_sign_encode(id)); |
1143 | packet_put_string(blob, bloblen); | 1195 | packet_put_string(blob, bloblen); |
1144 | free(blob); | 1196 | free(blob); |
1145 | packet_send(); | 1197 | packet_send(); |
@@ -1743,7 +1795,7 @@ userauth_hostbased(Authctxt *authctxt) | |||
1743 | r = ssh_keysign(private, &sig, &siglen, | 1795 | r = ssh_keysign(private, &sig, &siglen, |
1744 | sshbuf_ptr(b), sshbuf_len(b)); | 1796 | sshbuf_ptr(b), sshbuf_len(b)); |
1745 | else if ((r = sshkey_sign(private, &sig, &siglen, | 1797 | else if ((r = sshkey_sign(private, &sig, &siglen, |
1746 | sshbuf_ptr(b), sshbuf_len(b), datafellows)) != 0) | 1798 | sshbuf_ptr(b), sshbuf_len(b), NULL, datafellows)) != 0) |
1747 | debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); | 1799 | debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); |
1748 | if (r != 0) { | 1800 | if (r != 0) { |
1749 | error("sign using hostkey %s %s failed", | 1801 | error("sign using hostkey %s %s failed", |