=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-keygen.c,v retrieving revision 1.306 retrieving revision 1.311 diff -u -r1.306 -r1.311 --- src/usr.bin/ssh/ssh-keygen.c 2017/07/01 13:50:45 1.306 +++ src/usr.bin/ssh/ssh-keygen.c 2018/02/10 05:43:26 1.311 @@ -1,4 +1,4 @@ -/* $OpenBSD: ssh-keygen.c,v 1.306 2017/07/01 13:50:45 djm Exp $ */ +/* $OpenBSD: ssh-keygen.c,v 1.311 2018/02/10 05:43:26 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -367,13 +367,6 @@ if (!PEM_write_RSAPublicKey(stdout, k->rsa)) fatal("PEM_write_RSAPublicKey failed"); break; -#if notyet /* OpenSSH 0.9.8 lacks this function */ - case KEY_DSA: - if (!PEM_write_DSAPublicKey(stdout, k->dsa)) - fatal("PEM_write_DSAPublicKey failed"); - break; -#endif - /* XXX ECDSA? */ default: fatal("%s: unsupported key type %s", __func__, sshkey_type(k)); } @@ -529,7 +522,7 @@ /* try the key */ if (sshkey_sign(key, &sig, &slen, data, sizeof(data), NULL, 0) != 0 || - sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) { + sshkey_verify(key, sig, slen, data, sizeof(data), NULL, 0) != 0) { sshkey_free(key); free(sig); return NULL; @@ -659,9 +652,6 @@ { FILE *fp; RSA *rsa; -#ifdef notyet - DSA *dsa; -#endif if ((fp = fopen(identity_file, "r")) == NULL) fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); @@ -673,18 +663,6 @@ fclose(fp); return; } -#if notyet /* OpenSSH 0.9.8 lacks this function */ - rewind(fp); - if ((dsa = PEM_read_DSAPublicKey(fp, NULL, NULL, NULL)) != NULL) { - if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); - (*k)->type = KEY_DSA; - (*k)->dsa = dsa; - fclose(fp); - return; - } - /* XXX ECDSA */ -#endif fatal("%s: unrecognised raw private key format", __func__); } @@ -981,20 +959,38 @@ int first = 0; struct stat st; struct sshkey *private, *public; - char comment[1024]; + char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file; int i, type, fd, r; FILE *f; for (i = 0; key_types[i].key_type; i++) { - if (stat(key_types[i].path, &st) == 0) - continue; - if (errno != ENOENT) { + public = private = NULL; + prv_tmp = pub_tmp = prv_file = pub_file = NULL; + + xasprintf(&prv_file, "%s%s", + identity_file, key_types[i].path); + + /* Check whether private key exists and is not zero-length */ + if (stat(prv_file, &st) == 0) { + if (st.st_size != 0) + goto next; + } else if (errno != ENOENT) { error("Could not stat %s: %s", key_types[i].path, strerror(errno)); - first = 0; - continue; + goto failnext; } + /* + * Private key doesn't exist or is invalid; proceed with + * key generation. + */ + xasprintf(&prv_tmp, "%s%s.XXXXXXXXXX", + identity_file, key_types[i].path); + xasprintf(&pub_tmp, "%s%s.pub.XXXXXXXXXX", + identity_file, key_types[i].path); + xasprintf(&pub_file, "%s%s.pub", + identity_file, key_types[i].path); + if (first == 0) { first = 1; printf("%s: generating new host keys: ", __progname); @@ -1002,56 +998,76 @@ printf("%s ", key_types[i].key_type_display); fflush(stdout); type = sshkey_type_from_name(key_types[i].key_type); - strlcpy(identity_file, key_types[i].path, sizeof(identity_file)); + if ((fd = mkstemp(prv_tmp)) == -1) { + error("Could not save your public key in %s: %s", + prv_tmp, strerror(errno)); + goto failnext; + } + close(fd); /* just using mkstemp() to generate/reserve a name */ bits = 0; type_bits_valid(type, NULL, &bits); if ((r = sshkey_generate(type, bits, &private)) != 0) { error("sshkey_generate failed: %s", ssh_err(r)); - first = 0; - continue; + goto failnext; } if ((r = sshkey_from_private(private, &public)) != 0) fatal("sshkey_from_private failed: %s", ssh_err(r)); snprintf(comment, sizeof comment, "%s@%s", pw->pw_name, hostname); - if ((r = sshkey_save_private(private, identity_file, "", + if ((r = sshkey_save_private(private, prv_tmp, "", comment, use_new_format, new_format_cipher, rounds)) != 0) { error("Saving key \"%s\" failed: %s", - identity_file, ssh_err(r)); - sshkey_free(private); - sshkey_free(public); - first = 0; - continue; + prv_tmp, ssh_err(r)); + goto failnext; } - sshkey_free(private); - strlcat(identity_file, ".pub", sizeof(identity_file)); - fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (fd == -1) { - error("Could not save your public key in %s", - identity_file); - sshkey_free(public); - first = 0; - continue; + if ((fd = mkstemp(pub_tmp)) == -1) { + error("Could not save your public key in %s: %s", + pub_tmp, strerror(errno)); + goto failnext; } + (void)fchmod(fd, 0644); f = fdopen(fd, "w"); if (f == NULL) { - error("fdopen %s failed", identity_file); + error("fdopen %s failed: %s", pub_tmp, strerror(errno)); close(fd); - sshkey_free(public); - first = 0; - continue; + goto failnext; } if ((r = sshkey_write(public, f)) != 0) { error("write key failed: %s", ssh_err(r)); fclose(f); - sshkey_free(public); - first = 0; - continue; + goto failnext; } fprintf(f, " %s\n", comment); - fclose(f); - sshkey_free(public); + if (ferror(f) != 0) { + error("write key failed: %s", strerror(errno)); + fclose(f); + goto failnext; + } + if (fclose(f) != 0) { + error("key close failed: %s", strerror(errno)); + goto failnext; + } + /* Rename temporary files to their permanent locations. */ + if (rename(pub_tmp, pub_file) != 0) { + error("Unable to move %s into position: %s", + pub_file, strerror(errno)); + goto failnext; + } + if (rename(prv_tmp, prv_file) != 0) { + error("Unable to move %s into position: %s", + key_types[i].path, strerror(errno)); + failnext: + first = 0; + goto next; + } + next: + sshkey_free(private); + sshkey_free(public); + free(prv_tmp); + free(pub_tmp); + free(prv_file); + free(pub_file); } if (first != 0) printf("\n"); @@ -1778,7 +1794,7 @@ s, s + 4, s + 6, s + 8, s + 10, s + 12); break; default: - fatal("Invalid certificate time format %s", s); + fatal("Invalid certificate time format \"%s\"", s); } memset(&tm, 0, sizeof(tm)); @@ -1811,8 +1827,8 @@ /* * from:to, where - * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS - * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS + * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "always" + * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "forever" */ from = xstrdup(timespec); to = strchr(from, ':'); @@ -1822,11 +1838,15 @@ if (*from == '-' || *from == '+') cert_valid_from = parse_relative_time(from, now); + else if (strcmp(from, "always") == 0) + cert_valid_from = 0; else cert_valid_from = parse_absolute_time(from); if (*to == '-' || *to == '+') cert_valid_to = parse_relative_time(to, now); + else if (strcmp(to, "forever") == 0) + cert_valid_to = ~(u_int64_t)0; else cert_valid_to = parse_absolute_time(to); @@ -2803,7 +2823,8 @@ if ((r = sshkey_write(public, f)) != 0) error("write key failed: %s", ssh_err(r)); fprintf(f, " %s\n", comment); - fclose(f); + if (ferror(f) || fclose(f) != 0) + fatal("write public failed: %s", strerror(errno)); if (!quiet) { fp = sshkey_fingerprint(public, fingerprint_hash,