=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/ssh/ssh-keygen.c,v retrieving revision 1.136 retrieving revision 1.165 diff -u -r1.136 -r1.165 --- src/usr.bin/ssh/ssh-keygen.c 2006/02/20 17:19:54 1.136 +++ src/usr.bin/ssh/ssh-keygen.c 2008/01/19 22:37:19 1.165 @@ -1,3 +1,4 @@ +/* $OpenBSD: ssh-keygen.c,v 1.165 2008/01/19 22:37:19 djm Exp $ */ /* * Author: Tatu Ylonen * Copyright (c) 1994 Tatu Ylonen , Espoo, Finland @@ -11,32 +12,38 @@ * called by a name other than "ssh" or "Secure Shell". */ -#include "includes.h" -RCSID("$OpenBSD: ssh-keygen.c,v 1.136 2006/02/20 17:19:54 stevesk Exp $"); - #include #include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include + #include "xmalloc.h" #include "key.h" #include "rsa.h" #include "authfile.h" #include "uuencode.h" #include "buffer.h" -#include "bufaux.h" #include "pathnames.h" #include "log.h" #include "misc.h" #include "match.h" #include "hostfile.h" +#include "dns.h" #ifdef SMARTCARD #include "scard.h" #endif -#include "dns.h" /* Number of bits in the RSA/DSA key. This value can be set on the command line. */ #define DEFAULT_BITS 2048 @@ -106,7 +113,7 @@ if (key_type_name == NULL) name = _PATH_SSH_CLIENT_ID_RSA; - else + else { switch (key_type_from_name(key_type_name)) { case KEY_RSA1: name = _PATH_SSH_CLIENT_IDENTITY; @@ -122,13 +129,12 @@ exit(1); break; } - + } snprintf(identity_file, sizeof(identity_file), "%s/%s", pw->pw_dir, name); fprintf(stderr, "%s (%s): ", prompt, identity_file); if (fgets(buf, sizeof(buf), stdin) == NULL) exit(1); - if (strchr(buf, '\n')) - *strchr(buf, '\n') = 0; + buf[strcspn(buf, "\n")] = '\0'; if (strcmp(buf, "") != 0) strlcpy(identity_file, buf, sizeof(identity_file)); have_identity = 1; @@ -208,7 +214,8 @@ if (buffer_len(b) < bytes) fatal("buffer_get_bignum_bits: input buffer too small: " "need %d have %d", bytes, buffer_len(b)); - BN_bin2bn(buffer_ptr(b), bytes, value); + if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL) + fatal("buffer_get_bignum_bits: BN_bin2bn failed"); buffer_consume(b, bytes); } @@ -226,7 +233,7 @@ buffer_init(&b); buffer_append(&b, blob, blen); - magic = buffer_get_int(&b); + magic = buffer_get_int(&b); if (magic != SSH_COM_PRIVATE_KEY_MAGIC) { error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC); buffer_free(&b); @@ -238,7 +245,7 @@ i2 = buffer_get_int(&b); i3 = buffer_get_int(&b); i4 = buffer_get_int(&b); - debug("ignore (%d %d %d %d)", i1,i2,i3,i4); + debug("ignore (%d %d %d %d)", i1, i2, i3, i4); if (strcmp(cipher, "none") != 0) { error("unsupported cipher %s", cipher); xfree(cipher); @@ -269,7 +276,7 @@ buffer_get_bignum_bits(&b, key->dsa->priv_key); break; case KEY_RSA: - e = buffer_get_char(&b); + e = buffer_get_char(&b); debug("e %lx", e); if (e < 30) { e <<= 8; @@ -305,13 +312,43 @@ return key; } +static int +get_line(FILE *fp, char *line, size_t len) +{ + int c; + size_t pos = 0; + + line[0] = '\0'; + while ((c = fgetc(fp)) != EOF) { + if (pos >= len - 1) { + fprintf(stderr, "input line too long.\n"); + exit(1); + } + switch (c) { + case '\r': + c = fgetc(fp); + if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) { + fprintf(stderr, "unget: %s\n", strerror(errno)); + exit(1); + } + return pos; + case '\n': + return pos; + } + line[pos++] = c; + line[pos] = '\0'; + } + /* We reached EOF */ + return -1; +} + static void do_convert_from_ssh2(struct passwd *pw) { Key *k; int blen; u_int len; - char line[1024], *p; + char line[1024]; u_char blob[8096]; char encoded[8096]; struct stat st; @@ -330,12 +367,8 @@ exit(1); } encoded[0] = '\0'; - while (fgets(line, sizeof(line), fp)) { - if (!(p = strchr(line, '\n'))) { - fprintf(stderr, "input line too long.\n"); - exit(1); - } - if (p > line && p[-1] == '\\') + while ((blen = get_line(fp, line, sizeof(line))) != -1) { + if (line[blen - 1] == '\\') escaped++; if (strncmp(line, "----", 4) == 0 || strstr(line, ": ") != NULL) { @@ -352,7 +385,6 @@ /* fprintf(stderr, "escaped: %s", line); */ continue; } - *p = '\0'; strlcat(encoded, line, sizeof(encoded)); } len = strlen(encoded); @@ -465,7 +497,7 @@ FILE *f; Key *public; char *comment = NULL, *cp, *ep, line[16*1024], *fp; - int i, skip = 0, num = 1, invalid = 1; + int i, skip = 0, num = 0, invalid = 1; enum fp_rep rep; enum fp_type fptype; struct stat st; @@ -488,15 +520,17 @@ xfree(fp); exit(0); } - if (comment) + if (comment) { xfree(comment); + comment = NULL; + } f = fopen(identity_file, "r"); if (f != NULL) { while (fgets(line, sizeof(line), f)) { - i = strlen(line) - 1; - if (line[i] != '\n') { - error("line %d too long: %.40s...", num, line); + if ((cp = strchr(line, '\n')) == NULL) { + error("line %d too long: %.40s...", + num + 1, line); skip = 1; continue; } @@ -505,13 +539,13 @@ skip = 0; continue; } - line[i] = '\0'; + *cp = '\0'; /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) ; if (!*cp || *cp == '\n' || *cp == '#') - continue ; + continue; i = strtol(cp, &ep, 10); if (i == 0 || ep == NULL || (*ep != ' ' && *ep != '\t')) { int quoted = 0; @@ -556,7 +590,7 @@ } static void -print_host(FILE *f, char *name, Key *public, int hash) +print_host(FILE *f, const char *name, Key *public, int hash) { if (hash && (name = host_hash(name, NULL, 0)) == NULL) fatal("hash_host failed"); @@ -573,7 +607,7 @@ Key *public; char *cp, *cp2, *kp, *kp2; char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; - int c, i, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; + int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; if (!have_identity) { cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid); @@ -608,19 +642,18 @@ } while (fgets(line, sizeof(line), in)) { - num++; - i = strlen(line) - 1; - if (line[i] != '\n') { - error("line %d too long: %.40s...", num, line); + if ((cp = strchr(line, '\n')) == NULL) { + error("line %d too long: %.40s...", num + 1, line); skip = 1; invalid = 1; continue; } + num++; if (skip) { skip = 0; continue; } - line[i] = '\0'; + *cp = '\0'; /* Skip leading whitespace, empty and comment lines. */ for (cp = line; *cp == ' ' || *cp == '\t'; cp++) @@ -684,7 +717,8 @@ printf("# Host %s found: " "line %d type %s\n", name, num, key_type(public)); - print_host(out, cp, public, hash_hosts); + print_host(out, name, public, + hash_hosts); } if (delete_host && !c) print_host(out, cp, public, 0); @@ -708,7 +742,7 @@ fclose(in); if (invalid) { - fprintf(stderr, "%s is not a valid known_host file.\n", + fprintf(stderr, "%s is not a valid known_hosts file.\n", identity_file); if (inplace) { fprintf(stderr, "Not replacing existing known_hosts " @@ -835,30 +869,32 @@ /* * Print the SSHFP RR. */ -static void -do_print_resource_record(struct passwd *pw, char *hname) +static int +do_print_resource_record(struct passwd *pw, char *fname, char *hname) { Key *public; char *comment = NULL; struct stat st; - if (!have_identity) + if (fname == NULL) ask_filename(pw, "Enter file in which the key is"); - if (stat(identity_file, &st) < 0) { - perror(identity_file); + if (stat(fname, &st) < 0) { + if (errno == ENOENT) + return 0; + perror(fname); exit(1); } - public = key_load_public(identity_file, &comment); + public = key_load_public(fname, &comment); if (public != NULL) { export_dns_rr(hname, public, stdout, print_generic); key_free(public); xfree(comment); - exit(0); + return 1; } if (comment) xfree(comment); - printf("failed to read v2 public key from %s.\n", identity_file); + printf("failed to read v2 public key from %s.\n", fname); exit(1); } @@ -918,8 +954,7 @@ key_free(private); exit(1); } - if (strchr(new_comment, '\n')) - *strchr(new_comment, '\n') = 0; + new_comment[strcspn(new_comment, "\n")] = '\0'; } /* Save the file using the new passphrase. */ @@ -962,7 +997,7 @@ static void usage(void) { - fprintf(stderr, "Usage: %s [options]\n", __progname); + 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"); @@ -972,13 +1007,13 @@ #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, " -e Convert OpenSSH to RFC 4716 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, " -i Convert RFC 4716 to OpenSSH key file.\n"); fprintf(stderr, " -l Show fingerprint of key file.\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"); @@ -1004,7 +1039,7 @@ * Main program for key management. */ int -main(int ac, char **av) +main(int argc, char **argv) { char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2; char out_file[MAXPATHLEN], *reader_id = NULL; @@ -1027,7 +1062,7 @@ sanitise_stdfd(); SSLeay_add_all_algorithms(); - log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); + log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1); /* we need this for the home * directory. */ pw = getpwuid(getuid()); @@ -1040,11 +1075,11 @@ exit(1); } - while ((opt = getopt(ac, av, + while ((opt = getopt(argc, argv, "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) { switch (opt) { case 'b': - bits = strtonum(optarg, 768, 32768, &errstr); + bits = (u_int32_t)strtonum(optarg, 768, 32768, &errstr); if (errstr) fatal("Bits has bad value %s (%s)", optarg, errstr); @@ -1114,6 +1149,7 @@ break; case 'D': download = 1; + /*FALLTHROUGH*/ case 'U': reader_id = optarg; break; @@ -1130,19 +1166,20 @@ rr_hostname = optarg; break; case 'W': - generator_wanted = strtonum(optarg, 1, UINT_MAX, &errstr); + generator_wanted = (u_int32_t)strtonum(optarg, 1, + UINT_MAX, &errstr); if (errstr) fatal("Desired generator has bad value: %s (%s)", optarg, errstr); break; case 'a': - trials = strtonum(optarg, 1, UINT_MAX, &errstr); + trials = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr); if (errstr) fatal("Invalid number of trials: %s (%s)", optarg, errstr); break; case 'M': - memory = strtonum(optarg, 1, UINT_MAX, &errstr); + memory = (u_int32_t)strtonum(optarg, 1, UINT_MAX, &errstr); if (errstr) { fatal("Memory limit is %s: %s", errstr, optarg); } @@ -1171,9 +1208,9 @@ } /* reinit */ - log_init(av[0], log_level, SYSLOG_FACILITY_USER, 1); + log_init(argv[0], log_level, SYSLOG_FACILITY_USER, 1); - if (optind < ac) { + if (optind < argc) { printf("Too many arguments.\n"); usage(); } @@ -1196,7 +1233,27 @@ if (print_public) do_print_public(pw); if (rr_hostname != NULL) { - do_print_resource_record(pw, rr_hostname); + unsigned int n = 0; + + if (have_identity) { + n = do_print_resource_record(pw, + identity_file, rr_hostname); + if (n == 0) { + perror(identity_file); + exit(1); + } + exit(0); + } else { + + n += do_print_resource_record(pw, + _PATH_HOST_RSA_KEY_FILE, rr_hostname); + n += do_print_resource_record(pw, + _PATH_HOST_DSA_KEY_FILE, rr_hostname); + + if (n == 0) + fatal("no keys found."); + exit(0); + } } if (reader_id != NULL) { #ifdef SMARTCARD