diff options
-rw-r--r-- | ssh-keygen.1 | 9 | ||||
-rw-r--r-- | ssh-keygen.c | 106 |
2 files changed, 79 insertions, 36 deletions
diff --git a/ssh-keygen.1 b/ssh-keygen.1 index 66f8321c5..2bc61639a 100644 --- a/ssh-keygen.1 +++ b/ssh-keygen.1 | |||
@@ -1,4 +1,4 @@ | |||
1 | .\" $OpenBSD: ssh-keygen.1,v 1.142 2017/06/28 01:09:22 djm Exp $ | 1 | .\" $OpenBSD: ssh-keygen.1,v 1.143 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) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -35,7 +35,7 @@ | |||
35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 35 | .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 36 | .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
37 | .\" | 37 | .\" |
38 | .Dd $Mdocdate: June 28 2017 $ | 38 | .Dd $Mdocdate: July 7 2017 $ |
39 | .Dt SSH-KEYGEN 1 | 39 | .Dt SSH-KEYGEN 1 |
40 | .Os | 40 | .Os |
41 | .Sh NAME | 41 | .Sh NAME |
@@ -126,6 +126,7 @@ | |||
126 | .Op Fl f Ar input_keyfile | 126 | .Op Fl f Ar input_keyfile |
127 | .Nm ssh-keygen | 127 | .Nm ssh-keygen |
128 | .Fl A | 128 | .Fl A |
129 | .Op Fl f Ar prefix_path | ||
129 | .Nm ssh-keygen | 130 | .Nm ssh-keygen |
130 | .Fl k | 131 | .Fl k |
131 | .Fl f Ar krl_file | 132 | .Fl f Ar krl_file |
@@ -224,6 +225,10 @@ For each of the key types (rsa, dsa, ecdsa and ed25519) | |||
224 | for which host keys | 225 | for which host keys |
225 | do not exist, generate the host keys with the default key file path, | 226 | do not exist, generate the host keys with the default key file path, |
226 | an empty passphrase, default bits for the key type, and default comment. | 227 | an empty passphrase, default bits for the key type, and default comment. |
228 | If a | ||
229 | .Fl f | ||
230 | option has been specified, then its argument is used as a prefix to the | ||
231 | default path for the resulting host key files. | ||
227 | This is used by | 232 | This is used by |
228 | .Pa /etc/rc | 233 | .Pa /etc/rc |
229 | to generate new host keys. | 234 | to generate new host keys. |
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"); |