=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-keygen.c,v retrieving revision 1.120 retrieving revision 1.136 diff -u -r1.120 -r1.136 --- src/usr.bin/ssh/ssh-keygen.c 2005/03/02 01:27:41 1.120 +++ src/usr.bin/ssh/ssh-keygen.c 2006/02/20 17:19:54 1.136 @@ -12,8 +12,11 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh-keygen.c,v 1.120 2005/03/02 01:27:41 djm Exp $"); +RCSID("$OpenBSD: ssh-keygen.c,v 1.136 2006/02/20 17:19:54 stevesk Exp $"); +#include +#include + #include #include @@ -35,8 +38,10 @@ #endif #include "dns.h" -/* Number of bits in the RSA/DSA key. This value can be changed on the command line. */ -int bits = 1024; +/* Number of bits in the RSA/DSA key. This value can be set on the command line. */ +#define DEFAULT_BITS 2048 +#define DEFAULT_BITS_DSA 1024 +u_int32_t bits = 0; /* * Flag indicating that we just want to change the passphrase. This can be @@ -90,7 +95,7 @@ char hostname[MAXHOSTNAMELEN]; /* moduli.c */ -int gen_candidates(FILE *, int, int, BIGNUM *); +int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); int prime_test(FILE *, FILE *, u_int32_t, u_int32_t); static void @@ -684,7 +689,7 @@ if (delete_host && !c) print_host(out, cp, public, 0); } else if (hash_hosts) { - for(cp2 = strsep(&cp, ","); + for (cp2 = strsep(&cp, ","); cp2 != NULL && *cp2 != '\0'; cp2 = strsep(&cp, ",")) { if (strcspn(cp2, "*?!") != strlen(cp2)) @@ -707,7 +712,7 @@ identity_file); if (inplace) { fprintf(stderr, "Not replacing existing known_hosts " - "file beacuse of errors"); + "file because of errors\n"); fclose(out); unlink(tmp); } @@ -738,7 +743,7 @@ fprintf(stderr, "WARNING: %s contains unhashed " "entries\n", old); fprintf(stderr, "Delete this file to ensure privacy " - "of hostnames\n"); + "of hostnames\n"); } } @@ -959,32 +964,39 @@ { fprintf(stderr, "Usage: %s [options]\n", __progname); fprintf(stderr, "Options:\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 bits Number of bits in the key to create.\n"); + fprintf(stderr, " -C comment Provide new comment.\n"); fprintf(stderr, " -c Change comment in private and public key files.\n"); +#ifdef SMARTCARD + fprintf(stderr, " -D reader Download public key from smartcard.\n"); +#endif /* SMARTCARD */ fprintf(stderr, " -e Convert OpenSSH to IETF SECSH key file.\n"); + fprintf(stderr, " -F hostname Find hostname in known hosts file.\n"); fprintf(stderr, " -f filename Filename of the key file.\n"); + fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); fprintf(stderr, " -g Use generic DNS resource record format.\n"); + fprintf(stderr, " -H Hash names in known_hosts file.\n"); fprintf(stderr, " -i Convert IETF SECSH to OpenSSH key file.\n"); fprintf(stderr, " -l Show fingerprint of key file.\n"); - fprintf(stderr, " -p Change passphrase of private key file.\n"); - fprintf(stderr, " -q Quiet.\n"); - fprintf(stderr, " -y Read private key file and print public key.\n"); - fprintf(stderr, " -t type Specify type of key to create.\n"); - fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); - fprintf(stderr, " -H Hash names in known_hosts file\n"); - fprintf(stderr, " -F hostname Find hostname in known hosts file\n"); - fprintf(stderr, " -C comment Provide new comment.\n"); + fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n"); fprintf(stderr, " -N phrase Provide new passphrase.\n"); fprintf(stderr, " -P phrase Provide old passphrase.\n"); + fprintf(stderr, " -p Change passphrase of private key file.\n"); + fprintf(stderr, " -q Quiet.\n"); + fprintf(stderr, " -R hostname Remove host from known_hosts file.\n"); fprintf(stderr, " -r hostname Print DNS resource record.\n"); + fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n"); + fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n"); + fprintf(stderr, " -t type Specify type of key to create.\n"); #ifdef SMARTCARD - fprintf(stderr, " -D reader Download public key from smartcard.\n"); fprintf(stderr, " -U reader Upload private key to smartcard.\n"); #endif /* SMARTCARD */ + fprintf(stderr, " -v Verbose.\n"); + fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n"); + fprintf(stderr, " -y Read private key file and print public key.\n"); - fprintf(stderr, " -G file Generate candidates for DH-GEX moduli\n"); - fprintf(stderr, " -T file Screen candidates for DH-GEX moduli\n"); - exit(1); } @@ -1000,16 +1012,20 @@ Key *private, *public; struct passwd *pw; struct stat st; - int opt, type, fd, download = 0, memory = 0; - int generator_wanted = 0, trials = 100; + int opt, type, fd, download = 0; + u_int32_t memory = 0, generator_wanted = 0, trials = 100; int do_gen_candidates = 0, do_screen_candidates = 0; int log_level = SYSLOG_LEVEL_INFO; BIGNUM *start = NULL; FILE *f; + const char *errstr; extern int optind; extern char *optarg; + /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ + sanitise_stdfd(); + SSLeay_add_all_algorithms(); log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); @@ -1028,11 +1044,10 @@ "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { switch (opt) { case 'b': - bits = atoi(optarg); - if (bits < 512 || bits > 32768) { - printf("Bits has bad value.\n"); - exit(1); - } + bits = strtonum(optarg, 768, 32768, &errstr); + if (errstr) + fatal("Bits has bad value %s (%s)", + optarg, errstr); break; case 'F': find_host = 1; @@ -1058,7 +1073,9 @@ change_comment = 1; break; case 'f': - strlcpy(identity_file, optarg, sizeof(identity_file)); + if (strlcpy(identity_file, optarg, sizeof(identity_file)) >= + sizeof(identity_file)) + fatal("Identity filename too long"); have_identity = 1; break; case 'g': @@ -1113,23 +1130,34 @@ rr_hostname = optarg; break; case 'W': - generator_wanted = atoi(optarg); - if (generator_wanted < 1) - fatal("Desired generator has bad value."); + generator_wanted = strtonum(optarg, 1, UINT_MAX, &errstr); + if (errstr) + fatal("Desired generator has bad value: %s (%s)", + optarg, errstr); break; case 'a': - trials = atoi(optarg); + trials = strtonum(optarg, 1, UINT_MAX, &errstr); + if (errstr) + fatal("Invalid number of trials: %s (%s)", + optarg, errstr); break; case 'M': - memory = atoi(optarg); + memory = strtonum(optarg, 1, UINT_MAX, &errstr); + if (errstr) { + fatal("Memory limit is %s: %s", errstr, optarg); + } break; case 'G': do_gen_candidates = 1; - strlcpy(out_file, optarg, sizeof(out_file)); + if (strlcpy(out_file, optarg, sizeof(out_file)) >= + sizeof(out_file)) + fatal("Output filename too long"); break; case 'T': do_screen_candidates = 1; - strlcpy(out_file, optarg, sizeof(out_file)); + if (strlcpy(out_file, optarg, sizeof(out_file)) >= + sizeof(out_file)) + fatal("Output filename too long"); break; case 'S': /* XXX - also compare length against bits */ @@ -1189,8 +1217,10 @@ out_file, strerror(errno)); return (1); } + if (bits == 0) + bits = DEFAULT_BITS; if (gen_candidates(out, memory, bits, start) != 0) - fatal("modulus candidate generation failed\n"); + fatal("modulus candidate generation failed"); return (0); } @@ -1213,21 +1243,24 @@ out_file, strerror(errno)); } if (prime_test(in, out, trials, generator_wanted) != 0) - fatal("modulus screening failed\n"); + fatal("modulus screening failed"); return (0); } arc4random_stir(); - if (key_type_name == NULL) { - printf("You must specify a key type (-t).\n"); - usage(); - } + if (key_type_name == NULL) + key_type_name = "rsa"; + type = key_type_from_name(key_type_name); if (type == KEY_UNSPEC) { fprintf(stderr, "unknown key type %s\n", key_type_name); exit(1); } + if (bits == 0) + bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS; + if (type == KEY_DSA && bits != 1024) + fatal("DSA keys must be 1024 bits"); if (!quiet) printf("Generating public/private %s key pair.\n", key_type_name); private = key_generate(type, bits); @@ -1240,7 +1273,7 @@ if (!have_identity) ask_filename(pw, "Enter file in which to save the key"); - /* Create ~/.ssh directory if it doesn\'t already exist. */ + /* Create ~/.ssh directory if it doesn't already exist. */ snprintf(dotsshdir, sizeof dotsshdir, "%s/%s", pw->pw_dir, _PATH_SSH_USER_DIR); if (strstr(identity_file, dotsshdir) != NULL && stat(dotsshdir, &st) < 0) {