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
This commit is contained in:
parent
43616876ba
commit
853edbe057
|
@ -1,4 +1,4 @@
|
||||||
.\" $OpenBSD: ssh-keygen.1,v 1.142 2017/06/28 01:09:22 djm Exp $
|
.\" $OpenBSD: ssh-keygen.1,v 1.143 2017/07/07 03:53:12 djm Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd $Mdocdate: June 28 2017 $
|
.Dd $Mdocdate: July 7 2017 $
|
||||||
.Dt SSH-KEYGEN 1
|
.Dt SSH-KEYGEN 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -126,6 +126,7 @@
|
||||||
.Op Fl f Ar input_keyfile
|
.Op Fl f Ar input_keyfile
|
||||||
.Nm ssh-keygen
|
.Nm ssh-keygen
|
||||||
.Fl A
|
.Fl A
|
||||||
|
.Op Fl f Ar prefix_path
|
||||||
.Nm ssh-keygen
|
.Nm ssh-keygen
|
||||||
.Fl k
|
.Fl k
|
||||||
.Fl f Ar krl_file
|
.Fl f Ar krl_file
|
||||||
|
@ -224,6 +225,10 @@ For each of the key types (rsa, dsa, ecdsa and ed25519)
|
||||||
for which host keys
|
for which host keys
|
||||||
do not exist, generate the host keys with the default key file path,
|
do not exist, generate the host keys with the default key file path,
|
||||||
an empty passphrase, default bits for the key type, and default comment.
|
an empty passphrase, default bits for the key type, and default comment.
|
||||||
|
If a
|
||||||
|
.Fl f
|
||||||
|
option has been specified, then its argument is used as a prefix to the
|
||||||
|
default path for the resulting host key files.
|
||||||
This is used by
|
This is used by
|
||||||
.Pa /etc/rc
|
.Pa /etc/rc
|
||||||
to generate new host keys.
|
to generate new host keys.
|
||||||
|
|
106
ssh-keygen.c
106
ssh-keygen.c
|
@ -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.307 2017/07/07 03:53:12 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -997,20 +997,38 @@ do_gen_all_hostkeys(struct passwd *pw)
|
||||||
int first = 0;
|
int first = 0;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct sshkey *private, *public;
|
struct sshkey *private, *public;
|
||||||
char comment[1024];
|
char comment[1024], *prv_tmp, *pub_tmp, *prv_file, *pub_file;
|
||||||
int i, type, fd, r;
|
int i, type, fd, r;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
for (i = 0; key_types[i].key_type; i++) {
|
for (i = 0; key_types[i].key_type; i++) {
|
||||||
if (stat(key_types[i].path, &st) == 0)
|
public = private = NULL;
|
||||||
continue;
|
prv_tmp = pub_tmp = prv_file = pub_file = NULL;
|
||||||
if (errno != ENOENT) {
|
|
||||||
|
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,
|
error("Could not stat %s: %s", key_types[i].path,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
first = 0;
|
goto failnext;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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) {
|
if (first == 0) {
|
||||||
first = 1;
|
first = 1;
|
||||||
printf("%s: generating new host keys: ", __progname);
|
printf("%s: generating new host keys: ", __progname);
|
||||||
|
@ -1018,56 +1036,76 @@ do_gen_all_hostkeys(struct passwd *pw)
|
||||||
printf("%s ", key_types[i].key_type_display);
|
printf("%s ", key_types[i].key_type_display);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
type = sshkey_type_from_name(key_types[i].key_type);
|
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;
|
bits = 0;
|
||||||
type_bits_valid(type, NULL, &bits);
|
type_bits_valid(type, NULL, &bits);
|
||||||
if ((r = sshkey_generate(type, bits, &private)) != 0) {
|
if ((r = sshkey_generate(type, bits, &private)) != 0) {
|
||||||
error("sshkey_generate failed: %s", ssh_err(r));
|
error("sshkey_generate failed: %s", ssh_err(r));
|
||||||
first = 0;
|
goto failnext;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if ((r = sshkey_from_private(private, &public)) != 0)
|
if ((r = sshkey_from_private(private, &public)) != 0)
|
||||||
fatal("sshkey_from_private failed: %s", ssh_err(r));
|
fatal("sshkey_from_private failed: %s", ssh_err(r));
|
||||||
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
|
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
|
||||||
hostname);
|
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) {
|
comment, use_new_format, new_format_cipher, rounds)) != 0) {
|
||||||
error("Saving key \"%s\" failed: %s",
|
error("Saving key \"%s\" failed: %s",
|
||||||
identity_file, ssh_err(r));
|
prv_tmp, ssh_err(r));
|
||||||
sshkey_free(private);
|
goto failnext;
|
||||||
sshkey_free(public);
|
|
||||||
first = 0;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
sshkey_free(private);
|
if ((fd = mkstemp(pub_tmp)) == -1) {
|
||||||
strlcat(identity_file, ".pub", sizeof(identity_file));
|
error("Could not save your public key in %s: %s",
|
||||||
fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
pub_tmp, strerror(errno));
|
||||||
if (fd == -1) {
|
goto failnext;
|
||||||
error("Could not save your public key in %s",
|
|
||||||
identity_file);
|
|
||||||
sshkey_free(public);
|
|
||||||
first = 0;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
(void)fchmod(fd, 0644);
|
||||||
f = fdopen(fd, "w");
|
f = fdopen(fd, "w");
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
error("fdopen %s failed", identity_file);
|
error("fdopen %s failed: %s", pub_tmp, strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
sshkey_free(public);
|
goto failnext;
|
||||||
first = 0;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if ((r = sshkey_write(public, f)) != 0) {
|
if ((r = sshkey_write(public, f)) != 0) {
|
||||||
error("write key failed: %s", ssh_err(r));
|
error("write key failed: %s", ssh_err(r));
|
||||||
fclose(f);
|
fclose(f);
|
||||||
sshkey_free(public);
|
goto failnext;
|
||||||
first = 0;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
fprintf(f, " %s\n", comment);
|
fprintf(f, " %s\n", comment);
|
||||||
fclose(f);
|
if (ferror(f) != 0) {
|
||||||
sshkey_free(public);
|
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)
|
if (first != 0)
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
Loading…
Reference in New Issue