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

Diff for /src/usr.bin/ssh/auth2-pubkey.c between version 1.63 and 1.64

version 1.63, 2017/05/30 08:52:19 version 1.64, 2017/05/30 14:10:53
Line 49 
Line 49 
 #include "misc.h"  #include "misc.h"
 #include "servconf.h"  #include "servconf.h"
 #include "compat.h"  #include "compat.h"
 #include "key.h"  #include "sshkey.h"
 #include "hostfile.h"  #include "hostfile.h"
 #include "auth.h"  #include "auth.h"
 #include "pathnames.h"  #include "pathnames.h"
Line 74 
Line 74 
 static int  static int
 userauth_pubkey(Authctxt *authctxt)  userauth_pubkey(Authctxt *authctxt)
 {  {
         Buffer b;          struct ssh *ssh = active_state; /* XXX */
           struct sshbuf *b;
         struct sshkey *key = NULL;          struct sshkey *key = NULL;
         char *pkalg, *userstyle, *fp = NULL;          char *pkalg, *userstyle = NULL, *fp = NULL;
         u_char *pkblob, *sig;          u_char *pkblob, *sig, have_sig;
         u_int alen, blen, slen;          size_t blen, slen;
         int have_sig, pktype;          int r, pktype;
         int authenticated = 0;          int authenticated = 0;
   
         if (!authctxt->valid) {          if (!authctxt->valid) {
                 debug2("%s: disabled because of invalid user", __func__);                  debug2("%s: disabled because of invalid user", __func__);
                 return 0;                  return 0;
         }          }
         have_sig = packet_get_char();          if ((r = sshpkt_get_u8(ssh, &have_sig)) != 0)
         if (datafellows & SSH_BUG_PKAUTH) {                  fatal("%s: sshpkt_get_u8 failed: %s", __func__, ssh_err(r));
           if (ssh->compat & SSH_BUG_PKAUTH) {
                 debug2("%s: SSH_BUG_PKAUTH", __func__);                  debug2("%s: SSH_BUG_PKAUTH", __func__);
                   if ((b = sshbuf_new()) == NULL)
                           fatal("%s: sshbuf_new failed", __func__);
                 /* no explicit pkalg given */                  /* no explicit pkalg given */
                 pkblob = packet_get_string(&blen);  
                 buffer_init(&b);  
                 buffer_append(&b, pkblob, blen);  
                 /* so we have to extract the pkalg from the pkblob */                  /* so we have to extract the pkalg from the pkblob */
                 pkalg = buffer_get_string(&b, &alen);                  /* XXX use sshbuf_from() */
                 buffer_free(&b);                  if ((r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 ||
                       (r = sshbuf_put(b, pkblob, blen)) != 0 ||
                       (r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0)
                           fatal("%s: failed: %s", __func__, ssh_err(r));
                   sshbuf_free(b);
         } else {          } else {
                 pkalg = packet_get_string(&alen);                  if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 ||
                 pkblob = packet_get_string(&blen);                      (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0)
                           fatal("%s: sshpkt_get_cstring failed: %s",
                               __func__, ssh_err(r));
         }          }
         pktype = key_type_from_name(pkalg);          pktype = sshkey_type_from_name(pkalg);
         if (pktype == KEY_UNSPEC) {          if (pktype == KEY_UNSPEC) {
                 /* this is perfectly legal */                  /* this is perfectly legal */
                 logit("%s: unsupported public key algorithm: %s",                  logit("%s: unsupported public key algorithm: %s",
                     __func__, pkalg);                      __func__, pkalg);
                 goto done;                  goto done;
         }          }
         key = key_from_blob(pkblob, blen);          if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
                   error("%s: could not parse key: %s", __func__, ssh_err(r));
                   goto done;
           }
         if (key == NULL) {          if (key == NULL) {
                 error("%s: cannot decode key: %s", __func__, pkalg);                  error("%s: cannot decode key: %s", __func__, pkalg);
                 goto done;                  goto done;
Line 117 
Line 127 
                     "(received %d, expected %d)", __func__, key->type, pktype);                      "(received %d, expected %d)", __func__, key->type, pktype);
                 goto done;                  goto done;
         }          }
         if (key_type_plain(key->type) == KEY_RSA &&          if (sshkey_type_plain(key->type) == KEY_RSA &&
             (datafellows & SSH_BUG_RSASIGMD5) != 0) {              (ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
                 logit("Refusing RSA key because client uses unsafe "                  logit("Refusing RSA key because client uses unsafe "
                     "signature scheme");                      "signature scheme");
                 goto done;                  goto done;
         }          }
         fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);          fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_DEFAULT);
         if (auth2_userkey_already_used(authctxt, key)) {          if (auth2_userkey_already_used(authctxt, key)) {
                 logit("refusing previously-used %s key", key_type(key));                  logit("refusing previously-used %s key", sshkey_type(key));
                 goto done;                  goto done;
         }          }
         if (match_pattern_list(sshkey_ssh_name(key),          if (match_pattern_list(sshkey_ssh_name(key),
Line 138 
Line 148 
         if (have_sig) {          if (have_sig) {
                 debug3("%s: have signature for %s %s",                  debug3("%s: have signature for %s %s",
                     __func__, sshkey_type(key), fp);                      __func__, sshkey_type(key), fp);
                 sig = packet_get_string(&slen);                  if ((r = sshpkt_get_string(ssh, &sig, &slen)) != 0 ||
                 packet_check_eom();                      (r = sshpkt_get_end(ssh)) != 0)
                 buffer_init(&b);                          fatal("%s: %s", __func__, ssh_err(r));
                 if (datafellows & SSH_OLD_SESSIONID) {                  if ((b = sshbuf_new()) == NULL)
                         buffer_append(&b, session_id2, session_id2_len);                          fatal("%s: sshbuf_new failed", __func__);
                   if (ssh->compat & SSH_OLD_SESSIONID) {
                           if ((r = sshbuf_put(b, session_id2,
                               session_id2_len)) != 0)
                                   fatal("%s: sshbuf_put session id: %s",
                                       __func__, ssh_err(r));
                 } else {                  } else {
                         buffer_put_string(&b, session_id2, session_id2_len);                          if ((r = sshbuf_put_string(b, session_id2,
                               session_id2_len)) != 0)
                                   fatal("%s: sshbuf_put_string session id: %s",
                                       __func__, ssh_err(r));
                 }                  }
                 /* reconstruct packet */                  /* reconstruct packet */
                 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);  
                 xasprintf(&userstyle, "%s%s%s", authctxt->user,                  xasprintf(&userstyle, "%s%s%s", authctxt->user,
                     authctxt->style ? ":" : "",                      authctxt->style ? ":" : "",
                     authctxt->style ? authctxt->style : "");                      authctxt->style ? authctxt->style : "");
                 buffer_put_cstring(&b, userstyle);                  if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
                 free(userstyle);                      (r = sshbuf_put_cstring(b, userstyle)) != 0 ||
                 buffer_put_cstring(&b,                      (r = sshbuf_put_cstring(b, ssh->compat & SSH_BUG_PKSERVICE ?
                     datafellows & SSH_BUG_PKSERVICE ?                      "ssh-userauth" : authctxt->service)) != 0)
                     "ssh-userauth" :                          fatal("%s: build packet failed: %s",
                     authctxt->service);                              __func__, ssh_err(r));
                 if (datafellows & SSH_BUG_PKAUTH) {                  if (ssh->compat & SSH_BUG_PKAUTH) {
                         buffer_put_char(&b, have_sig);                          if ((r = sshbuf_put_u8(b, have_sig)) != 0)
                                   fatal("%s: build packet failed: %s",
                                       __func__, ssh_err(r));
                 } else {                  } else {
                         buffer_put_cstring(&b, "publickey");                          if ((r = sshbuf_put_cstring(b, "publickey")) != 0 ||
                         buffer_put_char(&b, have_sig);                              (r = sshbuf_put_u8(b, have_sig)) != 0 ||
                         buffer_put_cstring(&b, pkalg);                              (r = sshbuf_put_cstring(b, pkalg) != 0))
                                   fatal("%s: build packet failed: %s",
                                       __func__, ssh_err(r));
                 }                  }
                 buffer_put_string(&b, pkblob, blen);                  if ((r = sshbuf_put_string(b, pkblob, blen)) != 0)
                           fatal("%s: build packet failed: %s",
                               __func__, ssh_err(r));
 #ifdef DEBUG_PK  #ifdef DEBUG_PK
                 buffer_dump(&b);                  sshbuf_dump(b, stderr);
 #endif  #endif
                 pubkey_auth_info(authctxt, key, NULL);                  pubkey_auth_info(authctxt, key, NULL);
   
                 /* test for correct signature */                  /* test for correct signature */
                 authenticated = 0;                  authenticated = 0;
                 if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&                  if (PRIVSEP(user_key_allowed(authctxt->pw, key, 1)) &&
                     PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b),                      PRIVSEP(sshkey_verify(key, sig, slen, sshbuf_ptr(b),
                     buffer_len(&b))) == 1) {                      sshbuf_len(b), ssh->compat)) == 0) {
                         authenticated = 1;                          authenticated = 1;
                         /* Record the successful key to prevent reuse */                          /* Record the successful key to prevent reuse */
                         auth2_record_userkey(authctxt, key);                          auth2_record_userkey(authctxt, key);
                         key = NULL; /* Don't free below */                          key = NULL; /* Don't free below */
                 }                  }
                 buffer_free(&b);                  sshbuf_free(b);
                 free(sig);                  free(sig);
         } else {          } else {
                 debug("%s: test whether pkalg/pkblob are acceptable for %s %s",                  debug("%s: test whether pkalg/pkblob are acceptable for %s %s",
                     __func__, sshkey_type(key), fp);                      __func__, sshkey_type(key), fp);
                 packet_check_eom();                  if ((r = sshpkt_get_end(ssh)) != 0)
                           fatal("%s: %s", __func__, ssh_err(r));
   
                 /* XXX fake reply and always send PK_OK ? */                  /* XXX fake reply and always send PK_OK ? */
                 /*                  /*
Line 196 
Line 220 
                  * issue? -markus                   * issue? -markus
                  */                   */
                 if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {                  if (PRIVSEP(user_key_allowed(authctxt->pw, key, 0))) {
                         packet_start(SSH2_MSG_USERAUTH_PK_OK);                          if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_PK_OK))
                         packet_put_string(pkalg, alen);                              != 0 ||
                         packet_put_string(pkblob, blen);                              (r = sshpkt_put_cstring(ssh, pkalg)) != 0 ||
                         packet_send();                              (r = sshpkt_put_string(ssh, pkblob, blen)) != 0 ||
                         packet_write_wait();                              (r = sshpkt_send(ssh)) != 0)
                                   fatal("%s: %s", __func__, ssh_err(r));
                           ssh_packet_write_wait(ssh);
                         authctxt->postponed = 1;                          authctxt->postponed = 1;
                 }                  }
         }          }
Line 209 
Line 235 
 done:  done:
         debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);          debug2("%s: authenticated %d pkalg %s", __func__, authenticated, pkalg);
         if (key != NULL)          if (key != NULL)
                 key_free(key);                  sshkey_free(key);
           free(userstyle);
         free(pkalg);          free(pkalg);
         free(pkblob);          free(pkblob);
         free(fp);          free(fp);
Line 230 
Line 257 
                 i = vasprintf(&extra, fmt, ap);                  i = vasprintf(&extra, fmt, ap);
                 va_end(ap);                  va_end(ap);
                 if (i < 0 || extra == NULL)                  if (i < 0 || extra == NULL)
                         fatal("%s: vasprintf failed", __func__);                          fatal("%s: vasprintf failed", __func__);
         }          }
   
         if (key_is_cert(key)) {          if (sshkey_is_cert(key)) {
                 fp = sshkey_fingerprint(key->cert->signature_key,                  fp = sshkey_fingerprint(key->cert->signature_key,
                     options.fingerprint_hash, SSH_FP_DEFAULT);                      options.fingerprint_hash, SSH_FP_DEFAULT);
                 auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",                  auth_info(authctxt, "%s ID %s (serial %llu) CA %s %s%s%s",
                     key_type(key), key->cert->key_id,                      sshkey_type(key), key->cert->key_id,
                     (unsigned long long)key->cert->serial,                      (unsigned long long)key->cert->serial,
                     key_type(key->cert->signature_key),                      sshkey_type(key->cert->signature_key),
                     fp == NULL ? "(null)" : fp,                      fp == NULL ? "(null)" : fp,
                     extra == NULL ? "" : ", ", extra == NULL ? "" : extra);                      extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
                 free(fp);                  free(fp);
         } else {          } else {
                 fp = sshkey_fingerprint(key, options.fingerprint_hash,                  fp = sshkey_fingerprint(key, options.fingerprint_hash,
                     SSH_FP_DEFAULT);                      SSH_FP_DEFAULT);
                 auth_info(authctxt, "%s %s%s%s", key_type(key),                  auth_info(authctxt, "%s %s%s%s", sshkey_type(key),
                     fp == NULL ? "(null)" : fp,                      fp == NULL ? "(null)" : fp,
                     extra == NULL ? "" : ", ", extra == NULL ? "" : extra);                      extra == NULL ? "" : ", ", extra == NULL ? "" : extra);
                 free(fp);                  free(fp);
Line 759 
Line 786 
  * returns 1 if the key is allowed or 0 otherwise.   * returns 1 if the key is allowed or 0 otherwise.
  */   */
 static int  static int
 check_authkeys_file(FILE *f, char *file, struct sshkey* key, struct passwd *pw)  check_authkeys_file(FILE *f, char *file, struct sshkey *key, struct passwd *pw)
 {  {
         char line[SSH_MAX_PUBKEY_BYTES];          char line[SSH_MAX_PUBKEY_BYTES];
         int found_key = 0;          int found_key = 0;
         u_long linenum = 0;          u_long linenum = 0;
         struct sshkey *found;          struct sshkey *found = NULL;
   
         found_key = 0;  
   
         found = NULL;  
         while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {          while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
                 char *cp, *key_options = NULL, *fp = NULL;                  char *cp, *key_options = NULL, *fp = NULL;
                 const char *reason = NULL;                  const char *reason = NULL;
Line 777 
Line 801 
                 if (found_key)                  if (found_key)
                         continue;                          continue;
                 if (found != NULL)                  if (found != NULL)
                         key_free(found);                          sshkey_free(found);
                 found = key_new(key_is_cert(key) ? KEY_UNSPEC : key->type);                  found = sshkey_new(sshkey_is_cert(key) ? KEY_UNSPEC : key->type);
                   if (found == NULL)
                           goto done;
                 auth_clear_options();                  auth_clear_options();
   
                 /* Skip leading whitespace, empty and comment lines. */                  /* Skip leading whitespace, empty and comment lines. */
Line 787 
Line 813 
                 if (!*cp || *cp == '\n' || *cp == '#')                  if (!*cp || *cp == '\n' || *cp == '#')
                         continue;                          continue;
   
                 if (key_read(found, &cp) != 1) {                  if (sshkey_read(found, &cp) != 0) {
                         /* no key?  check if there are options for this key */                          /* no key?  check if there are options for this key */
                         int quoted = 0;                          int quoted = 0;
                         debug2("user_key_allowed: check options: '%s'", cp);                          debug2("user_key_allowed: check options: '%s'", cp);
Line 801 
Line 827 
                         /* Skip remaining whitespace. */                          /* Skip remaining whitespace. */
                         for (; *cp == ' ' || *cp == '\t'; cp++)                          for (; *cp == ' ' || *cp == '\t'; cp++)
                                 ;                                  ;
                         if (key_read(found, &cp) != 1) {                          if (sshkey_read(found, &cp) != 0) {
                                 debug2("user_key_allowed: advance: '%s'", cp);                                  debug2("user_key_allowed: advance: '%s'", cp);
                                 /* still no key?  advance to next line*/                                  /* still no key?  advance to next line*/
                                 continue;                                  continue;
                         }                          }
                 }                  }
                 if (key_is_cert(key)) {                  if (sshkey_is_cert(key)) {
                         if (!key_equal(found, key->cert->signature_key))                          if (!sshkey_equal(found, key->cert->signature_key))
                                 continue;                                  continue;
                         if (auth_parse_options(pw, key_options, file,                          if (auth_parse_options(pw, key_options, file,
                             linenum) != 1)                              linenum) != 1)
Line 819 
Line 845 
                             options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)                              options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
                                 continue;                                  continue;
                         debug("matching CA found: file %s, line %lu, %s %s",                          debug("matching CA found: file %s, line %lu, %s %s",
                             file, linenum, key_type(found), fp);                              file, linenum, sshkey_type(found), fp);
                         /*                          /*
                          * If the user has specified a list of principals as                           * If the user has specified a list of principals as
                          * a key option, then prefer that list to matching                           * a key option, then prefer that list to matching
Line 836 
Line 862 
                                 auth_debug_add("%s", reason);                                  auth_debug_add("%s", reason);
                                 continue;                                  continue;
                         }                          }
                         if (key_cert_check_authority(key, 0, 0,                          if (sshkey_cert_check_authority(key, 0, 0,
                             authorized_principals == NULL ? pw->pw_name : NULL,                              authorized_principals == NULL ? pw->pw_name : NULL,
                             &reason) != 0)                              &reason) != 0)
                                 goto fail_reason;                                  goto fail_reason;
Line 845 
Line 871 
                         verbose("Accepted certificate ID \"%s\" (serial %llu) "                          verbose("Accepted certificate ID \"%s\" (serial %llu) "
                             "signed by %s CA %s via %s", key->cert->key_id,                              "signed by %s CA %s via %s", key->cert->key_id,
                             (unsigned long long)key->cert->serial,                              (unsigned long long)key->cert->serial,
                             key_type(found), fp, file);                              sshkey_type(found), fp, file);
                         free(fp);                          free(fp);
                         found_key = 1;                          found_key = 1;
                         break;                          break;
                 } else if (key_equal(found, key)) {                  } else if (sshkey_equal(found, key)) {
                         if (auth_parse_options(pw, key_options, file,                          if (auth_parse_options(pw, key_options, file,
                             linenum) != 1)                              linenum) != 1)
                                 continue;                                  continue;
Line 859 
Line 885 
                             options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)                              options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
                                 continue;                                  continue;
                         debug("matching key found: file %s, line %lu %s %s",                          debug("matching key found: file %s, line %lu %s %s",
                             file, linenum, key_type(found), fp);                              file, linenum, sshkey_type(found), fp);
                         free(fp);                          free(fp);
                         found_key = 1;                          found_key = 1;
                         continue;                          continue;
                 }                  }
         }          }
    done:
         if (found != NULL)          if (found != NULL)
                 key_free(found);                  sshkey_free(found);
         if (!found_key)          if (!found_key)
                 debug2("key not found");                  debug2("key not found");
         return found_key;          return found_key;
Line 878 
Line 905 
 {  {
         char *ca_fp, *principals_file = NULL;          char *ca_fp, *principals_file = NULL;
         const char *reason;          const char *reason;
         int ret = 0, found_principal = 0, use_authorized_principals;          int r, ret = 0, found_principal = 0, use_authorized_principals;
   
         if (!key_is_cert(key) || options.trusted_user_ca_keys == NULL)          if (!sshkey_is_cert(key) || options.trusted_user_ca_keys == NULL)
                 return 0;                  return 0;
   
         if ((ca_fp = sshkey_fingerprint(key->cert->signature_key,          if ((ca_fp = sshkey_fingerprint(key->cert->signature_key,
             options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)              options.fingerprint_hash, SSH_FP_DEFAULT)) == NULL)
                 return 0;                  return 0;
   
         if (sshkey_in_file(key->cert->signature_key,          if ((r = sshkey_in_file(key->cert->signature_key,
             options.trusted_user_ca_keys, 1, 0) != 0) {              options.trusted_user_ca_keys, 1, 0)) != 0) {
                 debug2("%s: CA %s %s is not listed in %s", __func__,                  debug2("%s: CA %s %s is not listed in %s: %s", __func__,
                     key_type(key->cert->signature_key), ca_fp,                      sshkey_type(key->cert->signature_key), ca_fp,
                     options.trusted_user_ca_keys);                      options.trusted_user_ca_keys, ssh_err(r));
                 goto out;                  goto out;
         }          }
         /*          /*
Line 916 
Line 943 
                 auth_debug_add("%s", reason);                  auth_debug_add("%s", reason);
                 goto out;                  goto out;
         }          }
         if (key_cert_check_authority(key, 0, 1,          if (sshkey_cert_check_authority(key, 0, 1,
             use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)              use_authorized_principals ? NULL : pw->pw_name, &reason) != 0)
                 goto fail_reason;                  goto fail_reason;
         if (auth_cert_options(key, pw, &reason) != 0)          if (auth_cert_options(key, pw, &reason) != 0)
Line 925 
Line 952 
         verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "          verbose("Accepted certificate ID \"%s\" (serial %llu) signed by "
             "%s CA %s via %s", key->cert->key_id,              "%s CA %s via %s", key->cert->key_id,
             (unsigned long long)key->cert->serial,              (unsigned long long)key->cert->serial,
             key_type(key->cert->signature_key), ca_fp,              sshkey_type(key->cert->signature_key), ca_fp,
             options.trusted_user_ca_keys);              options.trusted_user_ca_keys);
         ret = 1;          ret = 1;
   
Line 1093 
Line 1120 
   
         if (auth_key_is_revoked(key))          if (auth_key_is_revoked(key))
                 return 0;                  return 0;
         if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))          if (sshkey_is_cert(key) &&
               auth_key_is_revoked(key->cert->signature_key))
                 return 0;                  return 0;
   
         success = user_cert_trusted_ca(pw, key);          success = user_cert_trusted_ca(pw, key);

Legend:
Removed from v.1.63  
changed lines
  Added in v.1.64