[BACK]Return to ssh-add.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / crypto / external / bsd / openssh / dist

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/crypto/external/bsd/openssh/dist/ssh-add.c between version 1.1.1.21 and 1.1.1.22

version 1.1.1.21, 2021/04/19 14:38:29 version 1.1.1.22, 2022/02/23 19:04:26
Line 1 
Line 1 
 /* $OpenBSD: ssh-add.c,v 1.160 2021/04/03 06:18:41 djm Exp $ */  /* $OpenBSD: ssh-add.c,v 1.165 2022/02/04 02:49:17 dtucker 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
Line 65 
Line 65 
 #include "digest.h"  #include "digest.h"
 #include "ssh-sk.h"  #include "ssh-sk.h"
 #include "sk-api.h"  #include "sk-api.h"
   #include "hostfile.h"
   
 /* argv0 */  /* argv0 */
 extern char *__progname;  extern char *__progname;
Line 72  extern char *__progname;
Line 73  extern char *__progname;
 /* Default files to add */  /* Default files to add */
 static char *default_files[] = {  static char *default_files[] = {
         _PATH_SSH_CLIENT_ID_RSA,          _PATH_SSH_CLIENT_ID_RSA,
         _PATH_SSH_CLIENT_ID_DSA,  
         _PATH_SSH_CLIENT_ID_ECDSA,          _PATH_SSH_CLIENT_ID_ECDSA,
         _PATH_SSH_CLIENT_ID_ECDSA_SK,          _PATH_SSH_CLIENT_ID_ECDSA_SK,
         _PATH_SSH_CLIENT_ID_ED25519,          _PATH_SSH_CLIENT_ID_ED25519,
         _PATH_SSH_CLIENT_ID_ED25519_SK,          _PATH_SSH_CLIENT_ID_ED25519_SK,
         _PATH_SSH_CLIENT_ID_XMSS,          _PATH_SSH_CLIENT_ID_XMSS,
           _PATH_SSH_CLIENT_ID_DSA,
         NULL          NULL
 };  };
   
Line 224  delete_all(int agent_fd, int qflag)
Line 225  delete_all(int agent_fd, int qflag)
   
 static int  static int
 add_file(int agent_fd, const char *filename, int key_only, int qflag,  add_file(int agent_fd, const char *filename, int key_only, int qflag,
     const char *skprovider)      const char *skprovider, struct dest_constraint **dest_constraints,
       size_t ndest_constraints)
 {  {
         struct sshkey *private, *cert;          struct sshkey *private, *cert;
         char *comment = NULL;          char *comment = NULL;
Line 347  add_file(int agent_fd, const char *filen
Line 349  add_file(int agent_fd, const char *filen
                             "without provider\n", filename);                              "without provider\n", filename);
                         goto out;                          goto out;
                 }                  }
                 if ((private->sk_flags & SSH_SK_USER_VERIFICATION_REQD) != 0) {  
                         fprintf(stderr, "FIDO verify-required key %s is not "  
                             "currently supported by ssh-agent\n", filename);  
                         goto out;  
                 }  
         } else {          } else {
                 /* Don't send provider constraint for other keys */                  /* Don't send provider constraint for other keys */
                 skprovider = NULL;                  skprovider = NULL;
         }          }
   
         if ((r = ssh_add_identity_constrained(agent_fd, private, comment,          if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
             lifetime, confirm, maxsign, skprovider)) == 0) {              lifetime, confirm, maxsign, skprovider,
               dest_constraints, ndest_constraints)) == 0) {
                 ret = 0;                  ret = 0;
                 if (!qflag) {                  if (!qflag) {
                         fprintf(stderr, "Identity added: %s (%s)\n",                          fprintf(stderr, "Identity added: %s (%s)\n",
Line 410  add_file(int agent_fd, const char *filen
Line 408  add_file(int agent_fd, const char *filen
         sshkey_free(cert);          sshkey_free(cert);
   
         if ((r = ssh_add_identity_constrained(agent_fd, private, comment,          if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
             lifetime, confirm, maxsign, skprovider)) != 0) {              lifetime, confirm, maxsign, skprovider,
               dest_constraints, ndest_constraints)) != 0) {
                 error_r(r, "Certificate %s (%s) add failed", certpath,                  error_r(r, "Certificate %s (%s) add failed", certpath,
                     private->cert->key_id);                      private->cert->key_id);
                 goto out;                  goto out;
Line 438  add_file(int agent_fd, const char *filen
Line 437  add_file(int agent_fd, const char *filen
 }  }
   
 static int  static int
 update_card(int agent_fd, int add, const char *id, int qflag)  update_card(int agent_fd, int add, const char *id, int qflag,
       struct dest_constraint **dest_constraints, size_t ndest_constraints)
 {  {
         char *pin = NULL;          char *pin = NULL;
         int r, ret = -1;          int r, ret = -1;
Line 450  update_card(int agent_fd, int add, const
Line 450  update_card(int agent_fd, int add, const
         }          }
   
         if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin,          if ((r = ssh_update_card(agent_fd, add, id, pin == NULL ? "" : pin,
             lifetime, confirm)) == 0) {              lifetime, confirm, dest_constraints, ndest_constraints)) == 0) {
                 ret = 0;                  ret = 0;
                 if (!qflag) {                  if (!qflag) {
                         fprintf(stderr, "Card %s: %s\n",                          fprintf(stderr, "Card %s: %s\n",
Line 571  lock_agent(int agent_fd, int lock)
Line 571  lock_agent(int agent_fd, int lock)
 }  }
   
 static int  static int
 load_resident_keys(int agent_fd, const char *skprovider, int qflag)  load_resident_keys(int agent_fd, const char *skprovider, int qflag,
       struct dest_constraint **dest_constraints, size_t ndest_constraints)
 {  {
         struct sshkey **keys;          struct sshsk_resident_key **srks;
         size_t nkeys, i;          size_t nsrks, i;
           struct sshkey *key;
         int r, ok = 0;          int r, ok = 0;
         char *fp;          char *fp;
   
         pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);          pass = read_passphrase("Enter PIN for authenticator: ", RP_ALLOW_STDIN);
         if ((r = sshsk_load_resident(skprovider, NULL, pass,          if ((r = sshsk_load_resident(skprovider, NULL, pass, 0,
             &keys, &nkeys)) != 0) {              &srks, &nsrks)) != 0) {
                 error_r(r, "Unable to load resident keys");                  error_r(r, "Unable to load resident keys");
                 return r;                  return r;
         }          }
         for (i = 0; i < nkeys; i++) {          for (i = 0; i < nsrks; i++) {
                 if ((fp = sshkey_fingerprint(keys[i],                  key = srks[i]->key;
                   if ((fp = sshkey_fingerprint(key,
                     fingerprint_hash, SSH_FP_DEFAULT)) == NULL)                      fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
                         fatal_f("sshkey_fingerprint failed");                          fatal_f("sshkey_fingerprint failed");
                 if ((r = ssh_add_identity_constrained(agent_fd, keys[i], "",                  if ((r = ssh_add_identity_constrained(agent_fd, key, "",
                     lifetime, confirm, maxsign, skprovider)) != 0) {                      lifetime, confirm, maxsign, skprovider,
                       dest_constraints, ndest_constraints)) != 0) {
                         error("Unable to add key %s %s",                          error("Unable to add key %s %s",
                             sshkey_type(keys[i]), fp);                              sshkey_type(key), fp);
                         free(fp);                          free(fp);
                         ok = r;                          ok = r;
                         continue;                          continue;
Line 600  load_resident_keys(int agent_fd, const c
Line 604  load_resident_keys(int agent_fd, const c
                         ok = 1;                          ok = 1;
                 if (!qflag) {                  if (!qflag) {
                         fprintf(stderr, "Resident identity added: %s %s\n",                          fprintf(stderr, "Resident identity added: %s %s\n",
                             sshkey_type(keys[i]), fp);                              sshkey_type(key), fp);
                         if (lifetime != 0) {                          if (lifetime != 0) {
                                 fprintf(stderr,                                  fprintf(stderr,
                                     "Lifetime set to %d seconds\n", lifetime);                                      "Lifetime set to %d seconds\n", lifetime);
Line 611  load_resident_keys(int agent_fd, const c
Line 615  load_resident_keys(int agent_fd, const c
                         }                          }
                 }                  }
                 free(fp);                  free(fp);
                 sshkey_free(keys[i]);  
         }          }
         free(keys);          sshsk_free_resident_keys(srks, nsrks);
         if (nkeys == 0)          if (nsrks == 0)
                 return SSH_ERR_KEY_NOT_FOUND;                  return SSH_ERR_KEY_NOT_FOUND;
         return ok == 1 ? 0 : ok;          return ok == 1 ? 0 : ok;
 }  }
   
 static int  static int
 do_file(int agent_fd, int deleting, int key_only, char *file, int qflag,  do_file(int agent_fd, int deleting, int key_only, char *file, int qflag,
     const char *skprovider)      const char *skprovider, struct dest_constraint **dest_constraints,
       size_t ndest_constraints)
 {  {
         if (deleting) {          if (deleting) {
                 if (delete_file(agent_fd, file, key_only, qflag) == -1)                  if (delete_file(agent_fd, file, key_only, qflag) == -1)
                         return -1;                          return -1;
         } else {          } else {
                 if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1)                  if (add_file(agent_fd, file, key_only, qflag, skprovider,
                       dest_constraints, ndest_constraints) == -1)
                         return -1;                          return -1;
         }          }
         return 0;          return 0;
 }  }
   
   /* Append string 's' to a NULL-terminated array of strings */
   static void
   stringlist_append(char ***listp, const char *s)
   {
           size_t i = 0;
   
           if (*listp == NULL)
                   *listp = xcalloc(2, sizeof(**listp));
           else {
                   for (i = 0; (*listp)[i] != NULL; i++)
                           ; /* count */
                   *listp = xrecallocarray(*listp, i + 1, i + 2, sizeof(**listp));
           }
           (*listp)[i] = xstrdup(s);
   }
   
   static void
   parse_dest_constraint_hop(const char *s, struct dest_constraint_hop *dch,
       char **hostkey_files)
   {
           char *user = NULL, *host, *os, *path;
           size_t i;
           struct hostkeys *hostkeys;
           const struct hostkey_entry *hke;
           int r, want_ca;
   
           memset(dch, '\0', sizeof(*dch));
           os = xstrdup(s);
           if ((host = strchr(os, '@')) == NULL)
                   host = os;
           else {
                   *host++ = '\0';
                   user = os;
           }
           cleanhostname(host);
           /* Trivial case: username@ (all hosts) */
           if (*host == '\0') {
                   if (user == NULL) {
                           fatal("Invalid key destination constraint \"%s\": "
                               "does not specify user or host", s);
                   }
                   dch->user = xstrdup(user);
                   /* other fields left blank */
                   free(os);
                   return;
           }
           if (hostkey_files == NULL)
                   fatal_f("no hostkey files");
           /* Otherwise we need to look up the keys for this hostname */
           hostkeys = init_hostkeys();
           for (i = 0; hostkey_files[i]; i++) {
                   path = tilde_expand_filename(hostkey_files[i], getuid());
                   debug2_f("looking up host keys for \"%s\" in %s", host, path);
                   load_hostkeys(hostkeys, host, path, 0);
                   free(path);
           }
           dch->user = user == NULL ? NULL : xstrdup(user);
           dch->hostname = xstrdup(host);
           for (i = 0; i < hostkeys->num_entries; i++) {
                   hke = hostkeys->entries + i;
                   want_ca = hke->marker == MRK_CA;
                   if (hke->marker != MRK_NONE && !want_ca)
                           continue;
                   debug3_f("%s%s%s: adding %s %skey from %s:%lu as key %u",
                       user == NULL ? "": user, user == NULL ? "" : "@",
                       host, sshkey_type(hke->key), want_ca ? "CA " : "",
                       hke->file, hke->line, dch->nkeys);
                   dch->keys = xrecallocarray(dch->keys, dch->nkeys,
                       dch->nkeys + 1, sizeof(*dch->keys));
                   dch->key_is_ca = xrecallocarray(dch->key_is_ca, dch->nkeys,
                       dch->nkeys + 1, sizeof(*dch->key_is_ca));
                   if ((r = sshkey_from_private(hke->key,
                       &(dch->keys[dch->nkeys]))) != 0)
                           fatal_fr(r, "sshkey_from_private");
                   dch->key_is_ca[dch->nkeys] = want_ca;
                   dch->nkeys++;
           }
           if (dch->nkeys == 0)
                   fatal("No host keys found for destination \"%s\"", host);
           free_hostkeys(hostkeys);
           free(os);
           return;
   }
   
   static void
   parse_dest_constraint(const char *s, struct dest_constraint ***dcp,
       size_t *ndcp, char **hostkey_files)
   {
           struct dest_constraint *dc;
           char *os, *cp;
   
           dc = xcalloc(1, sizeof(*dc));
           os = xstrdup(s);
           if ((cp = strchr(os, '>')) == NULL) {
                   /* initial hop; no 'from' hop specified */
                   parse_dest_constraint_hop(os, &dc->to, hostkey_files);
           } else {
                   /* two hops specified */
                   *(cp++) = '\0';
                   parse_dest_constraint_hop(os, &dc->from, hostkey_files);
                   parse_dest_constraint_hop(cp, &dc->to, hostkey_files);
                   if (dc->from.user != NULL) {
                           fatal("Invalid key constraint %s: cannot specify "
                               "user on 'from' host", os);
                   }
           }
           /* XXX eliminate or error on duplicates */
           debug2_f("constraint %zu: %s%s%s (%u keys) > %s%s%s (%u keys)", *ndcp,
               dc->from.user ? dc->from.user : "", dc->from.user ? "@" : "",
               dc->from.hostname ? dc->from.hostname : "(ORIGIN)", dc->from.nkeys,
               dc->to.user ? dc->to.user : "", dc->to.user ? "@" : "",
               dc->to.hostname ? dc->to.hostname : "(ANY)", dc->to.nkeys);
           *dcp = xrecallocarray(*dcp, *ndcp, *ndcp + 1, sizeof(**dcp));
           (*dcp)[(*ndcp)++] = dc;
           free(os);
   }
   
   
 static void  static void
 usage(void)  usage(void)
 {  {
         fprintf(stderr,          fprintf(stderr,
 "usage: ssh-add [-cDdKkLlqvXx] [-E fingerprint_hash] [-S provider] [-t life]\n"  "usage: ssh-add [-cDdKkLlqvXx] [-E fingerprint_hash] [-H hostkey_file]\n"
   "               [-h destination_constraint] [-S provider] [-t life]\n"
 #ifdef WITH_XMSS  #ifdef WITH_XMSS
 "               [-M maxsign] [-m minleft]\n"  "               [-M maxsign] [-m minleft]\n"
 #endif  #endif
Line 655  main(int argc, char **argv)
Line 779  main(int argc, char **argv)
         extern int optind;          extern int optind;
         int agent_fd;          int agent_fd;
         char *pkcs11provider = NULL, *skprovider = NULL;          char *pkcs11provider = NULL, *skprovider = NULL;
           char **dest_constraint_strings = NULL, **hostkey_files = NULL;
         int r, i, ch, deleting = 0, ret = 0, key_only = 0, do_download = 0;          int r, i, ch, deleting = 0, ret = 0, key_only = 0, do_download = 0;
         int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;          int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
         SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;          SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
         LogLevel log_level = SYSLOG_LEVEL_INFO;          LogLevel log_level = SYSLOG_LEVEL_INFO;
           struct dest_constraint **dest_constraints = NULL;
           size_t ndest_constraints = 0;
   
         /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */          /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
         sanitise_stdfd();          sanitise_stdfd();
Line 685  main(int argc, char **argv)
Line 812  main(int argc, char **argv)
   
         skprovider = getenv("SSH_SK_PROVIDER");          skprovider = getenv("SSH_SK_PROVIDER");
   
         while ((ch = getopt(argc, argv, "vkKlLcdDTxXE:e:M:m:qs:S:t:")) != -1) {          while ((ch = getopt(argc, argv, "vkKlLcdDTxXE:e:h:H:M:m:qs:S:t:")) != -1) {
                 switch (ch) {                  switch (ch) {
                 case 'v':                  case 'v':
                         if (log_level == SYSLOG_LEVEL_INFO)                          if (log_level == SYSLOG_LEVEL_INFO)
Line 698  main(int argc, char **argv)
Line 825  main(int argc, char **argv)
                         if (fingerprint_hash == -1)                          if (fingerprint_hash == -1)
                                 fatal("Invalid hash algorithm \"%s\"", optarg);                                  fatal("Invalid hash algorithm \"%s\"", optarg);
                         break;                          break;
                   case 'H':
                           stringlist_append(&hostkey_files, optarg);
                           break;
                   case 'h':
                           stringlist_append(&dest_constraint_strings, optarg);
                           break;
                 case 'k':                  case 'k':
                         key_only = 1;                          key_only = 1;
                         break;                          break;
Line 791  main(int argc, char **argv)
Line 924  main(int argc, char **argv)
   
         if (skprovider == NULL)          if (skprovider == NULL)
                 skprovider = "internal";                  skprovider = "internal";
           if (hostkey_files == NULL) {
                   /* use defaults from readconf.c */
                   stringlist_append(&hostkey_files, _PATH_SSH_USER_HOSTFILE);
                   stringlist_append(&hostkey_files, _PATH_SSH_USER_HOSTFILE2);
                   stringlist_append(&hostkey_files, _PATH_SSH_SYSTEM_HOSTFILE);
                   stringlist_append(&hostkey_files, _PATH_SSH_SYSTEM_HOSTFILE2);
           }
           if (dest_constraint_strings != NULL) {
                   for (i = 0; dest_constraint_strings[i] != NULL; i++) {
                           parse_dest_constraint(dest_constraint_strings[i],
                             &dest_constraints, &ndest_constraints, hostkey_files);
                   }
           }
   
         argc -= optind;          argc -= optind;
         argv += optind;          argv += optind;
Line 804  main(int argc, char **argv)
Line 950  main(int argc, char **argv)
         }          }
         if (pkcs11provider != NULL) {          if (pkcs11provider != NULL) {
                 if (update_card(agent_fd, !deleting, pkcs11provider,                  if (update_card(agent_fd, !deleting, pkcs11provider,
                     qflag) == -1)                      qflag, dest_constraints, ndest_constraints) == -1)
                         ret = 1;                          ret = 1;
                 goto done;                  goto done;
         }          }
         if (do_download) {          if (do_download) {
                 if (skprovider == NULL)                  if (skprovider == NULL)
                         fatal("Cannot download keys without provider");                          fatal("Cannot download keys without provider");
                 if (load_resident_keys(agent_fd, skprovider, qflag) != 0)                  if (load_resident_keys(agent_fd, skprovider, qflag,
                       dest_constraints, ndest_constraints) != 0)
                         ret = 1;                          ret = 1;
                 goto done;                  goto done;
         }          }
Line 834  main(int argc, char **argv)
Line 981  main(int argc, char **argv)
                         if (stat(buf, &st) == -1)                          if (stat(buf, &st) == -1)
                                 continue;                                  continue;
                         if (do_file(agent_fd, deleting, key_only, buf,                          if (do_file(agent_fd, deleting, key_only, buf,
                             qflag, skprovider) == -1)                              qflag, skprovider,
                               dest_constraints, ndest_constraints) == -1)
                                 ret = 1;                                  ret = 1;
                         else                          else
                                 count++;                                  count++;
Line 844  main(int argc, char **argv)
Line 992  main(int argc, char **argv)
         } else {          } else {
                 for (i = 0; i < argc; i++) {                  for (i = 0; i < argc; i++) {
                         if (do_file(agent_fd, deleting, key_only,                          if (do_file(agent_fd, deleting, key_only,
                             argv[i], qflag, skprovider) == -1)                              argv[i], qflag, skprovider,
                               dest_constraints, ndest_constraints) == -1)
                                 ret = 1;                                  ret = 1;
                 }                  }
         }          }

Legend:
Removed from v.1.1.1.21  
changed lines
  Added in v.1.1.1.22

CVSweb <webmaster@jp.NetBSD.org>