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

Diff for /src/usr.bin/ssh/ssh-pkcs11-helper.c between version 1.13 and 1.14

version 1.13, 2017/05/30 08:52:19 version 1.14, 2018/01/08 15:18:46
Line 25 
Line 25 
 #include <errno.h>  #include <errno.h>
   
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "buffer.h"  #include "sshbuf.h"
 #include "log.h"  #include "log.h"
 #include "misc.h"  #include "misc.h"
 #include "key.h"  #include "sshkey.h"
 #include "authfd.h"  #include "authfd.h"
 #include "ssh-pkcs11.h"  #include "ssh-pkcs11.h"
   #include "ssherr.h"
   
 /* borrows code from sftp-server and ssh-agent */  /* borrows code from sftp-server and ssh-agent */
   
Line 44 
Line 45 
   
 #define MAX_MSG_LENGTH          10240 /*XXX*/  #define MAX_MSG_LENGTH          10240 /*XXX*/
   
 /* helper */  
 #define get_int()                       buffer_get_int(&iqueue);  
 #define get_string(lenp)                buffer_get_string(&iqueue, lenp);  
   
 /* input and output queue */  /* input and output queue */
 Buffer iqueue;  struct sshbuf *iqueue;
 Buffer oqueue;  struct sshbuf *oqueue;
   
 static void  static void
 add_key(struct sshkey *k, char *name)  add_key(struct sshkey *k, char *name)
Line 73 
Line 70 
                 if (!strcmp(ki->providername, name)) {                  if (!strcmp(ki->providername, name)) {
                         TAILQ_REMOVE(&pkcs11_keylist, ki, next);                          TAILQ_REMOVE(&pkcs11_keylist, ki, next);
                         free(ki->providername);                          free(ki->providername);
                         key_free(ki->key);                          sshkey_free(ki->key);
                         free(ki);                          free(ki);
                 }                  }
         }          }
Line 87 
Line 84 
   
         TAILQ_FOREACH(ki, &pkcs11_keylist, next) {          TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
                 debug("check %p %s", ki, ki->providername);                  debug("check %p %s", ki, ki->providername);
                 if (key_equal(k, ki->key))                  if (sshkey_equal(k, ki->key))
                         return (ki->key);                          return (ki->key);
         }          }
         return (NULL);          return (NULL);
 }  }
   
 static void  static void
 send_msg(Buffer *m)  send_msg(struct sshbuf *m)
 {  {
         int mlen = buffer_len(m);          int r;
   
         buffer_put_int(&oqueue, mlen);          if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
         buffer_append(&oqueue, buffer_ptr(m), mlen);                  fatal("%s: buffer error: %s", __func__, ssh_err(r));
         buffer_consume(m, mlen);  
 }  }
   
 static void  static void
Line 108 
Line 104 
 {  {
         char *name, *pin;          char *name, *pin;
         struct sshkey **keys;          struct sshkey **keys;
         int i, nkeys;          int r, i, nkeys;
         u_char *blob;          u_char *blob;
         u_int blen;          size_t blen;
         Buffer msg;          struct sshbuf *msg;
   
         buffer_init(&msg);          if ((msg = sshbuf_new()) == NULL)
         name = get_string(NULL);                  fatal("%s: sshbuf_new failed", __func__);
         pin = get_string(NULL);          if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
               (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
                   fatal("%s: buffer error: %s", __func__, ssh_err(r));
         if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) {          if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) {
                 buffer_put_char(&msg, SSH2_AGENT_IDENTITIES_ANSWER);                  if ((r = sshbuf_put_u8(msg,
                 buffer_put_int(&msg, nkeys);                      SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
                       (r = sshbuf_put_u32(msg, nkeys)) != 0)
                           fatal("%s: buffer error: %s", __func__, ssh_err(r));
                 for (i = 0; i < nkeys; i++) {                  for (i = 0; i < nkeys; i++) {
                         if (key_to_blob(keys[i], &blob, &blen) == 0)                          if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) {
                                   debug("%s: sshkey_to_blob: %s",
                                       __func__, ssh_err(r));
                                 continue;                                  continue;
                         buffer_put_string(&msg, blob, blen);                          }
                         buffer_put_cstring(&msg, name);                          if ((r = sshbuf_put_string(msg, blob, blen)) != 0 ||
                               (r = sshbuf_put_cstring(msg, name)) != 0)
                                   fatal("%s: buffer error: %s",
                                       __func__, ssh_err(r));
                         free(blob);                          free(blob);
                         add_key(keys[i], name);                          add_key(keys[i], name);
                 }                  }
                 free(keys);                  free(keys);
         } else {          } else {
                 buffer_put_char(&msg, SSH_AGENT_FAILURE);                  if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
                           fatal("%s: buffer error: %s", __func__, ssh_err(r));
         }          }
         free(pin);          free(pin);
         free(name);          free(name);
         send_msg(&msg);          send_msg(msg);
         buffer_free(&msg);          sshbuf_free(msg);
 }  }
   
 static void  static void
 process_del(void)  process_del(void)
 {  {
         char *name, *pin;          char *name, *pin;
         Buffer msg;          struct sshbuf *msg;
           int r;
   
         buffer_init(&msg);          if ((msg = sshbuf_new()) == NULL)
         name = get_string(NULL);                  fatal("%s: sshbuf_new failed", __func__);
         pin = get_string(NULL);          if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
               (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
                   fatal("%s: buffer error: %s", __func__, ssh_err(r));
         del_keys_by_name(name);          del_keys_by_name(name);
         if (pkcs11_del_provider(name) == 0)          if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ?
                  buffer_put_char(&msg, SSH_AGENT_SUCCESS);              SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
         else                  fatal("%s: buffer error: %s", __func__, ssh_err(r));
                  buffer_put_char(&msg, SSH_AGENT_FAILURE);  
         free(pin);          free(pin);
         free(name);          free(name);
         send_msg(&msg);          send_msg(msg);
         buffer_free(&msg);          sshbuf_free(msg);
 }  }
   
 static void  static void
 process_sign(void)  process_sign(void)
 {  {
         u_char *blob, *data, *signature = NULL;          u_char *blob, *data, *signature = NULL;
         u_int blen, dlen, slen = 0;          size_t blen, dlen, slen = 0;
         int ok = -1;          int r, ok = -1;
         struct sshkey *key, *found;          struct sshkey *key, *found;
         Buffer msg;          struct sshbuf *msg;
   
         blob = get_string(&blen);          /* XXX support SHA2 signature flags */
         data = get_string(&dlen);          if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 ||
         (void)get_int(); /* XXX ignore flags */              (r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 ||
               (r = sshbuf_get_u32(iqueue, NULL)) != 0)
                   fatal("%s: buffer error: %s", __func__, ssh_err(r));
   
         if ((key = key_from_blob(blob, blen)) != NULL) {          if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
                   error("%s: sshkey_from_blob: %s", __func__, ssh_err(r));
           else {
                 if ((found = lookup_key(key)) != NULL) {                  if ((found = lookup_key(key)) != NULL) {
 #ifdef WITH_OPENSSL  #ifdef WITH_OPENSSL
                         int ret;                          int ret;
Line 184 
Line 196 
                         }                          }
 #endif /* WITH_OPENSSL */  #endif /* WITH_OPENSSL */
                 }                  }
                 key_free(key);                  sshkey_free(key);
         }          }
         buffer_init(&msg);          if ((msg = sshbuf_new()) == NULL)
                   fatal("%s: sshbuf_new failed", __func__);
         if (ok == 0) {          if (ok == 0) {
                 buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);                  if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
                 buffer_put_string(&msg, signature, slen);                      (r = sshbuf_put_string(msg, signature, slen)) != 0)
                           fatal("%s: buffer error: %s", __func__, ssh_err(r));
         } else {          } else {
                 buffer_put_char(&msg, SSH_AGENT_FAILURE);                  if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0)
                           fatal("%s: buffer error: %s", __func__, ssh_err(r));
         }          }
         free(data);          free(data);
         free(blob);          free(blob);
         free(signature);          free(signature);
         send_msg(&msg);          send_msg(msg);
         buffer_free(&msg);          sshbuf_free(msg);
 }  }
   
 static void  static void
Line 206 
Line 221 
         u_int msg_len;          u_int msg_len;
         u_int buf_len;          u_int buf_len;
         u_int consumed;          u_int consumed;
         u_int type;          u_char type;
         u_char *cp;          const u_char *cp;
           int r;
   
         buf_len = buffer_len(&iqueue);          buf_len = sshbuf_len(iqueue);
         if (buf_len < 5)          if (buf_len < 5)
                 return;         /* Incomplete message. */                  return;         /* Incomplete message. */
         cp = buffer_ptr(&iqueue);          cp = sshbuf_ptr(iqueue);
         msg_len = get_u32(cp);          msg_len = get_u32(cp);
         if (msg_len > MAX_MSG_LENGTH) {          if (msg_len > MAX_MSG_LENGTH) {
                 error("bad message len %d", msg_len);                  error("bad message len %d", msg_len);
Line 220 
Line 236 
         }          }
         if (buf_len < msg_len + 4)          if (buf_len < msg_len + 4)
                 return;                  return;
         buffer_consume(&iqueue, 4);          if ((r = sshbuf_consume(iqueue, 4)) != 0 ||
               (r = sshbuf_get_u8(iqueue, &type)) != 0)
                   fatal("%s: buffer error: %s", __func__, ssh_err(r));
         buf_len -= 4;          buf_len -= 4;
         type = buffer_get_char(&iqueue);  
         switch (type) {          switch (type) {
         case SSH_AGENTC_ADD_SMARTCARD_KEY:          case SSH_AGENTC_ADD_SMARTCARD_KEY:
                 debug("process_add");                  debug("process_add");
Line 241 
Line 258 
                 break;                  break;
         }          }
         /* discard the remaining bytes from the current packet */          /* discard the remaining bytes from the current packet */
         if (buf_len < buffer_len(&iqueue)) {          if (buf_len < sshbuf_len(iqueue)) {
                 error("iqueue grew unexpectedly");                  error("iqueue grew unexpectedly");
                 cleanup_exit(255);                  cleanup_exit(255);
         }          }
         consumed = buf_len - buffer_len(&iqueue);          consumed = buf_len - sshbuf_len(iqueue);
         if (msg_len < consumed) {          if (msg_len < consumed) {
                 error("msg_len %d < consumed %d", msg_len, consumed);                  error("msg_len %d < consumed %d", msg_len, consumed);
                 cleanup_exit(255);                  cleanup_exit(255);
         }          }
         if (msg_len > consumed)          if (msg_len > consumed) {
                 buffer_consume(&iqueue, msg_len - consumed);                  if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
                           fatal("%s: buffer error: %s", __func__, ssh_err(r));
           }
 }  }
   
 void  void
Line 265 
Line 284 
 main(int argc, char **argv)  main(int argc, char **argv)
 {  {
         fd_set *rset, *wset;          fd_set *rset, *wset;
         int in, out, max, log_stderr = 0;          int r, in, out, max, log_stderr = 0;
         ssize_t len, olen, set_size;          ssize_t len, olen, set_size;
         SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;          SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
         LogLevel log_level = SYSLOG_LEVEL_ERROR;          LogLevel log_level = SYSLOG_LEVEL_ERROR;
Line 287 
Line 306 
         if (out > max)          if (out > max)
                 max = out;                  max = out;
   
         buffer_init(&iqueue);          if ((iqueue = sshbuf_new()) == NULL)
         buffer_init(&oqueue);                  fatal("%s: sshbuf_new failed", __func__);
           if ((oqueue = sshbuf_new()) == NULL)
                   fatal("%s: sshbuf_new failed", __func__);
   
         set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);          set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
         rset = xmalloc(set_size);          rset = xmalloc(set_size);
Line 303 
Line 324 
                  * the worst-case length packet it can generate,                   * the worst-case length packet it can generate,
                  * otherwise apply backpressure by stopping reads.                   * otherwise apply backpressure by stopping reads.
                  */                   */
                 if (buffer_check_alloc(&iqueue, sizeof(buf)) &&                  if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
                     buffer_check_alloc(&oqueue, MAX_MSG_LENGTH))                      (r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
                         FD_SET(in, rset);                          FD_SET(in, rset);
                   else if (r != SSH_ERR_NO_BUFFER_SPACE)
                           fatal("%s: buffer error: %s", __func__, ssh_err(r));
   
                 olen = buffer_len(&oqueue);                  olen = sshbuf_len(oqueue);
                 if (olen > 0)                  if (olen > 0)
                         FD_SET(out, wset);                          FD_SET(out, wset);
   
Line 327 
Line 350 
                         } else if (len < 0) {                          } else if (len < 0) {
                                 error("read: %s", strerror(errno));                                  error("read: %s", strerror(errno));
                                 cleanup_exit(1);                                  cleanup_exit(1);
                         } else {                          } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
                                 buffer_append(&iqueue, buf, len);                                  fatal("%s: buffer error: %s",
                                       __func__, ssh_err(r));
                         }                          }
                 }                  }
                 /* send oqueue to stdout */                  /* send oqueue to stdout */
                 if (FD_ISSET(out, wset)) {                  if (FD_ISSET(out, wset)) {
                         len = write(out, buffer_ptr(&oqueue), olen);                          len = write(out, sshbuf_ptr(oqueue), olen);
                         if (len < 0) {                          if (len < 0) {
                                 error("write: %s", strerror(errno));                                  error("write: %s", strerror(errno));
                                 cleanup_exit(1);                                  cleanup_exit(1);
                         } else {                          } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
                                 buffer_consume(&oqueue, len);                                  fatal("%s: buffer error: %s",
                                       __func__, ssh_err(r));
                         }                          }
                 }                  }
   
Line 347 
Line 372 
                  * into the output buffer, otherwise stop processing input                   * into the output buffer, otherwise stop processing input
                  * and let the output queue drain.                   * and let the output queue drain.
                  */                   */
                 if (buffer_check_alloc(&oqueue, MAX_MSG_LENGTH))                  if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
                         process();                          process();
                   else if (r != SSH_ERR_NO_BUFFER_SPACE)
                           fatal("%s: buffer error: %s", __func__, ssh_err(r));
         }          }
 }  }

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14