[BACK]Return to ssh-keygen.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/ssh-keygen.c between version 1.102 and 1.130

version 1.102, 2002/11/26 00:45:03 version 1.130, 2005/10/07 11:13:57
Line 26 
Line 26 
 #include "bufaux.h"  #include "bufaux.h"
 #include "pathnames.h"  #include "pathnames.h"
 #include "log.h"  #include "log.h"
 #include "readpass.h"  #include "misc.h"
   #include "match.h"
   #include "hostfile.h"
   
 #ifdef SMARTCARD  #ifdef SMARTCARD
 #include "scard.h"  #include "scard.h"
 #endif  #endif
   #include "dns.h"
   
 /* Number of bits in the RSA/DSA key.  This value can be changed on the command line. */  /* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
 int bits = 1024;  #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   * Flag indicating that we just want to change the passphrase.  This can be
Line 49 
Line 54 
   
 int quiet = 0;  int quiet = 0;
   
   /* Flag indicating that we want to hash a known_hosts file */
   int hash_hosts = 0;
   /* Flag indicating that we want lookup a host in known_hosts file */
   int find_host = 0;
   /* Flag indicating that we want to delete a host from a known_hosts file */
   int delete_host = 0;
   
 /* Flag indicating that we just want to see the key fingerprint */  /* Flag indicating that we just want to see the key fingerprint */
 int print_fingerprint = 0;  int print_fingerprint = 0;
 int print_bubblebabble = 0;  int print_bubblebabble = 0;
Line 70 
Line 82 
 int convert_to_ssh2 = 0;  int convert_to_ssh2 = 0;
 int convert_from_ssh2 = 0;  int convert_from_ssh2 = 0;
 int print_public = 0;  int print_public = 0;
   int print_generic = 0;
   
 char *key_type_name = NULL;  char *key_type_name = NULL;
   
Line 78 
Line 91 
   
 char hostname[MAXHOSTNAMELEN];  char hostname[MAXHOSTNAMELEN];
   
   /* moduli.c */
   int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
   int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
   
 static void  static void
 ask_filename(struct passwd *pw, const char *prompt)  ask_filename(struct passwd *pw, const char *prompt)
 {  {
Line 159 
Line 176 
                         exit(1);                          exit(1);
                 }                  }
         }          }
           if (k->type == KEY_RSA1) {
                   fprintf(stderr, "version 1 keys are not supported\n");
                   exit(1);
           }
         if (key_to_blob(k, &blob, &len) <= 0) {          if (key_to_blob(k, &blob, &len) <= 0) {
                 fprintf(stderr, "key_to_blob failed\n");                  fprintf(stderr, "key_to_blob failed\n");
                 exit(1);                  exit(1);
Line 178 
Line 199 
 static void  static void
 buffer_get_bignum_bits(Buffer *b, BIGNUM *value)  buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
 {  {
         int bits = buffer_get_int(b);          u_int bignum_bits = buffer_get_int(b);
         int bytes = (bits + 7) / 8;          u_int bytes = (bignum_bits + 7) / 8;
   
         if (buffer_len(b) < bytes)          if (buffer_len(b) < bytes)
                 fatal("buffer_get_bignum_bits: input buffer too small: "                  fatal("buffer_get_bignum_bits: input buffer too small: "
Line 229 
Line 250 
         } else if (strstr(type, "rsa")) {          } else if (strstr(type, "rsa")) {
                 ktype = KEY_RSA;                  ktype = KEY_RSA;
         } else {          } else {
                   buffer_free(&b);
                 xfree(type);                  xfree(type);
                 return NULL;                  return NULL;
         }          }
Line 411 
Line 433 
         key_free(prv);          key_free(prv);
         if (ret < 0)          if (ret < 0)
                 exit(1);                  exit(1);
         log("loading key done");          logit("loading key done");
         exit(0);          exit(0);
 }  }
   
Line 530 
Line 552 
         exit(0);          exit(0);
 }  }
   
   static void
   print_host(FILE *f, char *name, Key *public, int hash)
   {
           if (hash && (name = host_hash(name, NULL, 0)) == NULL)
                   fatal("hash_host failed");
           fprintf(f, "%s ", name);
           if (!key_write(public, f))
                   fatal("key_write failed");
           fprintf(f, "\n");
   }
   
   static void
   do_known_hosts(struct passwd *pw, const char *name)
   {
           FILE *in, *out = stdout;
           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;
   
           if (!have_identity) {
                   cp = tilde_expand_filename(_PATH_SSH_USER_HOSTFILE, pw->pw_uid);
                   if (strlcpy(identity_file, cp, sizeof(identity_file)) >=
                       sizeof(identity_file))
                           fatal("Specified known hosts path too long");
                   xfree(cp);
                   have_identity = 1;
           }
           if ((in = fopen(identity_file, "r")) == NULL)
                   fatal("fopen: %s", strerror(errno));
   
           /*
            * Find hosts goes to stdout, hash and deletions happen in-place
            * A corner case is ssh-keygen -HF foo, which should go to stdout
            */
           if (!find_host && (hash_hosts || delete_host)) {
                   if (strlcpy(tmp, identity_file, sizeof(tmp)) >= sizeof(tmp) ||
                       strlcat(tmp, ".XXXXXXXXXX", sizeof(tmp)) >= sizeof(tmp) ||
                       strlcpy(old, identity_file, sizeof(old)) >= sizeof(old) ||
                       strlcat(old, ".old", sizeof(old)) >= sizeof(old))
                           fatal("known_hosts path too long");
                   umask(077);
                   if ((c = mkstemp(tmp)) == -1)
                           fatal("mkstemp: %s", strerror(errno));
                   if ((out = fdopen(c, "w")) == NULL) {
                           c = errno;
                           unlink(tmp);
                           fatal("fdopen: %s", strerror(c));
                   }
                   inplace = 1;
           }
   
           while (fgets(line, sizeof(line), in)) {
                   num++;
                   i = strlen(line) - 1;
                   if (line[i] != '\n') {
                           error("line %d too long: %.40s...", num, line);
                           skip = 1;
                           invalid = 1;
                           continue;
                   }
                   if (skip) {
                           skip = 0;
                           continue;
                   }
                   line[i] = '\0';
   
                   /* Skip leading whitespace, empty and comment lines. */
                   for (cp = line; *cp == ' ' || *cp == '\t'; cp++)
                           ;
                   if (!*cp || *cp == '\n' || *cp == '#') {
                           if (inplace)
                                   fprintf(out, "%s\n", cp);
                           continue;
                   }
                   /* Find the end of the host name portion. */
                   for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
                           ;
                   if (*kp == '\0' || *(kp + 1) == '\0') {
                           error("line %d missing key: %.40s...",
                               num, line);
                           invalid = 1;
                           continue;
                   }
                   *kp++ = '\0';
                   kp2 = kp;
   
                   public = key_new(KEY_RSA1);
                   if (key_read(public, &kp) != 1) {
                           kp = kp2;
                           key_free(public);
                           public = key_new(KEY_UNSPEC);
                           if (key_read(public, &kp) != 1) {
                                   error("line %d invalid key: %.40s...",
                                       num, line);
                                   key_free(public);
                                   invalid = 1;
                                   continue;
                           }
                   }
   
                   if (*cp == HASH_DELIM) {
                           if (find_host || delete_host) {
                                   cp2 = host_hash(name, cp, strlen(cp));
                                   if (cp2 == NULL) {
                                           error("line %d: invalid hashed "
                                               "name: %.64s...", num, line);
                                           invalid = 1;
                                           continue;
                                   }
                                   c = (strcmp(cp2, cp) == 0);
                                   if (find_host && c) {
                                           printf("# Host %s found: "
                                               "line %d type %s\n", name,
                                               num, key_type(public));
                                           print_host(out, cp, public, 0);
                                   }
                                   if (delete_host && !c)
                                           print_host(out, cp, public, 0);
                           } else if (hash_hosts)
                                   print_host(out, cp, public, 0);
                   } else {
                           if (find_host || delete_host) {
                                   c = (match_hostname(name, cp,
                                       strlen(cp)) == 1);
                                   if (find_host && c) {
                                           printf("# Host %s found: "
                                               "line %d type %s\n", name,
                                               num, key_type(public));
                                           print_host(out, cp, public, hash_hosts);
                                   }
                                   if (delete_host && !c)
                                           print_host(out, cp, public, 0);
                           } else if (hash_hosts) {
                                   for (cp2 = strsep(&cp, ",");
                                       cp2 != NULL && *cp2 != '\0';
                                       cp2 = strsep(&cp, ",")) {
                                           if (strcspn(cp2, "*?!") != strlen(cp2))
                                                   fprintf(stderr, "Warning: "
                                                       "ignoring host name with "
                                                       "metacharacters: %.64s\n",
                                                       cp2);
                                           else
                                                   print_host(out, cp2, public, 1);
                                   }
                                   has_unhashed = 1;
                           }
                   }
                   key_free(public);
           }
           fclose(in);
   
           if (invalid) {
                   fprintf(stderr, "%s is not a valid known_host file.\n",
                       identity_file);
                   if (inplace) {
                           fprintf(stderr, "Not replacing existing known_hosts "
                               "file because of errors\n");
                           fclose(out);
                           unlink(tmp);
                   }
                   exit(1);
           }
   
           if (inplace) {
                   fclose(out);
   
                   /* Backup existing file */
                   if (unlink(old) == -1 && errno != ENOENT)
                           fatal("unlink %.100s: %s", old, strerror(errno));
                   if (link(identity_file, old) == -1)
                           fatal("link %.100s to %.100s: %s", identity_file, old,
                               strerror(errno));
                   /* Move new one into place */
                   if (rename(tmp, identity_file) == -1) {
                           error("rename\"%s\" to \"%s\": %s", tmp, identity_file,
                               strerror(errno));
                           unlink(tmp);
                           unlink(old);
                           exit(1);
                   }
   
                   fprintf(stderr, "%s updated.\n", identity_file);
                   fprintf(stderr, "Original contents retained as %s\n", old);
                   if (has_unhashed) {
                           fprintf(stderr, "WARNING: %s contains unhashed "
                               "entries\n", old);
                           fprintf(stderr, "Delete this file to ensure privacy "
                               "of hostnames\n");
                   }
           }
   
           exit(0);
   }
   
 /*  /*
  * Perform changing a passphrase.  The argument is the passwd structure   * Perform changing a passphrase.  The argument is the passwd structure
  * for the current user.   * for the current user.
Line 613 
Line 830 
 }  }
   
 /*  /*
    * Print the SSHFP RR.
    */
   static void
   do_print_resource_record(struct passwd *pw, char *hname)
   {
           Key *public;
           char *comment = NULL;
           struct stat st;
   
           if (!have_identity)
                   ask_filename(pw, "Enter file in which the key is");
           if (stat(identity_file, &st) < 0) {
                   perror(identity_file);
                   exit(1);
           }
           public = key_load_public(identity_file, &comment);
           if (public != NULL) {
                   export_dns_rr(hname, public, stdout, print_generic);
                   key_free(public);
                   xfree(comment);
                   exit(0);
           }
           if (comment)
                   xfree(comment);
   
           printf("failed to read v2 public key from %s.\n", identity_file);
           exit(1);
   }
   
   /*
  * Change the comment of a private key file.   * Change the comment of a private key file.
  */   */
 static void  static void
Line 714 
Line 961 
 {  {
         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 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, "  -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");          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, "  -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, "  -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 IETF SECSH to OpenSSH key file.\n");
         fprintf(stderr, "  -l          Show fingerprint of 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");
           fprintf(stderr, "  -P phrase   Provide old passphrase.\n");
         fprintf(stderr, "  -p          Change passphrase of private key file.\n");          fprintf(stderr, "  -p          Change passphrase of private key file.\n");
         fprintf(stderr, "  -q          Quiet.\n");          fprintf(stderr, "  -q          Quiet.\n");
         fprintf(stderr, "  -y          Read private key file and print public key.\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");          fprintf(stderr, "  -t type     Specify type of key to create.\n");
         fprintf(stderr, "  -B          Show bubblebabble digest of key file.\n");  
         fprintf(stderr, "  -C comment  Provide new comment.\n");  
         fprintf(stderr, "  -N phrase   Provide new passphrase.\n");  
         fprintf(stderr, "  -P phrase   Provide old passphrase.\n");  
 #ifdef SMARTCARD  #ifdef SMARTCARD
         fprintf(stderr, "  -D reader   Download public key from smartcard.\n");  
         fprintf(stderr, "  -U reader   Upload private key to smartcard.\n");          fprintf(stderr, "  -U reader   Upload private key to smartcard.\n");
 #endif /* SMARTCARD */  #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");
   
         exit(1);          exit(1);
 }  }
Line 743 
Line 1004 
 main(int ac, char **av)  main(int ac, char **av)
 {  {
         char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;          char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
         char *reader_id = NULL;          char out_file[MAXPATHLEN], *reader_id = NULL;
           char *rr_hostname = NULL;
         Key *private, *public;          Key *private, *public;
         struct passwd *pw;          struct passwd *pw;
         struct stat st;          struct stat st;
         int opt, type, fd, download = 0;          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;          FILE *f;
           const char *errstr;
   
         extern int optind;          extern int optind;
         extern char *optarg;          extern char *optarg;
   
           /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
           sanitise_stdfd();
   
         SSLeay_add_all_algorithms();          SSLeay_add_all_algorithms();
           log_init(av[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
   
         /* we need this for the home * directory.  */          /* we need this for the home * directory.  */
         pw = getpwuid(getuid());          pw = getpwuid(getuid());
Line 766 
Line 1037 
                 exit(1);                  exit(1);
         }          }
   
         while ((opt = getopt(ac, av, "deiqpclBRxXyb:f:t:U:D:P:N:C:")) != -1) {          while ((opt = getopt(ac, av,
               "degiqpclBHvxXyF:b:f:t:U:D:P:N:C:r:g:R:T:G:M:S:a:W:")) != -1) {
                 switch (opt) {                  switch (opt) {
                 case 'b':                  case 'b':
                         bits = atoi(optarg);                          bits = strtonum(optarg, 512, 32768, &errstr);
                         if (bits < 512 || bits > 32768) {                          if (errstr)
                                 printf("Bits has bad value.\n");                                  fatal("Bits has bad value %s (%s)",
                                 exit(1);                                          optarg, errstr);
                         }  
                         break;                          break;
                   case 'F':
                           find_host = 1;
                           rr_hostname = optarg;
                           break;
                   case 'H':
                           hash_hosts = 1;
                           break;
                   case 'R':
                           delete_host = 1;
                           rr_hostname = optarg;
                           break;
                 case 'l':                  case 'l':
                         print_fingerprint = 1;                          print_fingerprint = 1;
                         break;                          break;
Line 788 
Line 1070 
                         change_comment = 1;                          change_comment = 1;
                         break;                          break;
                 case 'f':                  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;                          have_identity = 1;
                         break;                          break;
                   case 'g':
                           print_generic = 1;
                           break;
                 case 'P':                  case 'P':
                         identity_passphrase = optarg;                          identity_passphrase = optarg;
                         break;                          break;
Line 803 
Line 1090 
                 case 'q':                  case 'q':
                         quiet = 1;                          quiet = 1;
                         break;                          break;
                 case 'R':  
                         /* unused */  
                         exit(0);  
                         break;  
                 case 'e':                  case 'e':
                 case 'x':                  case 'x':
                         /* export key */                          /* export key */
Line 831 
Line 1114 
                 case 'U':                  case 'U':
                         reader_id = optarg;                          reader_id = optarg;
                         break;                          break;
                   case 'v':
                           if (log_level == SYSLOG_LEVEL_INFO)
                                   log_level = SYSLOG_LEVEL_DEBUG1;
                           else {
                                   if (log_level >= SYSLOG_LEVEL_DEBUG1 &&
                                       log_level < SYSLOG_LEVEL_DEBUG3)
                                           log_level++;
                           }
                           break;
                   case 'r':
                           rr_hostname = optarg;
                           break;
                   case 'W':
                           generator_wanted = 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);
                           if (errstr)
                                   fatal("Invalid number of trials: %s (%s)",
                                           optarg, errstr);
                           break;
                   case 'M':
                           memory = strtonum(optarg, 1, UINT_MAX, &errstr);
                           if (errstr) {
                                   fatal("Memory limit is %s: %s", errstr, optarg);
                           }
                           break;
                   case 'G':
                           do_gen_candidates = 1;
                           if (strlcpy(out_file, optarg, sizeof(out_file)) >=
                               sizeof(out_file))
                                   fatal("Output filename too long");
                           break;
                   case 'T':
                           do_screen_candidates = 1;
                           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 */
                           if (BN_hex2bn(&start, optarg) == 0)
                                   fatal("Invalid start point.");
                           break;
                 case '?':                  case '?':
                 default:                  default:
                         usage();                          usage();
                 }                  }
         }          }
   
           /* reinit */
           log_init(av[0], log_level, SYSLOG_FACILITY_USER, 1);
   
         if (optind < ac) {          if (optind < ac) {
                 printf("Too many arguments.\n");                  printf("Too many arguments.\n");
                 usage();                  usage();
Line 844 
Line 1178 
                 printf("Can only have one of -p and -c.\n");                  printf("Can only have one of -p and -c.\n");
                 usage();                  usage();
         }          }
           if (delete_host || hash_hosts || find_host)
                   do_known_hosts(pw, rr_hostname);
         if (print_fingerprint || print_bubblebabble)          if (print_fingerprint || print_bubblebabble)
                 do_fingerprint(pw);                  do_fingerprint(pw);
         if (change_passphrase)          if (change_passphrase)
Line 856 
Line 1192 
                 do_convert_from_ssh2(pw);                  do_convert_from_ssh2(pw);
         if (print_public)          if (print_public)
                 do_print_public(pw);                  do_print_public(pw);
           if (rr_hostname != NULL) {
                   do_print_resource_record(pw, rr_hostname);
           }
         if (reader_id != NULL) {          if (reader_id != NULL) {
 #ifdef SMARTCARD  #ifdef SMARTCARD
                 if (download)                  if (download)
Line 867 
Line 1206 
 #endif /* SMARTCARD */  #endif /* SMARTCARD */
         }          }
   
           if (do_gen_candidates) {
                   FILE *out = fopen(out_file, "w");
   
                   if (out == NULL) {
                           error("Couldn't open modulus candidate file \"%s\": %s",
                               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");
   
                   return (0);
           }
   
           if (do_screen_candidates) {
                   FILE *in;
                   FILE *out = fopen(out_file, "w");
   
                   if (have_identity && strcmp(identity_file, "-") != 0) {
                           if ((in = fopen(identity_file, "r")) == NULL) {
                                   fatal("Couldn't open modulus candidate "
                                       "file \"%s\": %s", identity_file,
                                       strerror(errno));
                           }
                   } else
                           in = stdin;
   
                   if (out == NULL) {
                           fatal("Couldn't open moduli file \"%s\": %s",
                               out_file, strerror(errno));
                   }
                   if (prime_test(in, out, trials, generator_wanted) != 0)
                           fatal("modulus screening failed\n");
                   return (0);
           }
   
         arc4random_stir();          arc4random_stir();
   
         if (key_type_name == NULL) {          if (key_type_name == NULL) {
Line 880 
Line 1257 
         }          }
         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);
           if (bits == 0)
                   bits = (type == KEY_DSA) ? DEFAULT_BITS_DSA : DEFAULT_BITS;
         private = key_generate(type, bits);          private = key_generate(type, bits);
         if (private == NULL) {          if (private == NULL) {
                 fprintf(stderr, "key_generate failed");                  fprintf(stderr, "key_generate failed");

Legend:
Removed from v.1.102  
changed lines
  Added in v.1.130