[ssh-keygen.1 ssh-keygen.c]
     Add -A option.  For each of the key types (rsa1, rsa, dsa and ecdsa)
     for which host keys 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.  This will be used by /etc/rc to generate
     new host keys.  Idea from deraadt.
     ok deraadt
This commit is contained in:
Damien Miller 2011-05-05 14:06:15 +10:00
parent c5219e701e
commit 58f1bafb3d
3 changed files with 157 additions and 30 deletions

View File

@ -18,6 +18,14 @@
[ssh-keyscan.c] [ssh-keyscan.c]
use timerclear macro use timerclear macro
ok djm@ ok djm@
- stevesk@cvs.openbsd.org 2011/03/23 15:16:22
[ssh-keygen.1 ssh-keygen.c]
Add -A option. For each of the key types (rsa1, rsa, dsa and ecdsa)
for which host keys 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. This will be used by /etc/rc to generate
new host keys. Idea from deraadt.
ok deraadt
20110221 20110221
- (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the - (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: ssh-keygen.1,v 1.101 2010/10/28 18:33:28 jmc Exp $ .\" $OpenBSD: ssh-keygen.1,v 1.102 2011/03/23 15:16:22 stevesk 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: October 28 2010 $ .Dd $Mdocdate: March 23 2011 $
.Dt SSH-KEYGEN 1 .Dt SSH-KEYGEN 1
.Os .Os
.Sh NAME .Sh NAME
@ -117,6 +117,8 @@
.Nm ssh-keygen .Nm ssh-keygen
.Fl L .Fl L
.Op Fl f Ar input_keyfile .Op Fl f Ar input_keyfile
.Nm ssh-keygen
.Fl A
.Ek .Ek
.Sh DESCRIPTION .Sh DESCRIPTION
.Nm .Nm
@ -192,6 +194,13 @@ should be placed to be activated.
.Pp .Pp
The options are as follows: The options are as follows:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Fl A
For each of the key types (rsa1, rsa, dsa and ecdsa) for which host keys
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.
This is used by
.Pa /etc/rc
to generate new host keys.
.It Fl a Ar trials .It Fl a Ar trials
Specifies the number of primality tests to perform when screening DH-GEX Specifies the number of primality tests to perform when screening DH-GEX
candidates using the candidates using the

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ssh-keygen.c,v 1.205 2011/01/11 06:13:10 djm Exp $ */ /* $OpenBSD: ssh-keygen.c,v 1.206 2011/03/23 15:16:22 stevesk 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
@ -159,6 +159,38 @@ char hostname[MAXHOSTNAMELEN];
int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
static void
type_bits_valid(int type, u_int32_t *bits)
{
u_int maxbits;
if (type == KEY_UNSPEC) {
fprintf(stderr, "unknown key type %s\n", key_type_name);
exit(1);
}
if (*bits == 0) {
if (type == KEY_DSA)
*bits = DEFAULT_BITS_DSA;
else if (type == KEY_ECDSA)
*bits = DEFAULT_BITS_ECDSA;
else
*bits = DEFAULT_BITS;
}
maxbits = (type == KEY_DSA) ?
OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
if (*bits > maxbits) {
fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
exit(1);
}
if (type == KEY_DSA && *bits != 1024)
fatal("DSA keys must be 1024 bits");
else if (type != KEY_ECDSA && *bits < 768)
fatal("Key must at least be 768 bits");
else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bits) == -1)
fatal("Invalid ECDSA key length - valid lengths are "
"256, 384 or 521 bits");
}
static void static void
ask_filename(struct passwd *pw, const char *prompt) ask_filename(struct passwd *pw, const char *prompt)
{ {
@ -817,6 +849,98 @@ do_fingerprint(struct passwd *pw)
exit(0); exit(0);
} }
static void
do_gen_all_hostkeys(struct passwd *pw)
{
struct {
char *key_type;
char *key_type_display;
char *path;
} key_types[] = {
{ "rsa1", "RSA1", _PATH_HOST_KEY_FILE },
{ "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE },
{ "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE },
{ "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE },
{ NULL, NULL, NULL }
};
int first = 0;
struct stat st;
Key *private, *public;
char comment[1024];
int i, type, fd;
FILE *f;
for (i = 0; key_types[i].key_type; i++) {
if (stat(key_types[i].path, &st) == 0)
continue;
if (errno != ENOENT) {
printf("Could not stat %s: %s", key_types[i].path,
strerror(errno));
first = 0;
continue;
}
if (first == 0) {
first = 1;
printf("%s: generating new host keys: ", __progname);
}
printf("%s ", key_types[i].key_type_display);
fflush(stdout);
arc4random_stir();
type = key_type_from_name(key_types[i].key_type);
strlcpy(identity_file, key_types[i].path, sizeof(identity_file));
bits = 0;
type_bits_valid(type, &bits);
private = key_generate(type, bits);
if (private == NULL) {
fprintf(stderr, "key_generate failed\n");
first = 0;
continue;
}
public = key_from_private(private);
snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
hostname);
if (!key_save_private(private, identity_file, "", comment)) {
printf("Saving the key failed: %s.\n", identity_file);
key_free(private);
key_free(public);
first = 0;
continue;
}
key_free(private);
arc4random_stir();
strlcat(identity_file, ".pub", sizeof(identity_file));
fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
printf("Could not save your public key in %s\n",
identity_file);
key_free(public);
first = 0;
continue;
}
f = fdopen(fd, "w");
if (f == NULL) {
printf("fdopen %s failed\n", identity_file);
key_free(public);
first = 0;
continue;
}
if (!key_write(public, f)) {
fprintf(stderr, "write key failed\n");
key_free(public);
first = 0;
continue;
}
fprintf(f, " %s\n", comment);
fclose(f);
key_free(public);
}
if (first != 0)
printf("\n");
}
static void static void
printhost(FILE *f, const char *name, Key *public, int ca, int hash) printhost(FILE *f, const char *name, Key *public, int ca, int hash)
{ {
@ -1745,6 +1869,7 @@ usage(void)
{ {
fprintf(stderr, "usage: %s [options]\n", __progname); fprintf(stderr, "usage: %s [options]\n", __progname);
fprintf(stderr, "Options:\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -A Generate non-existent host keys for all key types.\n");
fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n"); fprintf(stderr, " -a trials Number of trials for screening DH-GEX moduli.\n");
fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); fprintf(stderr, " -B Show bubblebabble digest of key file.\n");
fprintf(stderr, " -b bits Number of bits in the key to create.\n"); fprintf(stderr, " -b bits Number of bits in the key to create.\n");
@ -1799,9 +1924,9 @@ main(int argc, char **argv)
struct passwd *pw; struct passwd *pw;
struct stat st; struct stat st;
int opt, type, fd; int opt, type, fd;
u_int maxbits;
u_int32_t memory = 0, generator_wanted = 0, trials = 100; u_int32_t memory = 0, generator_wanted = 0, trials = 100;
int do_gen_candidates = 0, do_screen_candidates = 0; int do_gen_candidates = 0, do_screen_candidates = 0;
int gen_all_hostkeys = 0;
BIGNUM *start = NULL; BIGNUM *start = NULL;
FILE *f; FILE *f;
const char *errstr; const char *errstr;
@ -1830,9 +1955,12 @@ main(int argc, char **argv)
exit(1); exit(1);
} }
while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:" while ((opt = getopt(argc, argv, "AdegiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
"O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) { "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
switch (opt) { switch (opt) {
case 'A':
gen_all_hostkeys = 1;
break;
case 'b': case 'b':
bits = (u_int32_t)strtonum(optarg, 256, 32768, &errstr); bits = (u_int32_t)strtonum(optarg, 256, 32768, &errstr);
if (errstr) if (errstr)
@ -2108,37 +2236,19 @@ main(int argc, char **argv)
return (0); return (0);
} }
if (gen_all_hostkeys) {
do_gen_all_hostkeys(pw);
return (0);
}
arc4random_stir(); arc4random_stir();
if (key_type_name == NULL) if (key_type_name == NULL)
key_type_name = "rsa"; key_type_name = "rsa";
type = key_type_from_name(key_type_name); type = key_type_from_name(key_type_name);
if (type == KEY_UNSPEC) { type_bits_valid(type, &bits);
fprintf(stderr, "unknown key type %s\n", key_type_name);
exit(1);
}
if (bits == 0) {
if (type == KEY_DSA)
bits = DEFAULT_BITS_DSA;
else if (type == KEY_ECDSA)
bits = DEFAULT_BITS_ECDSA;
else
bits = DEFAULT_BITS;
}
maxbits = (type == KEY_DSA) ?
OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
if (bits > maxbits) {
fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
exit(1);
}
if (type == KEY_DSA && bits != 1024)
fatal("DSA keys must be 1024 bits");
else if (type != KEY_ECDSA && bits < 768)
fatal("Key must at least be 768 bits");
else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(bits) == -1)
fatal("Invalid ECDSA key length - valid lengths are "
"256, 384 or 521 bits");
if (!quiet) if (!quiet)
printf("Generating public/private %s key pair.\n", key_type_name); printf("Generating public/private %s key pair.\n", key_type_name);
private = key_generate(type, bits); private = key_generate(type, bits);