[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.379 and 1.384

version 1.379, 2019/12/30 09:24:45 version 1.384, 2020/01/21 11:06:09
Line 2145 
Line 2145 
         exit(ok ? 0 : 1);          exit(ok ? 0 : 1);
 }  }
   
 #ifdef WITH_OPENSSL  
 static void  static void
 load_krl(const char *path, struct ssh_krl **krlp)  load_krl(const char *path, struct ssh_krl **krlp)
 {  {
Line 2440 
Line 2439 
         ssh_krl_free(krl);          ssh_krl_free(krl);
         exit(ret);          exit(ret);
 }  }
 #endif  
   
 static struct sshkey *  static struct sshkey *
 load_sign_key(const char *keypath, const struct sshkey *pubkey)  load_sign_key(const char *keypath, const struct sshkey *pubkey)
Line 2853 
Line 2851 
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
 }  }
   
   static char *
   private_key_passphrase(void)
   {
           char *passphrase1, *passphrase2;
   
           /* Ask for a passphrase (twice). */
           if (identity_passphrase)
                   passphrase1 = xstrdup(identity_passphrase);
           else if (identity_new_passphrase)
                   passphrase1 = xstrdup(identity_new_passphrase);
           else {
   passphrase_again:
                   passphrase1 =
                           read_passphrase("Enter passphrase (empty for no "
                               "passphrase): ", RP_ALLOW_STDIN);
                   passphrase2 = read_passphrase("Enter same passphrase again: ",
                       RP_ALLOW_STDIN);
                   if (strcmp(passphrase1, passphrase2) != 0) {
                           /*
                            * The passphrases do not match.  Clear them and
                            * retry.
                            */
                           freezero(passphrase1, strlen(passphrase1));
                           freezero(passphrase2, strlen(passphrase2));
                           printf("Passphrases do not match.  Try again.\n");
                           goto passphrase_again;
                   }
                   /* Clear the other copy of the passphrase. */
                   freezero(passphrase2, strlen(passphrase2));
           }
           return passphrase1;
   }
   
   static const char *
   skip_ssh_url_preamble(const char *s)
   {
           if (strncmp(s, "ssh://", 6) == 0)
                   return s + 6;
           else if (strncmp(s, "ssh:", 4) == 0)
                   return s + 4;
           return s;
   }
   
   static int
   do_download_sk(const char *skprovider, const char *device)
   {
           struct sshkey **keys;
           size_t nkeys, i;
           int r, ok = -1;
           char *fp, *pin, *pass = NULL, *path, *pubpath;
           const char *ext;
   
           if (skprovider == NULL)
                   fatal("Cannot download keys without provider");
   
           pin = read_passphrase("Enter PIN for security key: ", RP_ALLOW_STDIN);
           if ((r = sshsk_load_resident(skprovider, device, pin,
               &keys, &nkeys)) != 0) {
                   freezero(pin, strlen(pin));
                   error("Unable to load resident keys: %s", ssh_err(r));
                   return -1;
           }
           if (nkeys == 0)
                   logit("No keys to download");
           freezero(pin, strlen(pin));
   
           for (i = 0; i < nkeys; i++) {
                   if (keys[i]->type != KEY_ECDSA_SK &&
                       keys[i]->type != KEY_ED25519_SK) {
                           error("Unsupported key type %s (%d)",
                               sshkey_type(keys[i]), keys[i]->type);
                           continue;
                   }
                   if ((fp = sshkey_fingerprint(keys[i],
                       fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
                           fatal("%s: sshkey_fingerprint failed", __func__);
                   debug("%s: key %zu: %s %s %s (flags 0x%02x)", __func__, i,
                       sshkey_type(keys[i]), fp, keys[i]->sk_application,
                       keys[i]->sk_flags);
                   ext = skip_ssh_url_preamble(keys[i]->sk_application);
                   xasprintf(&path, "id_%s_rk%s%s",
                       keys[i]->type == KEY_ECDSA_SK ? "ecdsa_sk" : "ed25519_sk",
                       *ext == '\0' ? "" : "_", ext);
   
                   /* If the file already exists, ask the user to confirm. */
                   if (!confirm_overwrite(path)) {
                           free(path);
                           break;
                   }
   
                   /* Save the key with the application string as the comment */
                   if (pass == NULL)
                           pass = private_key_passphrase();
                   if ((r = sshkey_save_private(keys[i], path, pass,
                       keys[i]->sk_application, private_key_format,
                       openssh_format_cipher, rounds)) != 0) {
                           error("Saving key \"%s\" failed: %s",
                               path, ssh_err(r));
                           free(path);
                           break;
                   }
                   if (!quiet) {
                           printf("Saved %s key%s%s to %s\n",
                               sshkey_type(keys[i]),
                               *ext != '\0' ? " " : "",
                               *ext != '\0' ? keys[i]->sk_application : "",
                               path);
                   }
   
                   /* Save public key too */
                   xasprintf(&pubpath, "%s.pub", path);
                   free(path);
                   if ((r = sshkey_save_public(keys[i], pubpath,
                       keys[i]->sk_application)) != 0) {
                           free(pubpath);
                           error("Saving public key \"%s\" failed: %s",
                               pubpath, ssh_err(r));
                           break;
                   }
                   free(pubpath);
           }
   
           if (i >= nkeys)
                   ok = 0; /* success */
           if (pass != NULL)
                   freezero(pass, strlen(pass));
           for (i = 0; i < nkeys; i++)
                   sshkey_free(keys[i]);
           free(keys);
           return ok ? 0 : -1;
   }
   
 static void  static void
 usage(void)  usage(void)
 {  {
         fprintf(stderr,          fprintf(stderr,
             "usage: ssh-keygen [-q] [-b bits] [-C comment] [-f output_keyfile] [-m format]\n"              "usage: ssh-keygen [-q] [-b bits] [-C comment] [-f output_keyfile] [-m format]\n"
             "                  [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n"              "                  [-t dsa | ecdsa | ecdsa-sk | ed25519 | ed25519-sk | rsa]\n"
             "                  [-N new_passphrase] [-w provider] [-x flags]\n"              "                  [-N new_passphrase] [-O option] [-w provider]\n"
             "       ssh-keygen -p [-f keyfile] [-m format] [-N new_passphrase]\n"              "       ssh-keygen -p [-f keyfile] [-m format] [-N new_passphrase]\n"
             "                   [-P old_passphrase]\n"              "                   [-P old_passphrase]\n"
             "       ssh-keygen -i [-f input_keyfile] [-m key_format]\n"              "       ssh-keygen -i [-f input_keyfile] [-m key_format]\n"
Line 2875 
Line 3005 
         fprintf(stderr,          fprintf(stderr,
             "       ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n"              "       ssh-keygen -F hostname [-lv] [-f known_hosts_file]\n"
             "       ssh-keygen -H [-f known_hosts_file]\n"              "       ssh-keygen -H [-f known_hosts_file]\n"
               "       ssh-keygen -K [-w provider]\n"
             "       ssh-keygen -R hostname [-f known_hosts_file]\n"              "       ssh-keygen -R hostname [-f known_hosts_file]\n"
             "       ssh-keygen -r hostname [-g] [-f input_keyfile]\n"              "       ssh-keygen -r hostname [-g] [-f input_keyfile]\n"
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
             "       ssh-keygen -M generate [-O option] output\n"              "       ssh-keygen -M generate [-O option] output_file\n"
             "       ssh-keygen -M screen [-f input_file] [-O option] [-a rounds] output_file\n"              "       ssh-keygen -M screen [-f input_file] [-O option] output_file\n"
 #endif  #endif
             "       ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"              "       ssh-keygen -I certificate_identity -s ca_key [-hU] [-D pkcs11_provider]\n"
             "                  [-n principals] [-O option] [-V validity_interval]\n"              "                  [-n principals] [-O option] [-V validity_interval]\n"
Line 2902 
Line 3033 
 int  int
 main(int argc, char **argv)  main(int argc, char **argv)
 {  {
         char dotsshdir[PATH_MAX], comment[1024], *passphrase1, *passphrase2;          char dotsshdir[PATH_MAX], comment[1024], *passphrase;
         char *rr_hostname = NULL, *ep, *fp, *ra;          char *rr_hostname = NULL, *ep, *fp, *ra;
         struct sshkey *private, *public;          struct sshkey *private, *public;
         struct passwd *pw;          struct passwd *pw;
         struct stat st;          struct stat st;
         int r, opt, type, fd;          int r, opt, type;
         int change_passphrase = 0, change_comment = 0, show_cert = 0;          int change_passphrase = 0, change_comment = 0, show_cert = 0;
         int find_host = 0, delete_host = 0, hash_hosts = 0;          int find_host = 0, delete_host = 0, hash_hosts = 0;
         int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;          int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
         int prefer_agent = 0, convert_to = 0, convert_from = 0;          int prefer_agent = 0, convert_to = 0, convert_from = 0;
         int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;          int print_public = 0, print_generic = 0, cert_serial_autoinc = 0;
         int do_gen_candidates = 0, do_screen_candidates = 0;          int do_gen_candidates = 0, do_screen_candidates = 0, download_sk = 0;
         unsigned long long ull, cert_serial = 0;          unsigned long long cert_serial = 0;
         char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL;          char *identity_comment = NULL, *ca_key_path = NULL, **opts = NULL;
           char *sk_application = NULL, *sk_device = NULL, *sk_user = NULL;
         size_t i, nopts = 0;          size_t i, nopts = 0;
         u_int32_t bits = 0;          u_int32_t bits = 0;
         uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD;          uint8_t sk_flags = SSH_SK_USER_PRESENCE_REQD;
         FILE *f;  
         const char *errstr;          const char *errstr;
         int log_level = SYSLOG_LEVEL_INFO;          int log_level = SYSLOG_LEVEL_INFO;
         char *sign_op = NULL;          char *sign_op = NULL;
Line 2946 
Line 3077 
   
         sk_provider = getenv("SSH_SK_PROVIDER");          sk_provider = getenv("SSH_SK_PROVIDER");
   
         /* Remaining characters: dGjJKSTW */          /* Remaining characters: dGjJSTWx */
         while ((opt = getopt(argc, argv, "ABHLQUXceghiklopquvy"          while ((opt = getopt(argc, argv, "ABHKLQUXceghiklopquvy"
             "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"              "C:D:E:F:I:M:N:O:P:R:V:Y:Z:"
             "a:b:f:g:m:n:r:s:t:w:x:z:")) != -1) {              "a:b:f:g:m:n:r:s:t:w:z:")) != -1) {
                 switch (opt) {                  switch (opt) {
                 case 'A':                  case 'A':
                         gen_all_hostkeys = 1;                          gen_all_hostkeys = 1;
Line 3027 
Line 3158 
                 case 'g':                  case 'g':
                         print_generic = 1;                          print_generic = 1;
                         break;                          break;
                   case 'K':
                           download_sk = 1;
                           break;
                 case 'P':                  case 'P':
                         identity_passphrase = optarg;                          identity_passphrase = optarg;
                         break;                          break;
Line 3111 
Line 3245 
                 case 'w':                  case 'w':
                         sk_provider = optarg;                          sk_provider = optarg;
                         break;                          break;
                 case 'x':  
                         if (*optarg == '\0')  
                                 fatal("Missing security key flags");  
                         if (strcasecmp(optarg, "no-touch-required") == 0)  
                                 sk_flags &= ~SSH_SK_USER_PRESENCE_REQD;  
                         else if (strcasecmp(optarg, "resident") == 0)  
                                 sk_flags |= SSH_SK_RESIDENT_KEY;  
                         else {  
                                 ull = strtoull(optarg, &ep, 0);  
                                 if (*ep != '\0')  
                                         fatal("Security key flags \"%s\" is "  
                                             "not a number", optarg);  
                                 if (ull > 0xff) {  
                                         fatal("Invalid security key "  
                                             "flags 0x%llx", ull);  
                                 }  
                                 sk_flags = (uint8_t)ull;  
                         }  
                         break;  
                 case 'z':                  case 'z':
                         errno = 0;                          errno = 0;
                         if (*optarg == '+') {                          if (*optarg == '+') {
Line 3227 
Line 3342 
                 usage();                  usage();
         }          }
         if (gen_krl) {          if (gen_krl) {
 #ifdef WITH_OPENSSL  
                 do_gen_krl(pw, update_krl, ca_key_path,                  do_gen_krl(pw, update_krl, ca_key_path,
                     cert_serial, identity_comment, argc, argv);                      cert_serial, identity_comment, argc, argv);
                 return (0);                  return (0);
 #else  
                 fatal("KRL generation not supported");  
 #endif  
         }          }
         if (check_krl) {          if (check_krl) {
 #ifdef WITH_OPENSSL  
                 do_check_krl(pw, argc, argv);                  do_check_krl(pw, argc, argv);
                 return (0);                  return (0);
 #else  
                 fatal("KRL checking not supported");  
 #endif  
         }          }
         if (ca_key_path != NULL) {          if (ca_key_path != NULL) {
                 if (cert_key_id == NULL)                  if (cert_key_id == NULL)
Line 3259 
Line 3366 
         }          }
         if (pkcs11provider != NULL)          if (pkcs11provider != NULL)
                 do_download(pw);                  do_download(pw);
           if (download_sk) {
                   for (i = 0; i < nopts; i++) {
                           if (strncasecmp(opts[i], "device=", 7) == 0) {
                                   sk_device = xstrdup(opts[i] + 7);
                           } else {
                                   fatal("Option \"%s\" is unsupported for "
                                       "FIDO authenticator download", opts[i]);
                           }
                   }
                   return do_download_sk(sk_provider, sk_device);
           }
         if (print_fingerprint || print_bubblebabble)          if (print_fingerprint || print_bubblebabble)
                 do_fingerprint(pw);                  do_fingerprint(pw);
         if (change_passphrase)          if (change_passphrase)
Line 3340 
Line 3458 
         switch (type) {          switch (type) {
         case KEY_ECDSA_SK:          case KEY_ECDSA_SK:
         case KEY_ED25519_SK:          case KEY_ED25519_SK:
                 passphrase1 = NULL;                  for (i = 0; i < nopts; i++) {
                 for (i = 0 ; i < 3; i++) {                          if (strcasecmp(opts[i], "no-touch-required") == 0) {
                         if (!quiet) {                                  sk_flags &= ~SSH_SK_USER_PRESENCE_REQD;
                                 printf("You may need to touch your security "                          } else if (strcasecmp(opts[i], "resident") == 0) {
                                     "key to authorize key generation.\n");                                  sk_flags |= SSH_SK_RESIDENT_KEY;
                           } else if (strncasecmp(opts[i], "device=", 7) == 0) {
                                   sk_device = xstrdup(opts[i] + 7);
                           } else if (strncasecmp(opts[i], "user=", 5) == 0) {
                                   sk_user = xstrdup(opts[i] + 5);
                           } else if (strncasecmp(opts[i],
                               "application=", 12) == 0) {
                                   sk_application = xstrdup(opts[i] + 12);
                           } else {
                                   fatal("Option \"%s\" is unsupported for "
                                       "FIDO authenticator enrollment", opts[i]);
                         }                          }
                   }
                   if (!quiet) {
                           printf("You may need to touch your security key "
                               "to authorize key generation.\n");
                   }
                   passphrase = NULL;
                   for (i = 0 ; i < 3; i++) {
                         fflush(stdout);                          fflush(stdout);
                         r = sshsk_enroll(type, sk_provider,                          r = sshsk_enroll(type, sk_provider, sk_device,
                             cert_key_id == NULL ? "ssh:" : cert_key_id,                              sk_application == NULL ? "ssh:" : sk_application,
                             sk_flags, passphrase1, NULL, &private, NULL);                              sk_user, sk_flags, passphrase, NULL,
                               &private, NULL);
                         if (r == 0)                          if (r == 0)
                                 break;                                  break;
                         if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)                          if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
                                 exit(1); /* error message already printed */                                  exit(1); /* error message already printed */
                         passphrase1 = read_passphrase("Enter PIN for security "                          if (passphrase != NULL)
                                   freezero(passphrase, strlen(passphrase));
                           passphrase = read_passphrase("Enter PIN for security "
                             "key: ", RP_ALLOW_STDIN);                              "key: ", RP_ALLOW_STDIN);
                 }                  }
                   if (passphrase != NULL)
                           freezero(passphrase, strlen(passphrase));
                 if (i > 3)                  if (i > 3)
                         fatal("Too many incorrect PINs");                          fatal("Too many incorrect PINs");
                 break;                  break;
Line 3389 
Line 3529 
         /* If the file already exists, ask the user to confirm. */          /* If the file already exists, ask the user to confirm. */
         if (!confirm_overwrite(identity_file))          if (!confirm_overwrite(identity_file))
                 exit(1);                  exit(1);
         /* Ask for a passphrase (twice). */  
         if (identity_passphrase)  
                 passphrase1 = xstrdup(identity_passphrase);  
         else if (identity_new_passphrase)  
                 passphrase1 = xstrdup(identity_new_passphrase);  
         else {  
 passphrase_again:  
                 passphrase1 =  
                         read_passphrase("Enter passphrase (empty for no "  
                             "passphrase): ", RP_ALLOW_STDIN);  
                 passphrase2 = read_passphrase("Enter same passphrase again: ",  
                     RP_ALLOW_STDIN);  
                 if (strcmp(passphrase1, passphrase2) != 0) {  
                         /*  
                          * The passphrases do not match.  Clear them and  
                          * retry.  
                          */  
                         explicit_bzero(passphrase1, strlen(passphrase1));  
                         explicit_bzero(passphrase2, strlen(passphrase2));  
                         free(passphrase1);  
                         free(passphrase2);  
                         printf("Passphrases do not match.  Try again.\n");  
                         goto passphrase_again;  
                 }  
                 /* Clear the other copy of the passphrase. */  
                 explicit_bzero(passphrase2, strlen(passphrase2));  
                 free(passphrase2);  
         }  
   
           /* Determine the passphrase for the private key */
           passphrase = private_key_passphrase();
         if (identity_comment) {          if (identity_comment) {
                 strlcpy(comment, identity_comment, sizeof(comment));                  strlcpy(comment, identity_comment, sizeof(comment));
         } else {          } else {
Line 3426 
Line 3540 
         }          }
   
         /* Save the key with the given passphrase and comment. */          /* Save the key with the given passphrase and comment. */
         if ((r = sshkey_save_private(private, identity_file, passphrase1,          if ((r = sshkey_save_private(private, identity_file, passphrase,
             comment, private_key_format, openssh_format_cipher, rounds)) != 0) {              comment, private_key_format, openssh_format_cipher, rounds)) != 0) {
                 error("Saving key \"%s\" failed: %s",                  error("Saving key \"%s\" failed: %s",
                     identity_file, ssh_err(r));                      identity_file, ssh_err(r));
                 explicit_bzero(passphrase1, strlen(passphrase1));                  freezero(passphrase, strlen(passphrase));
                 free(passphrase1);  
                 exit(1);                  exit(1);
         }          }
         /* Clear the passphrase. */          freezero(passphrase, strlen(passphrase));
         explicit_bzero(passphrase1, strlen(passphrase1));  
         free(passphrase1);  
   
         /* Clear the private key and the random number generator. */  
         sshkey_free(private);          sshkey_free(private);
   
         if (!quiet)          if (!quiet) {
                 printf("Your identification has been saved in %s.\n", identity_file);                  printf("Your identification has been saved in %s.\n",
                       identity_file);
           }
   
         strlcat(identity_file, ".pub", sizeof(identity_file));          strlcat(identity_file, ".pub", sizeof(identity_file));
         if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)          if ((r = sshkey_save_public(public, identity_file, comment)) != 0) {
                 fatal("Unable to save public key to %s: %s",                  fatal("Unable to save public key to %s: %s",
                     identity_file, strerror(errno));                      identity_file, strerror(errno));
         if ((f = fdopen(fd, "w")) == NULL)          }
                 fatal("fdopen %s failed: %s", identity_file, strerror(errno));  
         if ((r = sshkey_write(public, f)) != 0)  
                 error("write key failed: %s", ssh_err(r));  
         fprintf(f, " %s\n", comment);  
         if (ferror(f) || fclose(f) != 0)  
                 fatal("write public failed: %s", strerror(errno));  
   
         if (!quiet) {          if (!quiet) {
                 fp = sshkey_fingerprint(public, fingerprint_hash,                  fp = sshkey_fingerprint(public, fingerprint_hash,

Legend:
Removed from v.1.379  
changed lines
  Added in v.1.384