Merge branch 'vendor/OPENSSH'
authorPeter Avalos <pavalos@dragonflybsd.org>
Wed, 29 Sep 2010 02:05:08 +0000 (16:05 -1000)
committerPeter Avalos <pavalos@dragonflybsd.org>
Wed, 29 Sep 2010 02:26:31 +0000 (16:26 -1000)
37 files changed:
1  2 
crypto/openssh/auth-rh-rsa.c
crypto/openssh/auth-rsa.c
crypto/openssh/auth2-hostbased.c
crypto/openssh/auth2-pubkey.c
crypto/openssh/authfile.c
crypto/openssh/authfile.h
crypto/openssh/buffer.c
crypto/openssh/buffer.h
crypto/openssh/channels.c
crypto/openssh/channels.h
crypto/openssh/clientloop.c
crypto/openssh/kex.c
crypto/openssh/kex.h
crypto/openssh/loginrec.c
crypto/openssh/myproposal.h
crypto/openssh/openbsd-compat/port-tun.c
crypto/openssh/packet.c
crypto/openssh/pathnames.h
crypto/openssh/readconf.c
crypto/openssh/readconf.h
crypto/openssh/scp.c
crypto/openssh/servconf.c
crypto/openssh/servconf.h
crypto/openssh/session.c
crypto/openssh/sftp.1
crypto/openssh/sftp.c
crypto/openssh/ssh-agent.c
crypto/openssh/ssh.1
crypto/openssh/ssh.c
crypto/openssh/ssh_config
crypto/openssh/ssh_config.5
crypto/openssh/sshconnect.c
crypto/openssh/sshconnect2.c
crypto/openssh/sshd.8
crypto/openssh/sshd.c
crypto/openssh/sshd_config
crypto/openssh/sshd_config.5

@@@ -44,22 -42,11 +44,25 @@@ in
  auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
      Key *client_host_key)
  {
 +      char *fp;
        HostStatus host_status;
  
 +      if (blacklisted_key(client_host_key)) {
 +              fp = key_fingerprint(client_host_key, SSH_FP_MD5, SSH_FP_HEX);
 +              if (options.permit_blacklisted_keys)
 +                      logit("Public key %s blacklisted (see "
 +                          "ssh-vulnkey(1)); continuing anyway", fp);
 +              else
 +                      logit("Public key %s blacklisted (see "
 +                          "ssh-vulnkey(1))", fp);
 +              xfree(fp);
 +              if (!options.permit_blacklisted_keys)
 +                      return 0;
 +      }
 +
+       if (auth_key_is_revoked(client_host_key))
+               return 0;
        /* Check if we would accept it using rhosts authentication. */
        if (!auth_rhosts(pw, cuser))
                return 0;
@@@ -39,8 -38,8 +38,9 @@@
  #include "log.h"
  #include "servconf.h"
  #include "key.h"
+ #include "auth-options.h"
  #include "hostfile.h"
 +#include "authfile.h"
  #include "auth.h"
  #ifdef GSSAPI
  #include "ssh-gss.h"
@@@ -142,24 -141,14 +142,27 @@@ in
  hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
      Key *key)
  {
-       char *fp;
-       const char *resolvedname, *ipaddr, *lookup;
+       const char *resolvedname, *ipaddr, *lookup, *reason;
        HostStatus host_status;
        int len;
+       char *fp;
+       if (auth_key_is_revoked(key))
+               return 0;
  
 +      if (blacklisted_key(key)) {
 +              fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
 +              if (options.permit_blacklisted_keys)
 +                      logit("Public key %s blacklisted (see "
 +                          "ssh-vulnkey(1)); continuing anyway", fp);
 +              else
 +                      logit("Public key %s blacklisted (see "
 +                          "ssh-vulnkey(1))", fp);
 +              xfree(fp);
 +              if (!options.permit_blacklisted_keys)
 +                      return 0;
 +      }
 +
        resolvedname = get_canonical_hostname(options.use_dns);
        ipaddr = get_remote_ipaddr();
  
@@@ -256,19 -439,15 +441,28 @@@ user_key_allowed(struct passwd *pw, Ke
        int success;
        char *file;
  
 +      if (blacklisted_key(key)) {
 +              fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
 +              if (options.permit_blacklisted_keys)
 +                      logit("Public key %s blacklisted (see "
 +                          "ssh-vulnkey(1)); continuing anyway", fp);
 +              else
 +                      logit("Public key %s blacklisted (see "
 +                          "ssh-vulnkey(1))", fp);
 +              xfree(fp);
 +              if (!options.permit_blacklisted_keys)
 +                      return 0;
 +      }
 +
+       if (auth_key_is_revoked(key))
+               return 0;
+       if (key_is_cert(key) && auth_key_is_revoked(key->cert->signature_key))
+               return 0;
+       success = user_cert_trusted_ca(pw, key);
+       if (success)
+               return success;
        file = authorized_keys_file(pw);
        success = user_key_allowed2(pw, key, file);
        xfree(file);
@@@ -679,112 -693,124 +694,234 @@@ key_load_public(const char *filename, c
        return NULL;
  }
  
 +char *
 +blacklist_filename(const Key *key)
 +{
 +      char *name;
 +
 +      xasprintf(&name, "%s.%s-%u",
 +          _PATH_BLACKLIST, key_type(key), key_size(key));
 +      return name;
 +}
 +
 +/* Scan a blacklist of known-vulnerable keys. */
 +int
 +blacklisted_key(const Key *key)
 +{
 +      char *blacklist_file;
 +      int fd = -1;
 +      char *dgst_hex = NULL;
 +      char *dgst_packed = NULL, *p;
 +      int i;
 +      size_t line_len;
 +      struct stat st;
 +      char buf[256];
 +      off_t start, lower, upper;
 +      int ret = 0;
 +
 +      blacklist_file = blacklist_filename(key);
 +      debug("Checking blacklist file %s", blacklist_file);
 +      fd = open(blacklist_file, O_RDONLY);
 +      if (fd < 0)
 +              goto out;
 +
 +      dgst_hex = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
 +      /* Remove all colons */
 +      dgst_packed = xcalloc(1, strlen(dgst_hex) + 1);
 +      for (i = 0, p = dgst_packed; dgst_hex[i]; i++)
 +              if (dgst_hex[i] != ':')
 +                      *p++ = dgst_hex[i];
 +      /* Only compare least-significant 80 bits (to keep the blacklist
 +       * size down)
 +       */
 +      line_len = strlen(dgst_packed + 12);
 +      if (line_len > 32)
 +              goto out;
 +
 +      /* Skip leading comments */
 +      start = 0;
 +      for (;;) {
 +              ssize_t r;
 +              char *newline;
 +
 +              r = atomicio(read, fd, buf, 256);
 +              if (r <= 0)
 +                      goto out;
 +              if (buf[0] != '#')
 +                      break;
 +
 +              newline = memchr(buf, '\n', 256);
 +              if (!newline)
 +                      goto out;
 +              start += newline + 1 - buf;
 +              if (lseek(fd, start, SEEK_SET) < 0)
 +                      goto out;
 +      }
 +
 +      /* Initialise binary search record numbers */
 +      if (fstat(fd, &st) < 0)
 +              goto out;
 +      lower = 0;
 +      upper = (st.st_size - start) / (line_len + 1);
 +
 +      while (lower != upper) {
 +              off_t cur;
 +              char buf[32];
 +              int cmp;
 +
 +              cur = lower + (upper - lower) / 2;
 +
 +              /* Read this line and compare to digest; this is
 +               * overflow-safe since cur < max(off_t) / (line_len + 1) */
 +              if (lseek(fd, start + cur * (line_len + 1), SEEK_SET) < 0)
 +                      break;
 +              if (atomicio(read, fd, buf, line_len) != line_len)
 +                      break;
 +              cmp = memcmp(buf, dgst_packed + 12, line_len);
 +              if (cmp < 0) {
 +                      if (cur == lower)
 +                              break;
 +                      lower = cur;
 +              } else if (cmp > 0) {
 +                      if (cur == upper)
 +                              break;
 +                      upper = cur;
 +              } else {
 +                      debug("Found %s in blacklist", dgst_hex);
 +                      ret = 1;
 +                      break;
 +              }
 +      }
 +
 +out:
 +      if (dgst_packed)
 +              xfree(dgst_packed);
 +      if (dgst_hex)
 +              xfree(dgst_hex);
 +      if (fd >= 0)
 +              close(fd);
 +      xfree(blacklist_file);
 +      return ret;
 +}
++
+ /* Load the certificate associated with the named private key */
+ Key *
+ key_load_cert(const char *filename)
+ {
+       Key *pub;
+       char *file;
+       pub = key_new(KEY_UNSPEC);
+       xasprintf(&file, "%s-cert.pub", filename);
+       if (key_try_load_public(pub, file, NULL) == 1) {
+               xfree(file);
+               return pub;
+       }
+       xfree(file);
+       key_free(pub);
+       return NULL;
+ }
+ /* Load private key and certificate */
+ Key *
+ key_load_private_cert(int type, const char *filename, const char *passphrase,
+     int *perm_ok)
+ {
+       Key *key, *pub;
+       switch (type) {
+       case KEY_RSA:
+       case KEY_DSA:
+               break;
+       default:
+               error("%s: unsupported key type", __func__);
+               return NULL;
+       }
+       if ((key = key_load_private_type(type, filename, 
+           passphrase, NULL, perm_ok)) == NULL)
+               return NULL;
+       if ((pub = key_load_cert(filename)) == NULL) {
+               key_free(key);
+               return NULL;
+       }
+       /* Make sure the private key matches the certificate */
+       if (key_equal_public(key, pub) == 0) {
+               error("%s: certificate does not match private key %s",
+                   __func__, filename);
+       } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) {
+               error("%s: key_to_certified failed", __func__);
+       } else {
+               key_cert_copy(pub, key);
+               key_free(pub);
+               return key;
+       }
+       key_free(key);
+       key_free(pub);
+       return NULL;
+ }
+ /*
+  * Returns 1 if the specified "key" is listed in the file "filename",
+  * 0 if the key is not listed or -1 on error.
+  * If strict_type is set then the key type must match exactly,
+  * otherwise a comparison that ignores certficiate data is performed.
+  */
+ int
+ key_in_file(Key *key, const char *filename, int strict_type)
+ {
+       FILE *f;
+       char line[SSH_MAX_PUBKEY_BYTES];
+       char *cp;
+       u_long linenum = 0;
+       int ret = 0;
+       Key *pub;
+       int (*key_compare)(const Key *, const Key *) = strict_type ?
+           key_equal : key_equal_public;
+       if ((f = fopen(filename, "r")) == NULL) {
+               if (errno == ENOENT) {
+                       debug("%s: keyfile \"%s\" missing", __func__, filename);
+                       return 0;
+               } else {
+                       error("%s: could not open keyfile \"%s\": %s", __func__,
+                           filename, strerror(errno));
+                       return -1;
+               }
+       }
+       while (read_keyfile_line(f, filename, line, sizeof(line),
+                   &linenum) != -1) {
+               cp = line;
+               /* Skip leading whitespace. */
+               for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
+                       ;
+               /* Skip comments and empty lines */
+               switch (*cp) {
+               case '#':
+               case '\n':
+               case '\0':
+                       continue;
+               }
+               pub = key_new(KEY_UNSPEC);
+               if (key_read(pub, &cp) != 1) {
+                       key_free(pub);
+                       continue;
+               }
+               if (key_compare(key, pub)) {
+                       ret = 1;
+                       key_free(pub);
+                       break;
+               }
+               key_free(pub);
+       }
+       fclose(f);
+       return ret;
+ }
@@@ -22,8 -24,6 +24,9 @@@ Key   *key_load_private_cert(int, const c
  Key   *key_load_private_type(int, const char *, const char *, char **, int *);
  Key   *key_load_private_pem(int, int, const char *, char **);
  int    key_perm_ok(int, const char *);
+ int    key_in_file(Key *, const char *, int);
  
 +char  *blacklist_filename(const Key *key);
 +int    blacklisted_key(const Key *key);
 +
  #endif
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -48,7 -48,7 +48,8 @@@
  #include "match.h"
  #include "dispatch.h"
  #include "monitor.h"
+ #include "roaming.h"
 +#include "canohost.h"
  
  #if OPENSSL_VERSION_NUMBER >= 0x00907000L
  # if defined(HAVE_EVP_SHA256)
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -130,12 -128,11 +130,13 @@@ typedef enum 
        oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
        oAddressFamily, oGssAuthentication, oGssDelegateCreds,
        oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
-       oSendEnv, oControlPath, oControlMaster, oHashKnownHosts,
 +      oVersionAddendum,
+       oSendEnv, oControlPath, oControlMaster, oControlPersist,
+       oHashKnownHosts,
        oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
        oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
 -      oDeprecated, oUnsupported
 +      oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
 +      oHPNBufferSize, oDeprecated, oUnsupported
  } OpCodes;
  
  /* Textual representations of the tokens. */
@@@ -1252,31 -1244,12 +1303,35 @@@ fill_default_options(Options * options
                options->server_alive_interval = 0;
        if (options->server_alive_count_max == -1)
                options->server_alive_count_max = 3;
 +      if (options->none_switch == -1)
 +              options->none_switch = 0;
 +      if (options->hpn_disabled == -1)
 +              options->hpn_disabled = 0;
 +      if (options->hpn_buffer_size > -1)
 +      {
 +        /* if a user tries to set the size to 0 set it to 1KB */
 +              if (options->hpn_buffer_size == 0)
 +              options->hpn_buffer_size = 1024;
 +              /*limit the buffer to 64MB*/
 +              if (options->hpn_buffer_size > 65536)
 +              {
 +                      options->hpn_buffer_size = 65536*1024;
 +                      debug("User requested buffer larger than 64MB. Request reverted to 64MB");
 +              }
 +              debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
 +      }
 +      if (options->tcp_rcv_buf == 0)
 +              options->tcp_rcv_buf = 1;
 +      if (options->tcp_rcv_buf > -1)
 +              options->tcp_rcv_buf *=1024;
 +      if (options->tcp_rcv_buf_poll == -1)
 +              options->tcp_rcv_buf_poll = 1;
        if (options->control_master == -1)
                options->control_master = 0;
+       if (options->control_persist == -1) {
+               options->control_persist = 0;
+               options->control_persist_timeout = 0;
+       }
        if (options->hash_known_hosts == -1)
                options->hash_known_hosts = 0;
        if (options->tun_open == -1)
Simple merge
Simple merge
@@@ -130,10 -129,9 +131,13 @@@ initialize_server_options(ServerOption
        options->adm_forced_command = NULL;
        options->chroot_directory = NULL;
        options->zero_knowledge_password_authentication = -1;
 +      options->none_enabled = -1;
 +      options->tcp_rcv_buf_poll = -1;
 +      options->hpn_disabled = -1;
 +      options->hpn_buffer_size = -1;
+       options->revoked_keys_file = NULL;
+       options->trusted_user_ca_keys = NULL;
+       options->authorized_principals_file = NULL;
  }
  
  void
@@@ -354,9 -310,8 +359,10 @@@ typedef enum 
        sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
        sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
        sUsePrivilegeSeparation, sAllowAgentForwarding,
-       sZeroKnowledgePasswordAuthentication,
+       sZeroKnowledgePasswordAuthentication, sHostCertificate,
+       sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
 +      sNoneEnabled, sTcpRcvBufPoll, sHPNDisabled, sHPNBufferSize,
 +      sVersionAddendum,
        sDeprecated, sUnsupported
  } ServerOpCodes;
  
@@@ -467,20 -421,19 +473,24 @@@ static struct 
        { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
        { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
        { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
-       { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
-       { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
-       { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
+       { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
+       { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL },
+       { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
 +      { "versionaddendum", sVersionAddendum , SSHCFG_GLOBAL },
        { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
-       { "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
+       { "permittunnel", sPermitTunnel, SSHCFG_ALL },
        { "match", sMatch, SSHCFG_ALL },
        { "permitopen", sPermitOpen, SSHCFG_ALL },
        { "forcecommand", sForceCommand, SSHCFG_ALL },
        { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
+       { "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
+       { "revokedkeys", sRevokedKeys, SSHCFG_ALL },
+       { "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
+       { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL },
 +      { "noneenabled", sNoneEnabled },
 +      { "hpndisabled", sHPNDisabled },
 +      { "hpnbuffersize", sHPNBufferSize },
 +      { "tcprcvbufpoll", sTcpRcvBufPoll },
        { NULL, sBadOption, 0 }
  };
  
@@@ -1372,12 -1343,13 +1421,19 @@@ process_server_config_line(ServerOption
                        *charptr = xstrdup(arg);
                break;
  
 +      case sVersionAddendum:
 +                ssh_version_set_addendum(strtok(cp, "\n"));
 +                do {
 +                        arg = strdelim(&cp);
 +                } while (arg != NULL && *arg != '\0');
 +              break;
+       case sTrustedUserCAKeys:
+               charptr = &options->trusted_user_ca_keys;
+               goto parse_filename;
+       case sRevokedKeys:
+               charptr = &options->revoked_keys_file;
+               goto parse_filename;
  
        case sDeprecated:
                logit("%s line %d: Deprecated option %s",
Simple merge
@@@ -2334,16 -2333,10 +2372,16 @@@ session_set_fds(Session *s, int fdin, i
         */
        if (s->chanid == -1)
                fatal("no channel for session %d", s->self);
 +      if (options.hpn_disabled)
        channel_set_fds(s->chanid,
            fdout, fdin, fderr,
-           fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
+           ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
            1, is_tty, CHAN_SES_WINDOW_DEFAULT);
-                   fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
 +      else
 +              channel_set_fds(s->chanid,
 +                  fdout, fdin, fderr,
++                  ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ,
 +                  1, is_tty, options.hpn_buffer_size);
  }
  
  /*
@@@ -203,8 -234,12 +234,13 @@@ diagnostic messages fro
  Specify how many requests may be outstanding at any one time.
  Increasing this may slightly improve file transfer speed
  but will increase memory usage.
 -The default is 64 outstanding requests.
 +The default is 256 outstanding requests providing for 8MB
 +of outstanding data with a 32KB buffer.
+ .It Fl r
+ Recursively copy entire directories when uploading and downloading.
+ Note that
+ .Nm
+ does not follow symbolic links encountered in the tree traversal.
  .It Fl S Ar program
  Name of the
  .Ar program
@@@ -65,6 -68,9 +68,9 @@@ typedef void EditLine
  #include "sftp-common.h"
  #include "sftp-client.h"
  
 -#define DEFAULT_NUM_REQUESTS  64      /* # concurrent outstanding requests */
+ #define DEFAULT_COPY_BUFLEN   32768   /* Size of buffer for up/download */
++#define DEFAULT_NUM_REQUESTS  256     /* # concurrent outstanding requests */
  /* File to read commands from */
  FILE* infile;
  
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -219,12 -193,12 +221,15 @@@ ssh_create_socket(int privileged, struc
                return sock;
        }
        sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
-       if (sock < 0)
+       if (sock < 0) {
                error("socket: %.100s", strerror(errno));
+               return -1;
+       }
+       fcntl(sock, F_SETFD, FD_CLOEXEC);
  
 +      if (options.tcp_rcv_buf > 0)
 +              ssh_set_socket_recvbuf(sock);
 +
        /* Bind the socket to an alternative local IP address */
        if (options.bind_address == NULL)
                return sock;
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -834,10 -863,13 +892,15 @@@ Specifies whether public key authentica
  The default is
  .Dq yes .
  Note that this option applies to protocol version 2 only.
+ .It Cm RevokedKeys
+ Specifies a list of revoked public keys.
+ Keys listed in this file will be refused for public key authentication.
+ Note that if this file is not readable, then public key authentication will
+ be refused for all users.
  .It Cm RhostsRSAAuthentication
 -Specifies whether rhosts or /etc/hosts.equiv authentication together
 +Specifies whether rhosts or
 +.Pa /etc/hosts.equiv
 +authentication together
  with successful RSA host authentication is allowed.
  The default is
  .Dq no .