summaryrefslogtreecommitdiff
path: root/ssh-keygen.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r--ssh-keygen.c157
1 files changed, 68 insertions, 89 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 0d6ed1fff..2c5c75db7 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.398 2020/02/07 03:27:54 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.409.2.1 2020/05/18 19:02:13 benno Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -327,8 +327,7 @@ load_identity(const char *filename, char **commentp)
327 else 327 else
328 pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN); 328 pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN);
329 r = sshkey_load_private(filename, pass, &prv, commentp); 329 r = sshkey_load_private(filename, pass, &prv, commentp);
330 explicit_bzero(pass, strlen(pass)); 330 freezero(pass, strlen(pass));
331 free(pass);
332 if (r != 0) 331 if (r != 0)
333 fatal("Load key \"%s\": %s", filename, ssh_err(r)); 332 fatal("Load key \"%s\": %s", filename, ssh_err(r));
334 return prv; 333 return prv;
@@ -670,9 +669,10 @@ do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
670 encoded[len-3] = '\0'; 669 encoded[len-3] = '\0';
671 if ((r = sshbuf_b64tod(buf, encoded)) != 0) 670 if ((r = sshbuf_b64tod(buf, encoded)) != 0)
672 fatal("%s: base64 decoding failed: %s", __func__, ssh_err(r)); 671 fatal("%s: base64 decoding failed: %s", __func__, ssh_err(r));
673 if (*private) 672 if (*private) {
674 *k = do_convert_private_ssh2(buf); 673 if ((*k = do_convert_private_ssh2(buf)) == NULL)
675 else if ((r = sshkey_fromb(buf, k)) != 0) 674 fatal("%s: private key conversion failed", __func__);
675 } else if ((r = sshkey_fromb(buf, k)) != 0)
676 fatal("decode blob failed: %s", ssh_err(r)); 676 fatal("decode blob failed: %s", ssh_err(r));
677 sshbuf_free(buf); 677 sshbuf_free(buf);
678 fclose(fp); 678 fclose(fp);
@@ -911,22 +911,25 @@ fingerprint_private(const char *path)
911{ 911{
912 struct stat st; 912 struct stat st;
913 char *comment = NULL; 913 char *comment = NULL;
914 struct sshkey *public = NULL; 914 struct sshkey *privkey = NULL, *pubkey = NULL;
915 int r; 915 int r;
916 916
917 if (stat(identity_file, &st) == -1) 917 if (stat(identity_file, &st) == -1)
918 fatal("%s: %s", path, strerror(errno)); 918 fatal("%s: %s", path, strerror(errno));
919 if ((r = sshkey_load_public(path, &public, &comment)) != 0) { 919 if ((r = sshkey_load_public(path, &pubkey, &comment)) != 0)
920 debug("load public \"%s\": %s", path, ssh_err(r)); 920 debug("load public \"%s\": %s", path, ssh_err(r));
921 if (pubkey == NULL || comment == NULL || *comment == '\0') {
922 free(comment);
921 if ((r = sshkey_load_private(path, NULL, 923 if ((r = sshkey_load_private(path, NULL,
922 &public, &comment)) != 0) { 924 &privkey, &comment)) != 0)
923 debug("load private \"%s\": %s", path, ssh_err(r)); 925 debug("load private \"%s\": %s", path, ssh_err(r));
924 fatal("%s is not a key file.", path);
925 }
926 } 926 }
927 if (pubkey == NULL && privkey == NULL)
928 fatal("%s is not a key file.", path);
927 929
928 fingerprint_one_key(public, comment); 930 fingerprint_one_key(pubkey == NULL ? privkey : pubkey, comment);
929 sshkey_free(public); 931 sshkey_free(pubkey);
932 sshkey_free(privkey);
930 free(comment); 933 free(comment);
931} 934}
932 935
@@ -1054,7 +1057,6 @@ do_gen_all_hostkeys(struct passwd *pw)
1054 struct sshkey *private, *public; 1057 struct sshkey *private, *public;
1055 char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file; 1058 char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
1056 int i, type, fd, r; 1059 int i, type, fd, r;
1057 FILE *f;
1058 1060
1059 for (i = 0; key_types[i].key_type; i++) { 1061 for (i = 0; key_types[i].key_type; i++) {
1060 public = private = NULL; 1062 public = private = NULL;
@@ -1092,11 +1094,11 @@ do_gen_all_hostkeys(struct passwd *pw)
1092 fflush(stdout); 1094 fflush(stdout);
1093 type = sshkey_type_from_name(key_types[i].key_type); 1095 type = sshkey_type_from_name(key_types[i].key_type);
1094 if ((fd = mkstemp(prv_tmp)) == -1) { 1096 if ((fd = mkstemp(prv_tmp)) == -1) {
1095 error("Could not save your public key in %s: %s", 1097 error("Could not save your private key in %s: %s",
1096 prv_tmp, strerror(errno)); 1098 prv_tmp, strerror(errno));
1097 goto failnext; 1099 goto failnext;
1098 } 1100 }
1099 close(fd); /* just using mkstemp() to generate/reserve a name */ 1101 (void)close(fd); /* just using mkstemp() to reserve a name */
1100 bits = 0; 1102 bits = 0;
1101 type_bits_valid(type, NULL, &bits); 1103 type_bits_valid(type, NULL, &bits);
1102 if ((r = sshkey_generate(type, bits, &private)) != 0) { 1104 if ((r = sshkey_generate(type, bits, &private)) != 0) {
@@ -1120,25 +1122,10 @@ do_gen_all_hostkeys(struct passwd *pw)
1120 goto failnext; 1122 goto failnext;
1121 } 1123 }
1122 (void)fchmod(fd, 0644); 1124 (void)fchmod(fd, 0644);
1123 f = fdopen(fd, "w"); 1125 (void)close(fd);
1124 if (f == NULL) { 1126 if ((r = sshkey_save_public(public, pub_tmp, comment)) != 0) {
1125 error("fdopen %s failed: %s", pub_tmp, strerror(errno)); 1127 fatal("Unable to save public key to %s: %s",
1126 close(fd); 1128 identity_file, ssh_err(r));
1127 goto failnext;
1128 }
1129 if ((r = sshkey_write(public, f)) != 0) {
1130 error("write key failed: %s", ssh_err(r));
1131 fclose(f);
1132 goto failnext;
1133 }
1134 fprintf(f, " %s\n", comment);
1135 if (ferror(f) != 0) {
1136 error("write key failed: %s", strerror(errno));
1137 fclose(f);
1138 goto failnext;
1139 }
1140 if (fclose(f) != 0) {
1141 error("key close failed: %s", strerror(errno));
1142 goto failnext; 1129 goto failnext;
1143 } 1130 }
1144 1131
@@ -1424,8 +1411,7 @@ do_change_passphrase(struct passwd *pw)
1424 RP_ALLOW_STDIN); 1411 RP_ALLOW_STDIN);
1425 r = sshkey_load_private(identity_file, old_passphrase, 1412 r = sshkey_load_private(identity_file, old_passphrase,
1426 &private, &comment); 1413 &private, &comment);
1427 explicit_bzero(old_passphrase, strlen(old_passphrase)); 1414 freezero(old_passphrase, strlen(old_passphrase));
1428 free(old_passphrase);
1429 if (r != 0) 1415 if (r != 0)
1430 goto badkey; 1416 goto badkey;
1431 } else if (r != 0) { 1417 } else if (r != 0) {
@@ -1456,8 +1442,7 @@ do_change_passphrase(struct passwd *pw)
1456 exit(1); 1442 exit(1);
1457 } 1443 }
1458 /* Destroy the other copy. */ 1444 /* Destroy the other copy. */
1459 explicit_bzero(passphrase2, strlen(passphrase2)); 1445 freezero(passphrase2, strlen(passphrase2));
1460 free(passphrase2);
1461 } 1446 }
1462 1447
1463 /* Save the file using the new passphrase. */ 1448 /* Save the file using the new passphrase. */
@@ -1465,15 +1450,13 @@ do_change_passphrase(struct passwd *pw)
1465 comment, private_key_format, openssh_format_cipher, rounds)) != 0) { 1450 comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
1466 error("Saving key \"%s\" failed: %s.", 1451 error("Saving key \"%s\" failed: %s.",
1467 identity_file, ssh_err(r)); 1452 identity_file, ssh_err(r));
1468 explicit_bzero(passphrase1, strlen(passphrase1)); 1453 freezero(passphrase1, strlen(passphrase1));
1469 free(passphrase1);
1470 sshkey_free(private); 1454 sshkey_free(private);
1471 free(comment); 1455 free(comment);
1472 exit(1); 1456 exit(1);
1473 } 1457 }
1474 /* Destroy the passphrase and the copy of the key in memory. */ 1458 /* Destroy the passphrase and the copy of the key in memory. */
1475 explicit_bzero(passphrase1, strlen(passphrase1)); 1459 freezero(passphrase1, strlen(passphrase1));
1476 free(passphrase1);
1477 sshkey_free(private); /* Destroys contents */ 1460 sshkey_free(private); /* Destroys contents */
1478 free(comment); 1461 free(comment);
1479 1462
@@ -1519,8 +1502,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
1519 struct sshkey *private; 1502 struct sshkey *private;
1520 struct sshkey *public; 1503 struct sshkey *public;
1521 struct stat st; 1504 struct stat st;
1522 FILE *f; 1505 int r;
1523 int r, fd;
1524 1506
1525 if (!have_identity) 1507 if (!have_identity)
1526 ask_filename(pw, "Enter file in which the key is"); 1508 ask_filename(pw, "Enter file in which the key is");
@@ -1543,8 +1525,7 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
1543 /* Try to load using the passphrase. */ 1525 /* Try to load using the passphrase. */
1544 if ((r = sshkey_load_private(identity_file, passphrase, 1526 if ((r = sshkey_load_private(identity_file, passphrase,
1545 &private, &comment)) != 0) { 1527 &private, &comment)) != 0) {
1546 explicit_bzero(passphrase, strlen(passphrase)); 1528 freezero(passphrase, strlen(passphrase));
1547 free(passphrase);
1548 fatal("Cannot load private key \"%s\": %s.", 1529 fatal("Cannot load private key \"%s\": %s.",
1549 identity_file, ssh_err(r)); 1530 identity_file, ssh_err(r));
1550 } 1531 }
@@ -1589,31 +1570,22 @@ do_change_comment(struct passwd *pw, const char *identity_comment)
1589 rounds)) != 0) { 1570 rounds)) != 0) {
1590 error("Saving key \"%s\" failed: %s", 1571 error("Saving key \"%s\" failed: %s",
1591 identity_file, ssh_err(r)); 1572 identity_file, ssh_err(r));
1592 explicit_bzero(passphrase, strlen(passphrase)); 1573 freezero(passphrase, strlen(passphrase));
1593 free(passphrase);
1594 sshkey_free(private); 1574 sshkey_free(private);
1595 free(comment); 1575 free(comment);
1596 exit(1); 1576 exit(1);
1597 } 1577 }
1598 explicit_bzero(passphrase, strlen(passphrase)); 1578 freezero(passphrase, strlen(passphrase));
1599 free(passphrase);
1600 if ((r = sshkey_from_private(private, &public)) != 0) 1579 if ((r = sshkey_from_private(private, &public)) != 0)
1601 fatal("sshkey_from_private failed: %s", ssh_err(r)); 1580 fatal("sshkey_from_private failed: %s", ssh_err(r));
1602 sshkey_free(private); 1581 sshkey_free(private);
1603 1582
1604 strlcat(identity_file, ".pub", sizeof(identity_file)); 1583 strlcat(identity_file, ".pub", sizeof(identity_file));
1605 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); 1584 if ((r = sshkey_save_public(public, identity_file, new_comment)) != 0) {
1606 if (fd == -1) 1585 fatal("Unable to save public key to %s: %s",
1607 fatal("Could not save your public key in %s", identity_file); 1586 identity_file, ssh_err(r));
1608 f = fdopen(fd, "w"); 1587 }
1609 if (f == NULL)
1610 fatal("fdopen %s failed: %s", identity_file, strerror(errno));
1611 if ((r = sshkey_write(public, f)) != 0)
1612 fatal("write key failed: %s", ssh_err(r));
1613 sshkey_free(public); 1588 sshkey_free(public);
1614 fprintf(f, " %s\n", new_comment);
1615 fclose(f);
1616
1617 free(comment); 1589 free(comment);
1618 1590
1619 if (strlen(new_comment) > 0) 1591 if (strlen(new_comment) > 0)
@@ -1678,7 +1650,7 @@ prepare_options_buf(struct sshbuf *c, int which)
1678 if ((which & OPTIONS_EXTENSIONS) != 0 && 1650 if ((which & OPTIONS_EXTENSIONS) != 0 &&
1679 (certflags_flags & CERTOPT_USER_RC) != 0) 1651 (certflags_flags & CERTOPT_USER_RC) != 0)
1680 add_flag_option(c, "permit-user-rc"); 1652 add_flag_option(c, "permit-user-rc");
1681 if ((which & OPTIONS_CRITICAL) != 0 && 1653 if ((which & OPTIONS_EXTENSIONS) != 0 &&
1682 (certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0) 1654 (certflags_flags & CERTOPT_NO_REQUIRE_USER_PRESENCE) != 0)
1683 add_flag_option(c, "no-touch-required"); 1655 add_flag_option(c, "no-touch-required");
1684 if ((which & OPTIONS_CRITICAL) != 0 && 1656 if ((which & OPTIONS_CRITICAL) != 0 &&
@@ -1745,12 +1717,11 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
1745 unsigned long long cert_serial, int cert_serial_autoinc, 1717 unsigned long long cert_serial, int cert_serial_autoinc,
1746 int argc, char **argv) 1718 int argc, char **argv)
1747{ 1719{
1748 int r, i, fd, found, agent_fd = -1; 1720 int r, i, found, agent_fd = -1;
1749 u_int n; 1721 u_int n;
1750 struct sshkey *ca, *public; 1722 struct sshkey *ca, *public;
1751 char valid[64], *otmp, *tmp, *cp, *out, *comment; 1723 char valid[64], *otmp, *tmp, *cp, *out, *comment;
1752 char *ca_fp = NULL, **plist = NULL; 1724 char *ca_fp = NULL, **plist = NULL;
1753 FILE *f;
1754 struct ssh_identitylist *agent_ids; 1725 struct ssh_identitylist *agent_ids;
1755 size_t j; 1726 size_t j;
1756 struct notifier_ctx *notifier = NULL; 1727 struct notifier_ctx *notifier = NULL;
@@ -1873,16 +1844,10 @@ do_ca_sign(struct passwd *pw, const char *ca_key_path, int prefer_agent,
1873 xasprintf(&out, "%s-cert.pub", tmp); 1844 xasprintf(&out, "%s-cert.pub", tmp);
1874 free(tmp); 1845 free(tmp);
1875 1846
1876 if ((fd = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) 1847 if ((r = sshkey_save_public(public, out, comment)) != 0) {
1877 fatal("Could not open \"%s\" for writing: %s", out, 1848 fatal("Unable to save public key to %s: %s",
1878 strerror(errno)); 1849 identity_file, ssh_err(r));
1879 if ((f = fdopen(fd, "w")) == NULL) 1850 }
1880 fatal("%s: fdopen: %s", __func__, strerror(errno));
1881 if ((r = sshkey_write(public, f)) != 0)
1882 fatal("Could not write certified key to %s: %s",
1883 out, ssh_err(r));
1884 fprintf(f, " %s\n", comment);
1885 fclose(f);
1886 1851
1887 if (!quiet) { 1852 if (!quiet) {
1888 sshkey_format_cert_validity(public->cert, 1853 sshkey_format_cert_validity(public->cert,
@@ -2330,6 +2295,9 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca,
2330 cp = cp + strspn(cp, " \t"); 2295 cp = cp + strspn(cp, " \t");
2331 hash_to_blob(cp, &blob, &blen, file, lnum); 2296 hash_to_blob(cp, &blob, &blen, file, lnum);
2332 r = ssh_krl_revoke_key_sha256(krl, blob, blen); 2297 r = ssh_krl_revoke_key_sha256(krl, blob, blen);
2298 if (r != 0)
2299 fatal("%s: revoke key failed: %s",
2300 __func__, ssh_err(r));
2333 } else { 2301 } else {
2334 if (strncasecmp(cp, "key:", 4) == 0) { 2302 if (strncasecmp(cp, "key:", 4) == 0) {
2335 cp += 4; 2303 cp += 4;
@@ -2444,7 +2412,7 @@ do_gen_krl(struct passwd *pw, int updating, const char *ca_key_path,
2444} 2412}
2445 2413
2446static void 2414static void
2447do_check_krl(struct passwd *pw, int argc, char **argv) 2415do_check_krl(struct passwd *pw, int print_krl, int argc, char **argv)
2448{ 2416{
2449 int i, r, ret = 0; 2417 int i, r, ret = 0;
2450 char *comment; 2418 char *comment;
@@ -2454,6 +2422,8 @@ do_check_krl(struct passwd *pw, int argc, char **argv)
2454 if (*identity_file == '\0') 2422 if (*identity_file == '\0')
2455 fatal("KRL checking requires an input file"); 2423 fatal("KRL checking requires an input file");
2456 load_krl(identity_file, &krl); 2424 load_krl(identity_file, &krl);
2425 if (print_krl)
2426 krl_dump(krl, stdout);
2457 for (i = 0; i < argc; i++) { 2427 for (i = 0; i < argc; i++) {
2458 if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0) 2428 if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
2459 fatal("Cannot load public key %s: %s", 2429 fatal("Cannot load public key %s: %s",
@@ -2481,7 +2451,7 @@ load_sign_key(const char *keypath, const struct sshkey *pubkey)
2481 int r; 2451 int r;
2482 2452
2483 /* 2453 /*
2484 * If passed a public key filename, then try to locate the correponding 2454 * If passed a public key filename, then try to locate the corresponding
2485 * private key. This lets us specify certificates on the command-line 2455 * private key. This lets us specify certificates on the command-line
2486 * and have ssh-keygen find the appropriate private key. 2456 * and have ssh-keygen find the appropriate private key.
2487 */ 2457 */
@@ -2965,22 +2935,31 @@ do_download_sk(const char *skprovider, const char *device)
2965 struct sshkey **keys; 2935 struct sshkey **keys;
2966 size_t nkeys, i; 2936 size_t nkeys, i;
2967 int r, ok = -1; 2937 int r, ok = -1;
2968 char *fp, *pin, *pass = NULL, *path, *pubpath; 2938 char *fp, *pin = NULL, *pass = NULL, *path, *pubpath;
2969 const char *ext; 2939 const char *ext;
2970 2940
2971 if (skprovider == NULL) 2941 if (skprovider == NULL)
2972 fatal("Cannot download keys without provider"); 2942 fatal("Cannot download keys without provider");
2973 2943
2974 pin = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN); 2944 for (i = 0; i < 2; i++) {
2975 if ((r = sshsk_load_resident(skprovider, device, pin, 2945 if (i == 1) {
2976 &keys, &nkeys)) != 0) { 2946 pin = read_passphrase("Enter PIN for authenticator: ",
2977 freezero(pin, strlen(pin)); 2947 RP_ALLOW_STDIN);
2978 error("Unable to load resident keys: %s", ssh_err(r)); 2948 }
2979 return -1; 2949 if ((r = sshsk_load_resident(skprovider, device, pin,
2950 &keys, &nkeys)) != 0) {
2951 if (i == 0 && r == SSH_ERR_KEY_WRONG_PASSPHRASE)
2952 continue;
2953 if (pin != NULL)
2954 freezero(pin, strlen(pin));
2955 error("Unable to load resident keys: %s", ssh_err(r));
2956 return -1;
2957 }
2980 } 2958 }
2981 if (nkeys == 0) 2959 if (nkeys == 0)
2982 logit("No keys to download"); 2960 logit("No keys to download");
2983 freezero(pin, strlen(pin)); 2961 if (pin != NULL)
2962 freezero(pin, strlen(pin));
2984 2963
2985 for (i = 0; i < nkeys; i++) { 2964 for (i = 0; i < nkeys; i++) {
2986 if (keys[i]->type != KEY_ECDSA_SK && 2965 if (keys[i]->type != KEY_ECDSA_SK &&
@@ -3030,9 +3009,9 @@ do_download_sk(const char *skprovider, const char *device)
3030 free(path); 3009 free(path);
3031 if ((r = sshkey_save_public(keys[i], pubpath, 3010 if ((r = sshkey_save_public(keys[i], pubpath,
3032 keys[i]->sk_application)) != 0) { 3011 keys[i]->sk_application)) != 0) {
3033 free(pubpath);
3034 error("Saving public key \"%s\" failed: %s", 3012 error("Saving public key \"%s\" failed: %s",
3035 pubpath, ssh_err(r)); 3013 pubpath, ssh_err(r));
3014 free(pubpath);
3036 break; 3015 break;
3037 } 3016 }
3038 free(pubpath); 3017 free(pubpath);
@@ -3084,7 +3063,7 @@ usage(void)
3084 " ssh-keygen -A [-f prefix_path]\n" 3063 " ssh-keygen -A [-f prefix_path]\n"
3085 " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n" 3064 " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
3086 " file ...\n" 3065 " file ...\n"
3087 " ssh-keygen -Q -f krl_file file ...\n" 3066 " ssh-keygen -Q [-l] -f krl_file [file ...]\n"
3088 " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n" 3067 " ssh-keygen -Y find-principals -s signature_file -f allowed_signers_file\n"
3089 " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n" 3068 " ssh-keygen -Y check-novalidate -n namespace -s signature_file\n"
3090 " ssh-keygen -Y sign -f key_file -n namespace file ...\n" 3069 " ssh-keygen -Y sign -f key_file -n namespace file ...\n"
@@ -3439,7 +3418,7 @@ main(int argc, char **argv)
3439 return (0); 3418 return (0);
3440 } 3419 }
3441 if (check_krl) { 3420 if (check_krl) {
3442 do_check_krl(pw, argc, argv); 3421 do_check_krl(pw, print_fingerprint, argc, argv);
3443 return (0); 3422 return (0);
3444 } 3423 }
3445 if (ca_key_path != NULL) { 3424 if (ca_key_path != NULL) {
@@ -3672,7 +3651,7 @@ main(int argc, char **argv)
3672 strlcat(identity_file, ".pub", sizeof(identity_file)); 3651 strlcat(identity_file, ".pub", sizeof(identity_file));
3673 if ((r = sshkey_save_public(public, identity_file, comment)) != 0) { 3652 if ((r = sshkey_save_public(public, identity_file, comment)) != 0) {
3674 fatal("Unable to save public key to %s: %s", 3653 fatal("Unable to save public key to %s: %s",
3675 identity_file, strerror(errno)); 3654 identity_file, ssh_err(r));
3676 } 3655 }
3677 3656
3678 if (!quiet) { 3657 if (!quiet) {