summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c172
1 files changed, 124 insertions, 48 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 87fa70a40..af00fb30c 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.308 2019/08/05 11:50:33 dtucker Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.320 2020/02/06 22:48:23 djm 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.
@@ -36,9 +36,9 @@
36#include <netdb.h> 36#include <netdb.h>
37#include <pwd.h> 37#include <pwd.h>
38#include <signal.h> 38#include <signal.h>
39#include <stdarg.h>
40#include <stdio.h> 39#include <stdio.h>
41#include <string.h> 40#include <string.h>
41#include <stdarg.h>
42#include <unistd.h> 42#include <unistd.h>
43#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) 43#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
44#include <vis.h> 44#include <vis.h>
@@ -72,6 +72,8 @@
72#include "hostfile.h" 72#include "hostfile.h"
73#include "ssherr.h" 73#include "ssherr.h"
74#include "utf8.h" 74#include "utf8.h"
75#include "ssh-sk.h"
76#include "sk-api.h"
75 77
76#ifdef GSSAPI 78#ifdef GSSAPI
77#include "ssh-gss.h" 79#include "ssh-gss.h"
@@ -117,7 +119,7 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
117 for (i = 0; i < options.num_system_hostfiles; i++) 119 for (i = 0; i < options.num_system_hostfiles; i++)
118 load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]); 120 load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
119 121
120 oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG); 122 oavail = avail = xstrdup(options.hostkeyalgorithms);
121 maxlen = strlen(avail) + 1; 123 maxlen = strlen(avail) + 1;
122 first = xmalloc(maxlen); 124 first = xmalloc(maxlen);
123 last = xmalloc(maxlen); 125 last = xmalloc(maxlen);
@@ -159,11 +161,28 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
159{ 161{
160 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 162 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
161 char *s, *all_key; 163 char *s, *all_key;
162 int r; 164 int r, use_known_hosts_order = 0;
163 165
164 xxx_host = host; 166 xxx_host = host;
165 xxx_hostaddr = hostaddr; 167 xxx_hostaddr = hostaddr;
166 168
169 /*
170 * If the user has not specified HostkeyAlgorithms, or has only
171 * appended or removed algorithms from that list then prefer algorithms
172 * that are in the list that are supported by known_hosts keys.
173 */
174 if (options.hostkeyalgorithms == NULL ||
175 options.hostkeyalgorithms[0] == '-' ||
176 options.hostkeyalgorithms[0] == '+')
177 use_known_hosts_order = 1;
178
179 /* Expand or fill in HostkeyAlgorithms */
180 all_key = sshkey_alg_list(0, 0, 1, ',');
181 if (kex_assemble_names(&options.hostkeyalgorithms,
182 kex_default_pk_alg(), all_key) != 0)
183 fatal("%s: kex_assemble_namelist", __func__);
184 free(all_key);
185
167 if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) 186 if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
168 fatal("%s: kex_names_cat", __func__); 187 fatal("%s: kex_names_cat", __func__);
169 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s); 188 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s);
@@ -172,25 +191,19 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
172 myproposal[PROPOSAL_ENC_ALGS_STOC] = 191 myproposal[PROPOSAL_ENC_ALGS_STOC] =
173 compat_cipher_proposal(options.ciphers); 192 compat_cipher_proposal(options.ciphers);
174 myproposal[PROPOSAL_COMP_ALGS_CTOS] = 193 myproposal[PROPOSAL_COMP_ALGS_CTOS] =
175 myproposal[PROPOSAL_COMP_ALGS_STOC] = options.compression ? 194 myproposal[PROPOSAL_COMP_ALGS_STOC] =
176 "zlib@openssh.com,zlib,none" : "none,zlib@openssh.com,zlib"; 195 (char *)compression_alg_list(options.compression);
177 myproposal[PROPOSAL_MAC_ALGS_CTOS] = 196 myproposal[PROPOSAL_MAC_ALGS_CTOS] =
178 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; 197 myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
179 if (options.hostkeyalgorithms != NULL) { 198 if (use_known_hosts_order) {
180 all_key = sshkey_alg_list(0, 0, 1, ','); 199 /* Query known_hosts and prefer algorithms that appear there */
181 if (kex_assemble_names(&options.hostkeyalgorithms,
182 KEX_DEFAULT_PK_ALG, all_key) != 0)
183 fatal("%s: kex_assemble_namelist", __func__);
184 free(all_key);
185 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
186 compat_pkalg_proposal(options.hostkeyalgorithms);
187 } else {
188 /* Enforce default */
189 options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG);
190 /* Prefer algorithms that we already have keys for */
191 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 200 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
192 compat_pkalg_proposal( 201 compat_pkalg_proposal(
193 order_hostkeyalgs(host, hostaddr, port)); 202 order_hostkeyalgs(host, hostaddr, port));
203 } else {
204 /* Use specified HostkeyAlgorithms exactly */
205 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
206 compat_pkalg_proposal(options.hostkeyalgorithms);
194 } 207 }
195 208
196 if (options.rekey_limit || options.rekey_interval) 209 if (options.rekey_limit || options.rekey_interval)
@@ -601,17 +614,23 @@ static char *
601format_identity(Identity *id) 614format_identity(Identity *id)
602{ 615{
603 char *fp = NULL, *ret = NULL; 616 char *fp = NULL, *ret = NULL;
617 const char *note = "";
604 618
605 if (id->key != NULL) { 619 if (id->key != NULL) {
606 fp = sshkey_fingerprint(id->key, options.fingerprint_hash, 620 fp = sshkey_fingerprint(id->key, options.fingerprint_hash,
607 SSH_FP_DEFAULT); 621 SSH_FP_DEFAULT);
608 } 622 }
623 if (id->key) {
624 if ((id->key->flags & SSHKEY_FLAG_EXT) != 0)
625 note = " token";
626 else if (sshkey_is_sk(id->key))
627 note = " authenticator";
628 }
609 xasprintf(&ret, "%s %s%s%s%s%s%s", 629 xasprintf(&ret, "%s %s%s%s%s%s%s",
610 id->filename, 630 id->filename,
611 id->key ? sshkey_type(id->key) : "", id->key ? " " : "", 631 id->key ? sshkey_type(id->key) : "", id->key ? " " : "",
612 fp ? fp : "", 632 fp ? fp : "",
613 id->userprovided ? " explicit" : "", 633 id->userprovided ? " explicit" : "", note,
614 (id->key && (id->key->flags & SSHKEY_FLAG_EXT)) ? " token" : "",
615 id->agent_fd != -1 ? " agent" : ""); 634 id->agent_fd != -1 ? " agent" : "");
616 free(fp); 635 free(fp);
617 return ret; 636 return ret;
@@ -1140,8 +1159,13 @@ static int
1140identity_sign(struct identity *id, u_char **sigp, size_t *lenp, 1159identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
1141 const u_char *data, size_t datalen, u_int compat, const char *alg) 1160 const u_char *data, size_t datalen, u_int compat, const char *alg)
1142{ 1161{
1143 struct sshkey *prv; 1162 struct sshkey *sign_key = NULL, *prv = NULL;
1144 int r; 1163 int r = SSH_ERR_INTERNAL_ERROR;
1164 struct notifier_ctx *notifier = NULL;
1165 char *fp = NULL;
1166
1167 *sigp = NULL;
1168 *lenp = 0;
1145 1169
1146 /* The agent supports this key. */ 1170 /* The agent supports this key. */
1147 if (id->key != NULL && id->agent_fd != -1) { 1171 if (id->key != NULL && id->agent_fd != -1) {
@@ -1155,27 +1179,47 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp,
1155 */ 1179 */
1156 if (id->key != NULL && 1180 if (id->key != NULL &&
1157 (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) { 1181 (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) {
1158 if ((r = sshkey_sign(id->key, sigp, lenp, data, datalen, 1182 sign_key = id->key;
1159 alg, compat)) != 0) 1183 } else {
1160 return r; 1184 /* Load the private key from the file. */
1161 /* 1185 if ((prv = load_identity_file(id)) == NULL)
1162 * PKCS#11 tokens may not support all signature algorithms, 1186 return SSH_ERR_KEY_NOT_FOUND;
1163 * so check what we get back. 1187 if (id->key != NULL && !sshkey_equal_public(prv, id->key)) {
1164 */ 1188 error("%s: private key %s contents do not match public",
1165 if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) 1189 __func__, id->filename);
1166 return r; 1190 r = SSH_ERR_KEY_NOT_FOUND;
1167 return 0; 1191 goto out;
1192 }
1193 sign_key = prv;
1194 if (sshkey_is_sk(sign_key) &&
1195 (sign_key->sk_flags & SSH_SK_USER_PRESENCE_REQD)) {
1196 /* XXX match batch mode should just skip these keys? */
1197 if ((fp = sshkey_fingerprint(sign_key,
1198 options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
1199 fatal("%s: sshkey_fingerprint", __func__);
1200 notifier = notify_start(options.batch_mode,
1201 "Confirm user presence for key %s %s",
1202 sshkey_type(sign_key), fp);
1203 free(fp);
1204 }
1168 } 1205 }
1169 1206 if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen,
1170 /* Load the private key from the file. */ 1207 alg, options.sk_provider, compat)) != 0) {
1171 if ((prv = load_identity_file(id)) == NULL) 1208 debug("%s: sshkey_sign: %s", __func__, ssh_err(r));
1172 return SSH_ERR_KEY_NOT_FOUND; 1209 goto out;
1173 if (id->key != NULL && !sshkey_equal_public(prv, id->key)) {
1174 error("%s: private key %s contents do not match public",
1175 __func__, id->filename);
1176 return SSH_ERR_KEY_NOT_FOUND;
1177 } 1210 }
1178 r = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat); 1211 /*
1212 * PKCS#11 tokens may not support all signature algorithms,
1213 * so check what we get back.
1214 */
1215 if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) {
1216 debug("%s: sshkey_check_sigtype: %s", __func__, ssh_err(r));
1217 goto out;
1218 }
1219 /* success */
1220 r = 0;
1221 out:
1222 notify_complete(notifier);
1179 sshkey_free(prv); 1223 sshkey_free(prv);
1180 return r; 1224 return r;
1181} 1225}
@@ -1278,7 +1322,7 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
1278 error("%s: no mutual signature supported", __func__); 1322 error("%s: no mutual signature supported", __func__);
1279 goto out; 1323 goto out;
1280 } 1324 }
1281 debug3("%s: signing using %s", __func__, alg); 1325 debug3("%s: signing using %s %s", __func__, alg, fp);
1282 1326
1283 sshbuf_free(b); 1327 sshbuf_free(b);
1284 if ((b = sshbuf_new()) == NULL) 1328 if ((b = sshbuf_new()) == NULL)
@@ -1325,7 +1369,9 @@ sign_and_send_pubkey(struct ssh *ssh, Identity *id)
1325 loc, sshkey_type(id->key), fp); 1369 loc, sshkey_type(id->key), fp);
1326 continue; 1370 continue;
1327 } 1371 }
1328 error("%s: signing failed: %s", __func__, ssh_err(r)); 1372 error("%s: signing failed for %s \"%s\"%s: %s", __func__,
1373 sshkey_type(sign_id->key), sign_id->filename,
1374 id->agent_fd != -1 ? " from agent" : "", ssh_err(r));
1329 goto out; 1375 goto out;
1330 } 1376 }
1331 if (slen == 0 || signature == NULL) /* shouldn't happen */ 1377 if (slen == 0 || signature == NULL) /* shouldn't happen */
@@ -1450,6 +1496,14 @@ load_identity_file(Identity *id)
1450 quit = 1; 1496 quit = 1;
1451 break; 1497 break;
1452 } 1498 }
1499 if (private != NULL && sshkey_is_sk(private) &&
1500 options.sk_provider == NULL) {
1501 debug("key \"%s\" is an authenticator-hosted key, "
1502 "but no provider specified", id->filename);
1503 sshkey_free(private);
1504 private = NULL;
1505 quit = 1;
1506 }
1453 if (!quit && private != NULL && id->agent_fd == -1 && 1507 if (!quit && private != NULL && id->agent_fd == -1 &&
1454 !(id->key && id->isprivate)) 1508 !(id->key && id->isprivate))
1455 maybe_add_key_to_agent(id->filename, private, comment, 1509 maybe_add_key_to_agent(id->filename, private, comment,
@@ -1520,8 +1574,19 @@ pubkey_prepare(Authctxt *authctxt)
1520 /* list of keys stored in the filesystem and PKCS#11 */ 1574 /* list of keys stored in the filesystem and PKCS#11 */
1521 for (i = 0; i < options.num_identity_files; i++) { 1575 for (i = 0; i < options.num_identity_files; i++) {
1522 key = options.identity_keys[i]; 1576 key = options.identity_keys[i];
1523 if (key && key->cert && key->cert->type != SSH2_CERT_TYPE_USER) 1577 if (key && key->cert &&
1578 key->cert->type != SSH2_CERT_TYPE_USER) {
1579 debug("%s: ignoring certificate %s: not a user "
1580 "certificate", __func__,
1581 options.identity_files[i]);
1582 continue;
1583 }
1584 if (key && sshkey_is_sk(key) && options.sk_provider == NULL) {
1585 debug("%s: ignoring authenticator-hosted key %s as no "
1586 "SecurityKeyProvider has been specified",
1587 __func__, options.identity_files[i]);
1524 continue; 1588 continue;
1589 }
1525 options.identity_keys[i] = NULL; 1590 options.identity_keys[i] = NULL;
1526 id = xcalloc(1, sizeof(*id)); 1591 id = xcalloc(1, sizeof(*id));
1527 id->agent_fd = -1; 1592 id->agent_fd = -1;
@@ -1534,8 +1599,19 @@ pubkey_prepare(Authctxt *authctxt)
1534 for (i = 0; i < options.num_certificate_files; i++) { 1599 for (i = 0; i < options.num_certificate_files; i++) {
1535 key = options.certificates[i]; 1600 key = options.certificates[i];
1536 if (!sshkey_is_cert(key) || key->cert == NULL || 1601 if (!sshkey_is_cert(key) || key->cert == NULL ||
1537 key->cert->type != SSH2_CERT_TYPE_USER) 1602 key->cert->type != SSH2_CERT_TYPE_USER) {
1603 debug("%s: ignoring certificate %s: not a user "
1604 "certificate", __func__,
1605 options.identity_files[i]);
1538 continue; 1606 continue;
1607 }
1608 if (key && sshkey_is_sk(key) && options.sk_provider == NULL) {
1609 debug("%s: ignoring authenticator-hosted key "
1610 "certificate %s as no "
1611 "SecurityKeyProvider has been specified",
1612 __func__, options.identity_files[i]);
1613 continue;
1614 }
1539 id = xcalloc(1, sizeof(*id)); 1615 id = xcalloc(1, sizeof(*id));
1540 id->agent_fd = -1; 1616 id->agent_fd = -1;
1541 id->key = key; 1617 id->key = key;
@@ -1860,7 +1936,7 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
1860 error("%s: fork: %s", __func__, strerror(errno)); 1936 error("%s: fork: %s", __func__, strerror(errno));
1861 return -1; 1937 return -1;
1862 } 1938 }
1863 osigchld = signal(SIGCHLD, SIG_DFL); 1939 osigchld = ssh_signal(SIGCHLD, SIG_DFL);
1864 if (pid == 0) { 1940 if (pid == 0) {
1865 close(from[0]); 1941 close(from[0]);
1866 if (dup2(from[1], STDOUT_FILENO) == -1) 1942 if (dup2(from[1], STDOUT_FILENO) == -1)
@@ -1932,11 +2008,11 @@ ssh_keysign(struct ssh *ssh, struct sshkey *key, u_char **sigp, size_t *lenp,
1932 if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) { 2008 if ((r = sshbuf_get_string(b, sigp, lenp)) != 0) {
1933 error("%s: buffer error: %s", __func__, ssh_err(r)); 2009 error("%s: buffer error: %s", __func__, ssh_err(r));
1934 fail: 2010 fail:
1935 signal(SIGCHLD, osigchld); 2011 ssh_signal(SIGCHLD, osigchld);
1936 sshbuf_free(b); 2012 sshbuf_free(b);
1937 return -1; 2013 return -1;
1938 } 2014 }
1939 signal(SIGCHLD, osigchld); 2015 ssh_signal(SIGCHLD, osigchld);
1940 sshbuf_free(b); 2016 sshbuf_free(b);
1941 2017
1942 return 0; 2018 return 0;