summaryrefslogtreecommitdiff
path: root/ssh-keygen.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2017-07-07 03:53:12 +0000
committerDamien Miller <djm@mindrot.org>2017-07-21 14:17:32 +1000
commit853edbe057a84ebd0024c8003e4da21bf2b469f7 (patch)
tree2f7010fb3e1a780ba438b06753c1be99fab3abe9 /ssh-keygen.c
parent43616876ba68a2ffaece6a6c792def4b039f2d6e (diff)
upstream commit
When generating all hostkeys (ssh-keygen -A), clobber existing keys if they exist but are zero length. zero-length keys could previously be made if ssh-keygen failed part way through generating them, so avoid that case too. bz#2561 reported by Krzysztof Cieplucha; ok dtucker@ Upstream-ID: f662201c28ab8e1f086b5d43c59cddab5ade4044
Diffstat (limited to 'ssh-keygen.c')
-rw-r--r--ssh-keygen.c106
1 files changed, 72 insertions, 34 deletions
diff --git a/ssh-keygen.c b/ssh-keygen.c
index d8f942f5a..835f7d016 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.306 2017/07/01 13:50:45 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.307 2017/07/07 03:53:12 djm 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
@@ -997,20 +997,38 @@ do_gen_all_hostkeys(struct passwd *pw)
997 int first = 0; 997 int first = 0;
998 struct stat st; 998 struct stat st;
999 struct sshkey *private, *public; 999 struct sshkey *private, *public;
1000 char comment[1024]; 1000 char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
1001 int i, type, fd, r; 1001 int i, type, fd, r;
1002 FILE *f; 1002 FILE *f;
1003 1003
1004 for (i = 0; key_types[i].key_type; i++) { 1004 for (i = 0; key_types[i].key_type; i++) {
1005 if (stat(key_types[i].path, &st) == 0) 1005 public = private = NULL;
1006 continue; 1006 prv_tmp = pub_tmp = prv_file = pub_file = NULL;
1007 if (errno != ENOENT) { 1007
1008 xasprintf(&prv_file, "%s%s",
1009 identity_file, key_types[i].path);
1010
1011 /* Check whether private key exists and is not zero-length */
1012 if (stat(prv_file, &st) == 0) {
1013 if (st.st_size != 0)
1014 goto next;
1015 } else if (errno != ENOENT) {
1008 error("Could not stat %s: %s", key_types[i].path, 1016 error("Could not stat %s: %s", key_types[i].path,
1009 strerror(errno)); 1017 strerror(errno));
1010 first = 0; 1018 goto failnext;
1011 continue;
1012 } 1019 }
1013 1020
1021 /*
1022 * Private key doesn't exist or is invalid; proceed with
1023 * key generation.
1024 */
1025 xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX",
1026 identity_file, key_types[i].path);
1027 xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX",
1028 identity_file, key_types[i].path);
1029 xasprintf(&pub_file, "%s%s.pub",
1030 identity_file, key_types[i].path);
1031
1014 if (first == 0) { 1032 if (first == 0) {
1015 first = 1; 1033 first = 1;
1016 printf("%s: generating new host keys: ", __progname); 1034 printf("%s: generating new host keys: ", __progname);
@@ -1018,56 +1036,76 @@ do_gen_all_hostkeys(struct passwd *pw)
1018 printf("%s ", key_types[i].key_type_display); 1036 printf("%s ", key_types[i].key_type_display);
1019 fflush(stdout); 1037 fflush(stdout);
1020 type = sshkey_type_from_name(key_types[i].key_type); 1038 type = sshkey_type_from_name(key_types[i].key_type);
1021 strlcpy(identity_file, key_types[i].path, sizeof(identity_file)); 1039 if ((fd = mkstemp(prv_tmp)) == -1) {
1040 error("Could not save your public key in %s: %s",
1041 prv_tmp, strerror(errno));
1042 goto failnext;
1043 }
1044 close(fd); /* just using mkstemp() to generate/reserve a name */
1022 bits = 0; 1045 bits = 0;
1023 type_bits_valid(type, NULL, &bits); 1046 type_bits_valid(type, NULL, &bits);
1024 if ((r = sshkey_generate(type, bits, &private)) != 0) { 1047 if ((r = sshkey_generate(type, bits, &private)) != 0) {
1025 error("sshkey_generate failed: %s", ssh_err(r)); 1048 error("sshkey_generate failed: %s", ssh_err(r));
1026 first = 0; 1049 goto failnext;
1027 continue;
1028 } 1050 }
1029 if ((r = sshkey_from_private(private, &public)) != 0) 1051 if ((r = sshkey_from_private(private, &public)) != 0)
1030 fatal("sshkey_from_private failed: %s", ssh_err(r)); 1052 fatal("sshkey_from_private failed: %s", ssh_err(r));
1031 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, 1053 snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
1032 hostname); 1054 hostname);
1033 if ((r = sshkey_save_private(private, identity_file, "", 1055 if ((r = sshkey_save_private(private, prv_tmp, "",
1034 comment, use_new_format, new_format_cipher, rounds)) != 0) { 1056 comment, use_new_format, new_format_cipher, rounds)) != 0) {
1035 error("Saving key \"%s\" failed: %s", 1057 error("Saving key \"%s\" failed: %s",
1036 identity_file, ssh_err(r)); 1058 prv_tmp, ssh_err(r));
1037 sshkey_free(private); 1059 goto failnext;
1038 sshkey_free(public);
1039 first = 0;
1040 continue;
1041 } 1060 }
1042 sshkey_free(private); 1061 if ((fd = mkstemp(pub_tmp)) == -1) {
1043 strlcat(identity_file, ".pub", sizeof(identity_file)); 1062 error("Could not save your public key in %s: %s",
1044 fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); 1063 pub_tmp, strerror(errno));
1045 if (fd == -1) { 1064 goto failnext;
1046 error("Could not save your public key in %s",
1047 identity_file);
1048 sshkey_free(public);
1049 first = 0;
1050 continue;
1051 } 1065 }
1066 (void)fchmod(fd, 0644);
1052 f = fdopen(fd, "w"); 1067 f = fdopen(fd, "w");
1053 if (f == NULL) { 1068 if (f == NULL) {
1054 error("fdopen %s failed", identity_file); 1069 error("fdopen %s failed: %s", pub_tmp, strerror(errno));
1055 close(fd); 1070 close(fd);
1056 sshkey_free(public); 1071 goto failnext;
1057 first = 0;
1058 continue;
1059 } 1072 }
1060 if ((r = sshkey_write(public, f)) != 0) { 1073 if ((r = sshkey_write(public, f)) != 0) {
1061 error("write key failed: %s", ssh_err(r)); 1074 error("write key failed: %s", ssh_err(r));
1062 fclose(f); 1075 fclose(f);
1063 sshkey_free(public); 1076 goto failnext;
1064 first = 0;
1065 continue;
1066 } 1077 }
1067 fprintf(f, " %s\n", comment); 1078 fprintf(f, " %s\n", comment);
1068 fclose(f); 1079 if (ferror(f) != 0) {
1069 sshkey_free(public); 1080 error("write key failed: %s", strerror(errno));
1081 fclose(f);
1082 goto failnext;
1083 }
1084 if (fclose(f) != 0) {
1085 error("key close failed: %s", strerror(errno));
1086 goto failnext;
1087 }
1070 1088
1089 /* Rename temporary files to their permanent locations. */
1090 if (rename(pub_tmp, pub_file) != 0) {
1091 error("Unable to move %s into position: %s",
1092 pub_file, strerror(errno));
1093 goto failnext;
1094 }
1095 if (rename(prv_tmp, prv_file) != 0) {
1096 error("Unable to move %s into position: %s",
1097 key_types[i].path, strerror(errno));
1098 failnext:
1099 first = 0;
1100 goto next;
1101 }
1102 next:
1103 sshkey_free(private);
1104 sshkey_free(public);
1105 free(prv_tmp);
1106 free(pub_tmp);
1107 free(prv_file);
1108 free(pub_file);
1071 } 1109 }
1072 if (first != 0) 1110 if (first != 0)
1073 printf("\n"); 1111 printf("\n");