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

Diff for /src/usr.bin/ssh/ssh-agent.c between version 1.237 and 1.238

version 1.237, 2019/06/28 13:35:04 version 1.238, 2019/10/31 21:22:01
Line 41 
Line 41 
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/un.h>  #include <sys/un.h>
   #include <sys/wait.h>
   
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
 #include <openssl/evp.h>  #include <openssl/evp.h>
Line 70 
Line 71 
 #include "digest.h"  #include "digest.h"
 #include "ssherr.h"  #include "ssherr.h"
 #include "match.h"  #include "match.h"
   #include "msg.h"
 #ifdef ENABLE_PKCS11  #include "pathnames.h"
 #include "ssh-pkcs11.h"  #include "ssh-pkcs11.h"
 #endif  #include "ssh-sk.h"
   
 #ifndef DEFAULT_PKCS11_WHITELIST  #ifndef DEFAULT_PROVIDER_WHITELIST
 # define DEFAULT_PKCS11_WHITELIST "/usr/lib*/*,/usr/local/lib*/*"  # define DEFAULT_PROVIDER_WHITELIST "/usr/lib*/*,/usr/local/lib*/*"
 #endif  #endif
   
 /* Maximum accepted message length */  /* Maximum accepted message length */
Line 108 
Line 109 
         char *provider;          char *provider;
         time_t death;          time_t death;
         u_int confirm;          u_int confirm;
           char *sk_provider;
 } Identity;  } Identity;
   
 struct idtable {  struct idtable {
Line 131 
Line 133 
 char socket_name[PATH_MAX];  char socket_name[PATH_MAX];
 char socket_dir[PATH_MAX];  char socket_dir[PATH_MAX];
   
 /* PKCS#11 path whitelist */  /* PKCS#11/Security key path whitelist */
 static char *pkcs11_whitelist;  static char *provider_whitelist;
   
 /* locking */  /* locking */
 #define LOCK_SIZE       32  #define LOCK_SIZE       32
Line 174 
Line 176 
         sshkey_free(id->key);          sshkey_free(id->key);
         free(id->provider);          free(id->provider);
         free(id->comment);          free(id->comment);
           free(id->sk_provider);
         free(id);          free(id);
 }  }
   
Line 263 
Line 266 
         return NULL;          return NULL;
 }  }
   
   static int
   provider_sign(const char *provider, struct sshkey *key,
       u_char **sigp, size_t *lenp,
       const u_char *data, size_t datalen,
       const char *alg, u_int compat)
   {
           int status, pair[2], r = SSH_ERR_INTERNAL_ERROR;
           pid_t pid;
           char *helper, *verbosity = NULL;
           struct sshbuf *kbuf, *req, *resp;
           u_char version;
   
           debug3("%s: start for provider %s", __func__, provider);
   
           *sigp = NULL;
           *lenp = 0;
   
           helper = getenv("SSH_SK_HELPER");
           if (helper == NULL || strlen(helper) == 0)
                   helper = _PATH_SSH_SK_HELPER;
           if (log_level_get() >= SYSLOG_LEVEL_DEBUG1)
                   verbosity = "-vvv";
   
           /* Start helper */
           if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) {
                   error("socketpair: %s", strerror(errno));
                   return SSH_ERR_SYSTEM_ERROR;
           }
           if ((pid = fork()) == -1) {
                   error("fork: %s", strerror(errno));
                   close(pair[0]);
                   close(pair[1]);
                   return SSH_ERR_SYSTEM_ERROR;
           }
           if (pid == 0) {
                   if ((dup2(pair[1], STDIN_FILENO) == -1) ||
                       (dup2(pair[1], STDOUT_FILENO) == -1))
                           fatal("%s: dup2: %s", __func__, ssh_err(r));
                   close(pair[0]);
                   close(pair[1]);
                   closefrom(STDERR_FILENO + 1);
                   debug("%s: starting %s %s", __func__, helper,
                       verbosity == NULL ? "" : verbosity);
                   execlp(helper, helper, verbosity, (char *)NULL);
                   fatal("%s: execlp: %s", __func__, strerror(errno));
           }
           close(pair[1]);
   
           if ((kbuf = sshbuf_new()) == NULL ||
               (req = sshbuf_new()) == NULL ||
               (resp = sshbuf_new()) == NULL)
                   fatal("%s: sshbuf_new failed", __func__);
   
           if ((r = sshkey_private_serialize(key, kbuf)) != 0 ||
               (r = sshbuf_put_stringb(req, kbuf)) != 0 ||
               (r = sshbuf_put_cstring(req, provider)) != 0 ||
               (r = sshbuf_put_string(req, data, datalen)) != 0 ||
               (r = sshbuf_put_u32(req, compat)) != 0)
                   fatal("%s: compose: %s", __func__, ssh_err(r));
           if ((r = ssh_msg_send(pair[0], SSH_SK_HELPER_VERSION, req)) != 0) {
                   error("%s: send: %s", __func__, ssh_err(r));
                   goto out;
           }
           if ((r = ssh_msg_recv(pair[0], resp)) != 0) {
                   error("%s: receive: %s", __func__, ssh_err(r));
                   goto out;
           }
           if ((r = sshbuf_get_u8(resp, &version)) != 0) {
                   error("%s: parse version: %s", __func__, ssh_err(r));
                   goto out;
           }
           if (version != SSH_SK_HELPER_VERSION) {
                   error("%s: unsupported version: got %u, expected %u",
                       __func__, version, SSH_SK_HELPER_VERSION);
                   r = SSH_ERR_INVALID_FORMAT;
                   goto out;
           }
           if ((r = sshbuf_get_string(resp, sigp, lenp)) != 0) {
                   error("%s: parse signature: %s", __func__, ssh_err(r));
                   r = SSH_ERR_INVALID_FORMAT;
                   goto out;
           }
           if (sshbuf_len(resp) != 0) {
                   error("%s: trailing data in response", __func__);
                   r = SSH_ERR_INVALID_FORMAT;
                   goto out;
           }
           /* success */
           r = 0;
    out:
           while (waitpid(pid, &status, 0) == -1) {
                   if (errno != EINTR)
                           fatal("%s: waitpid: %s", __func__, ssh_err(r));
           }
           if (!WIFEXITED(status)) {
                   error("%s: helper %s exited abnormally", __func__, helper);
                   if (r == 0)
                           r = SSH_ERR_SYSTEM_ERROR;
           } else if (WEXITSTATUS(status) != 0) {
                   error("%s: helper %s exited with non-zero exit status",
                       __func__, helper);
                   if (r == 0)
                           r = SSH_ERR_SYSTEM_ERROR;
           }
           if (r != 0) {
                   freezero(*sigp, *lenp);
                   *sigp = NULL;
                   *lenp = 0;
           }
           sshbuf_free(kbuf);
           sshbuf_free(req);
           sshbuf_free(resp);
           return r;
   }
   
 /* ssh2 only */  /* ssh2 only */
 static void  static void
 process_sign_request2(SocketEntry *e)  process_sign_request2(SocketEntry *e)
Line 293 
Line 411 
                 verbose("%s: user refused key", __func__);                  verbose("%s: user refused key", __func__);
                 goto send;                  goto send;
         }          }
         if ((r = sshkey_sign(id->key, &signature, &slen,          if (id->sk_provider != NULL) {
             data, dlen, agent_decode_alg(key, flags), compat)) != 0) {                  if ((r = provider_sign(id->sk_provider, id->key, &signature,
                 error("%s: sshkey_sign: %s", __func__, ssh_err(r));                      &slen, data, dlen, agent_decode_alg(key, flags),
                 goto send;                      compat)) != 0) {
                           error("%s: sshkey_sign: %s", __func__, ssh_err(r));
                           goto send;
                   }
           } else {
                   if ((r = sshkey_sign(id->key, &signature, &slen,
                       data, dlen, agent_decode_alg(key, flags), compat)) != 0) {
                           error("%s: sshkey_sign: %s", __func__, ssh_err(r));
                           goto send;
                   }
         }          }
         /* Success */          /* Success */
         ok = 0;          ok = 0;
Line 396 
Line 523 
         Identity *id;          Identity *id;
         int success = 0, confirm = 0;          int success = 0, confirm = 0;
         u_int seconds, maxsign;          u_int seconds, maxsign;
         char *comment = NULL;          char *fp, *comment = NULL, *ext_name = NULL, *sk_provider = NULL;
         time_t death = 0;          time_t death = 0;
         struct sshkey *k = NULL;          struct sshkey *k = NULL;
         u_char ctype;          u_char ctype;
Line 441 
Line 568 
                                 goto err;                                  goto err;
                         }                          }
                         break;                          break;
                   case SSH_AGENT_CONSTRAIN_EXTENSION:
                           if ((r = sshbuf_get_cstring(e->request,
                               &ext_name, NULL)) != 0) {
                                   error("%s: cannot parse extension: %s",
                                       __func__, ssh_err(r));
                                   goto err;
                           }
                           debug("%s: constraint ext %s", __func__, ext_name);
                           if (strcmp(ext_name, "sk-provider@openssh.com") == 0) {
                                   if (sk_provider != NULL) {
                                           error("%s already set", ext_name);
                                           goto err;
                                   }
                                   if ((r = sshbuf_get_cstring(e->request,
                                       &sk_provider, NULL)) != 0) {
                                           error("%s: cannot parse %s: %s",
                                               __func__, ext_name, ssh_err(r));
                                           goto err;
                                   }
                           } else {
                                   error("%s: unsupported constraint \"%s\"",
                                       __func__, ext_name);
                                   goto err;
                           }
                           free(ext_name);
                           break;
                 default:                  default:
                         error("%s: Unknown constraint %d", __func__, ctype);                          error("%s: Unknown constraint %d", __func__, ctype);
  err:   err:
                           free(sk_provider);
                           free(ext_name);
                         sshbuf_reset(e->request);                          sshbuf_reset(e->request);
                         free(comment);                          free(comment);
                         sshkey_free(k);                          sshkey_free(k);
                         goto send;                          goto send;
                 }                  }
         }          }
           if (sk_provider != NULL) {
                   if (sshkey_type_plain(k->type) != KEY_ECDSA_SK) {
                           error("Cannot add provider: %s is not a security key",
                               sshkey_type(k));
                           free(sk_provider);
                           goto send;
                   }
                   if (match_pattern_list(sk_provider,
                       provider_whitelist, 0) != 1) {
                           error("Refusing add key: provider %s not whitelisted",
                               sk_provider);
                           free(sk_provider);
                           goto send;
                   }
           }
   
         success = 1;          success = 1;
         if (lifetime && !death)          if (lifetime && !death)
Line 463 
Line 633 
                 /* key state might have been updated */                  /* key state might have been updated */
                 sshkey_free(id->key);                  sshkey_free(id->key);
                 free(id->comment);                  free(id->comment);
                   free(id->sk_provider);
         }          }
         id->key = k;          id->key = k;
         id->comment = comment;          id->comment = comment;
         id->death = death;          id->death = death;
         id->confirm = confirm;          id->confirm = confirm;
           id->sk_provider = sk_provider;
   
           if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT,
               SSH_FP_DEFAULT)) == NULL)
                   fatal("%s: sshkey_fingerprint failed", __func__);
           debug("%s: add %s %s \"%.100s\" (life: %u) (confirm: %u) "
               "(provider: %s)", __func__, sshkey_ssh_name(k), fp, comment,
               seconds, confirm, sk_provider == NULL ? "none" : sk_provider);
           free(fp);
 send:  send:
         send_status(e, success);          send_status(e, success);
 }  }
Line 585 
Line 765 
                     provider, strerror(errno));                      provider, strerror(errno));
                 goto send;                  goto send;
         }          }
         if (match_pattern_list(canonical_provider, pkcs11_whitelist, 0) != 1) {          if (match_pattern_list(canonical_provider, provider_whitelist, 0) != 1) {
                 verbose("refusing PKCS#11 add of \"%.100s\": "                  verbose("refusing PKCS#11 add of \"%.100s\": "
                     "provider not whitelisted", canonical_provider);                      "provider not whitelisted", canonical_provider);
                 goto send;                  goto send;
Line 1064 
Line 1244 
 {  {
         fprintf(stderr,          fprintf(stderr,
             "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"              "usage: ssh-agent [-c | -s] [-Dd] [-a bind_address] [-E fingerprint_hash]\n"
             "                 [-P pkcs11_whitelist] [-t life] [command [arg ...]]\n"              "                 [-P provider_whitelist] [-t life] [command [arg ...]]\n"
             "       ssh-agent [-c | -s] -k\n");              "       ssh-agent [-c | -s] -k\n");
         exit(1);          exit(1);
 }  }
Line 1117 
Line 1297 
                         k_flag++;                          k_flag++;
                         break;                          break;
                 case 'P':                  case 'P':
                         if (pkcs11_whitelist != NULL)                          if (provider_whitelist != NULL)
                                 fatal("-P option already specified");                                  fatal("-P option already specified");
                         pkcs11_whitelist = xstrdup(optarg);                          provider_whitelist = xstrdup(optarg);
                         break;                          break;
                 case 's':                  case 's':
                         if (c_flag)                          if (c_flag)
Line 1155 
Line 1335 
         if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag))          if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || D_flag))
                 usage();                  usage();
   
         if (pkcs11_whitelist == NULL)          if (provider_whitelist == NULL)
                 pkcs11_whitelist = xstrdup(DEFAULT_PKCS11_WHITELIST);                  provider_whitelist = xstrdup(DEFAULT_PROVIDER_WHITELIST);
   
         if (ac == 0 && !c_flag && !s_flag) {          if (ac == 0 && !c_flag && !s_flag) {
                 shell = getenv("SHELL");                  shell = getenv("SHELL");

Legend:
Removed from v.1.237  
changed lines
  Added in v.1.238