Import OpenSSH-5.9p1.
authorPeter Avalos <pavalos@dragonflybsd.org>
Tue, 20 Sep 2011 22:19:10 +0000 (15:19 -0700)
committerPeter Avalos <pavalos@dragonflybsd.org>
Tue, 20 Sep 2011 22:23:47 +0000 (15:23 -0700)
 * Introduce sandboxing of the pre-auth privsep child using an optional
   sshd_config(5) "UsePrivilegeSeparation=sandbox" mode that enables
   mandatory restrictions on the syscalls the privsep child can perform.
   This intention is to prevent a compromised privsep child from being
   used to attack other hosts (by opening sockets and proxying) or
   probing local kernel attack surface.

   The rlimit sandbox is a fallback choice for platforms that don't
   support a better one; it uses setrlimit() to reset the hard-limit
   of file descriptors and processes to zero, which should prevent
   the privsep child from forking or opening new network connections.

 * Add new SHA256-based HMAC transport integrity modes from
   http://www.ietf.org/id/draft-dbider-sha2-mac-for-ssh-02.txt
   These modes are hmac-sha2-256, hmac-sha2-256-96, hmac-sha2-512,
   and hmac-sha2-512-96, and are available by default in ssh(1) and
   sshd(8)

 * The pre-authentication sshd(8) privilege separation slave process
   now logs via a socket shared with the master process, avoiding the
   need to maintain /dev/log inside the chroot.

 * ssh(1) now warns when a server refuses X11 forwarding

 * sshd_config(5)'s AuthorizedKeysFile now accepts multiple paths,
   separated by whitespace. The undocumented AuthorizedKeysFile2
   option is deprecated (though the default for AuthorizedKeysFile
   includes .ssh/authorized_keys2)

 * sshd_config(5): similarly deprecate UserKnownHostsFile2 and
   GlobalKnownHostsFile2 by making UserKnownHostsFile and
   GlobalKnownHostsFile accept multiple options and default to
   include known_hosts2

 * Retain key comments when loading v.2 keys. These will be visible
   in "ssh-add -l" and other places. bz#439

 * ssh(1) and sshd(8): set IPv6 traffic class from IPQoS (as well as
   IPv4 ToS/DSCP). bz#1855

 * ssh_config(5)'s ControlPath option now expands %L to the host
   portion of the destination host name.

 * ssh_config(5) "Host" options now support negated Host matching, e.g.

     Host *.example.org !c.example.org
        User mekmitasdigoat

   Will match "a.example.org", "b.example.org", but not "c.example.org"

 * ssh_config(5): a new RequestTTY option provides control over when a
   TTY is requested for a connection, similar to the existing -t/-tt/-T
   ssh(1) commandline options.

 * sshd(8): allow GSSAPI authentication to detect when a server-side
   failure causes authentication failure and don't count such failures
   against MaxAuthTries; bz#1244

 * ssh-keygen(1): Add -A option. For each of the key types (rsa1, rsa,
   dsa and ecdsa) for which host keys do not exist, generate the host
   keys with the default key file path, an empty passphrase, default
   bits for the key type, and default comment. This is useful for
   system initialization scripts.

 * ssh(1): Allow graceful shutdown of multiplexing: request that a mux
   server removes its listener socket and refuse future multiplexing
   requests but don't kill existing connections. This may be requested
   using "ssh -O stop ..."

 * ssh-add(1) now accepts keys piped from standard input. E.g.
   "ssh-add - < /path/to/key"

 * ssh-keysign(8) now signs hostbased authentication
   challenges correctly using ECDSA keys; bz#1858

 * sftp(1): document that sftp accepts square brackets to delimit
   addresses (useful for IPv6); bz#1847a

 * ssh(1): when using session multiplexing, the master process will
   change its process title to reflect the control path in use and
   when a ControlPersist-ed master is waiting to close; bz#1883 and
   bz#1911

 * Other minor bugs fixed: 1849 1861 1862 1869 1875 1878 1879 1892
   1900 1905 1913

66 files changed:
crypto/openssh/PROTOCOL.mux
crypto/openssh/README
crypto/openssh/README.DELETED
crypto/openssh/auth-rsa.c
crypto/openssh/auth-skey.c
crypto/openssh/auth.c
crypto/openssh/auth.h
crypto/openssh/auth2-gss.c
crypto/openssh/auth2-pubkey.c
crypto/openssh/auth2.c
crypto/openssh/authfd.c
crypto/openssh/authfile.c
crypto/openssh/authfile.h
crypto/openssh/channels.c
crypto/openssh/channels.h
crypto/openssh/clientloop.c
crypto/openssh/clientloop.h
crypto/openssh/defines.h
crypto/openssh/entropy.c
crypto/openssh/gss-serv.c
crypto/openssh/key.c
crypto/openssh/log.c
crypto/openssh/log.h
crypto/openssh/mac.c
crypto/openssh/misc.c
crypto/openssh/misc.h
crypto/openssh/moduli.5
crypto/openssh/monitor.c
crypto/openssh/monitor.h
crypto/openssh/monitor_wrap.c
crypto/openssh/monitor_wrap.h
crypto/openssh/mux.c
crypto/openssh/myproposal.h
crypto/openssh/openbsd-compat/bsd-cygwin_util.h
crypto/openssh/openbsd-compat/openssl-compat.h
crypto/openssh/openbsd-compat/port-linux.h
crypto/openssh/packet.c
crypto/openssh/packet.h
crypto/openssh/pathnames.h
crypto/openssh/readconf.c
crypto/openssh/readconf.h
crypto/openssh/sandbox-rlimit.c [new file with mode: 0644]
crypto/openssh/servconf.c
crypto/openssh/servconf.h
crypto/openssh/serverloop.c
crypto/openssh/session.c
crypto/openssh/sftp-server.c
crypto/openssh/sftp.1
crypto/openssh/ssh-add.c
crypto/openssh/ssh-agent.c
crypto/openssh/ssh-keygen.1
crypto/openssh/ssh-keygen.c
crypto/openssh/ssh-keyscan.c
crypto/openssh/ssh-keysign.c
crypto/openssh/ssh-pkcs11-helper.c
crypto/openssh/ssh-pkcs11.c
crypto/openssh/ssh-sandbox.h [copied from crypto/openssh/openbsd-compat/port-linux.h with 58% similarity]
crypto/openssh/ssh.1
crypto/openssh/ssh.c
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

index 2a5817b..9ad2566 100644 (file)
@@ -73,6 +73,13 @@ non-multiplexed ssh(1) connection. Two additional cases that the
 client must cope with are it receiving a signal itself and the
 server disconnecting without sending an exit message.
 
+A master may also send a MUX_S_TTY_ALLOC_FAIL before MUX_S_EXIT_MESSAGE
+if remote TTY allocation was unsuccessful. The client may use this to
+return its local tty to "cooked" mode.
+
+       uint32  MUX_S_TTY_ALLOC_FAIL
+       uint32  session id
+
 3. Health checks
 
 The client may request a health check/PID report from a server:
@@ -149,10 +156,21 @@ The client then sends its standard input and output file descriptors
 
 The contents of "reserved" are currently ignored.
 
-A server may reply with a MUX_S_SESSION_OPEED, a MUX_S_PERMISSION_DENIED
+A server may reply with a MUX_S_SESSION_OPENED, a MUX_S_PERMISSION_DENIED
 or a MUX_S_FAILURE.
 
-8. Status messages
+8. Requesting shutdown of mux listener
+
+A client may request the master to stop accepting new multiplexing requests
+and remove its listener socket.
+
+       uint32  MUX_C_STOP_LISTENING
+       uint32  request id
+
+A server may reply with a MUX_S_OK, a MUX_S_PERMISSION_DENIED or a
+MUX_S_FAILURE.
+
+9. Status messages
 
 The MUX_S_OK message is empty:
 
@@ -169,7 +187,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
        uint32  client request id
        string  reason
 
-9. Protocol numbers
+10. Protocol numbers
 
 #define MUX_MSG_HELLO          0x00000001
 #define MUX_C_NEW_SESSION      0x10000002
@@ -178,6 +196,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
 #define MUX_C_OPEN_FWD         0x10000006
 #define MUX_C_CLOSE_FWD                0x10000007
 #define MUX_C_NEW_STDIO_FWD    0x10000008
+#define MUX_C_STOP_LISTENING   0x10000009
 #define MUX_S_OK               0x80000001
 #define MUX_S_PERMISSION_DENIED        0x80000002
 #define MUX_S_FAILURE          0x80000003
@@ -185,6 +204,7 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
 #define MUX_S_ALIVE            0x80000005
 #define MUX_S_SESSION_OPENED   0x80000006
 #define MUX_S_REMOTE_PORT      0x80000007
+#define MUX_S_TTY_ALLOC_FAIL   0x80000008
 
 #define MUX_FWD_LOCAL  1
 #define MUX_FWD_REMOTE 2
@@ -192,12 +212,10 @@ The MUX_S_PERMISSION_DENIED and MUX_S_FAILURE include a reason:
 
 XXX TODO
 XXX extended status (e.g. report open channels / forwards)
-XXX graceful close (delete listening socket, but keep existing sessions active)
 XXX lock (maybe)
 XXX watch in/out traffic (pre/post crypto)
 XXX inject packet (what about replies)
 XXX server->client error/warning notifications
-XXX port0 rfwd (need custom response message)
 XXX send signals via mux
 
-$OpenBSD: PROTOCOL.mux,v 1.4 2011/01/31 21:42:15 djm Exp $
+$OpenBSD: PROTOCOL.mux,v 1.7 2011/05/08 12:52:01 djm Exp $
index 4f69506..e26654b 100644 (file)
@@ -1,4 +1,4 @@
-See http://www.openssh.com/txt/release-5.8 for the release notes.
+See http://www.openssh.com/txt/release-5.9 for the release notes.
 
 - A Japanese translation of this document and of the OpenSSH FAQ is
 - available at http://www.unixuser.org/~haruyama/security/openssh/index.html
@@ -62,4 +62,4 @@ References -
 [6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
 [7] http://www.openssh.com/faq.html
 
-$Id: README,v 1.75.4.1 2011/02/04 00:57:50 djm Exp $
+$Id: README,v 1.77.2.2 2011/09/06 23:11:20 djm Exp $
index 225fa75..9ede1a9 100644 (file)
@@ -5,7 +5,6 @@ OVERVIEW
 README.platform
 README.privsep
 TODO
-WARNING.RNG
 aclocal.m4
 audit-linux.c
 buildpkg.sh.in
@@ -79,6 +78,9 @@ openbsd-compat/xcrypt.c
 openssh.xml.in
 opensshd.init.in
 regress/
+sandbox-darwin.c
+sandbox-null.c
+sandbox-systrace.c
 scard/
 scp.0
 sftp-server.0
@@ -89,12 +91,8 @@ ssh-keygen.0
 ssh-keyscan.0
 ssh-keysign.0
 ssh-pkcs11-helper.0
-ssh-rand-helper.0
-ssh-rand-helper.8
-ssh-rand-helper.c
 ssh.0
 ssh_config.0
-ssh_prng_cmds.in
 sshd.0
 sshd_config.0
 survey.sh.in
index 4edaab0..4ab46cd 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rsa.c,v 1.79 2010/12/03 23:55:27 djm Exp $ */
+/* $OpenBSD: auth-rsa.c,v 1.80 2011/05/23 03:30:07 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -160,44 +160,27 @@ auth_rsa_challenge_dialog(Key *key)
        return (success);
 }
 
-/*
- * check if there's user key matching client_n,
- * return key if login is allowed, NULL otherwise
- */
-
-int
-auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+static int
+rsa_key_allowed_in_file(struct passwd *pw, char *file,
+    const BIGNUM *client_n, Key **rkey)
 {
-       char line[SSH_MAX_PUBKEY_BYTES], *file;
+       char line[SSH_MAX_PUBKEY_BYTES];
        int allowed = 0;
        u_int bits;
        FILE *f;
        u_long linenum = 0;
        Key *key;
 
-       /* Temporarily use the user's uid. */
-       temporarily_use_uid(pw);
-
-       /* The authorized keys. */
-       file = authorized_keys_file(pw);
        debug("trying public RSA key file %s", file);
-       f = auth_openkeyfile(file, pw, options.strict_modes);
-       if (!f) {
-               xfree(file);
-               restore_uid();
-               return (0);
-       }
-
-       /* Flag indicating whether the key is allowed. */
-       allowed = 0;
-
-       key = key_new(KEY_RSA1);
+       if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
+               return 0;
 
        /*
         * Go though the accepted keys, looking for the current key.  If
         * found, perform a challenge-response dialog to verify that the
         * user really has the corresponding private key.
         */
+       key = key_new(KEY_RSA1);
        while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
                char *cp;
                char *key_options;
@@ -235,7 +218,10 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
                }
                /* cp now points to the comment part. */
 
-               /* Check if the we have found the desired key (identified by its modulus). */
+               /*
+                * Check if the we have found the desired key (identified
+                * by its modulus).
+                */
                if (BN_cmp(key->rsa->n, client_n) != 0)
                        continue;
 
@@ -264,11 +250,7 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
                break;
        }
 
-       /* Restore the privileged uid. */
-       restore_uid();
-
        /* Close the file. */
-       xfree(file);
        fclose(f);
 
        /* return key if allowed */
@@ -276,7 +258,33 @@ auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
                *rkey = key;
        else
                key_free(key);
-       return (allowed);
+
+       return allowed;
+}
+
+/*
+ * check if there's user key matching client_n,
+ * return key if login is allowed, NULL otherwise
+ */
+
+int
+auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
+{
+       char *file;
+       u_int i, allowed = 0;
+
+       temporarily_use_uid(pw);
+
+       for (i = 0; !allowed && i < options.num_authkeys_files; i++) {
+               file = expand_authorized_keys(
+                   options.authorized_keys_files[i], pw);
+               allowed = rsa_key_allowed_in_file(pw, file, client_n, rkey);
+               xfree(file);
+       }
+
+       restore_uid();
+
+       return allowed;
 }
 
 /*
index cb43dba..3536ec8 100644 (file)
@@ -39,6 +39,7 @@
 #include "hostfile.h"
 #include "auth.h"
 #include "ssh-gss.h"
+#include "log.h"
 #include "monitor_wrap.h"
 
 static void *
index 33680b9..cd95da9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.91 2010/11/29 23:45:51 djm Exp $ */
+/* $OpenBSD: auth.c,v 1.94 2011/05/23 03:33:38 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -331,7 +331,7 @@ auth_root_allowed(char *method)
  *
  * This returns a buffer allocated by xmalloc.
  */
-static char *
+char *
 expand_authorized_keys(const char *filename, struct passwd *pw)
 {
        char *file, ret[MAXPATHLEN];
@@ -354,18 +354,6 @@ expand_authorized_keys(const char *filename, struct passwd *pw)
        return (xstrdup(ret));
 }
 
-char *
-authorized_keys_file(struct passwd *pw)
-{
-       return expand_authorized_keys(options.authorized_keys_file, pw);
-}
-
-char *
-authorized_keys_file2(struct passwd *pw)
-{
-       return expand_authorized_keys(options.authorized_keys_file2, pw);
-}
-
 char *
 authorized_principals_file(struct passwd *pw)
 {
@@ -468,7 +456,6 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
                }
                strlcpy(buf, cp, sizeof(buf));
 
-               debug3("secure_filename: checking '%s'", buf);
                if (stat(buf, &st) < 0 ||
                    (st.st_uid != 0 && st.st_uid != uid) ||
                    (st.st_mode & 022) != 0) {
@@ -478,11 +465,9 @@ secure_filename(FILE *f, const char *file, struct passwd *pw,
                }
 
                /* If are past the homedir then we can stop */
-               if (comparehome && strcmp(homedir, buf) == 0) {
-                       debug3("secure_filename: terminating check at '%s'",
-                           buf);
+               if (comparehome && strcmp(homedir, buf) == 0)
                        break;
-               }
+
                /*
                 * dirname should always complete with a "/" path,
                 * but we can be paranoid and check for "." too
index 77317ae..0d786c4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.h,v 1.66 2010/05/07 11:30:29 djm Exp $ */
+/* $OpenBSD: auth.h,v 1.69 2011/05/23 03:30:07 djm Exp $ */
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
@@ -53,6 +53,7 @@ struct Authctxt {
        int              valid;         /* user exists and is allowed to login */
        int              attempt;
        int              failures;
+       int              server_caused_failure; 
        int              force_pwchange;
        char            *user;          /* username sent by the client */
        char            *service;
@@ -167,8 +168,7 @@ char        *get_challenge(Authctxt *);
 int    verify_response(Authctxt *, const char *);
 void   abandon_challenge_response(Authctxt *);
 
-char   *authorized_keys_file(struct passwd *);
-char   *authorized_keys_file2(struct passwd *);
+char   *expand_authorized_keys(const char *, struct passwd *pw);
 char   *authorized_principals_file(struct passwd *);
 
 FILE   *auth_openkeyfile(const char *, struct passwd *, int);
index 0e08d88..0d59b21 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-gss.c,v 1.16 2007/10/29 00:52:45 dtucker Exp $ */
+/* $OpenBSD: auth2-gss.c,v 1.17 2011/03/10 02:52:57 djm Exp $ */
 
 /*
  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -102,6 +102,7 @@ userauth_gssapi(Authctxt *authctxt)
 
        if (!present) {
                xfree(doid);
+               authctxt->server_caused_failure = 1;
                return (0);
        }
 
@@ -109,6 +110,7 @@ userauth_gssapi(Authctxt *authctxt)
                if (ctxt != NULL)
                        ssh_gssapi_delete_ctx(&ctxt);
                xfree(doid);
+               authctxt->server_caused_failure = 1;
                return (0);
        }
 
index 7d21413..137887e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-pubkey.c,v 1.27 2010/11/20 05:12:38 deraadt Exp $ */
+/* $OpenBSD: auth2-pubkey.c,v 1.29 2011/05/23 03:30:07 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -436,7 +436,7 @@ user_cert_trusted_ca(struct passwd *pw, Key *key)
 int
 user_key_allowed(struct passwd *pw, Key *key)
 {
-       int success;
+       u_int success, i;
        char *file;
 
        if (auth_key_is_revoked(key))
@@ -448,16 +448,13 @@ user_key_allowed(struct passwd *pw, Key *key)
        if (success)
                return success;
 
-       file = authorized_keys_file(pw);
-       success = user_key_allowed2(pw, key, file);
-       xfree(file);
-       if (success)
-               return success;
+       for (i = 0; !success && i < options.num_authkeys_files; i++) {
+               file = expand_authorized_keys(
+                   options.authorized_keys_files[i], pw);
+               success = user_key_allowed2(pw, key, file);
+               xfree(file);
+       }
 
-       /* try suffix "2" for backward compat, too */
-       file = authorized_keys_file2(pw);
-       success = user_key_allowed2(pw, key, file);
-       xfree(file);
        return success;
 }
 
index 95820f9..c06c95f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2.c,v 1.122 2010/08/31 09:58:37 djm Exp $ */
+/* $OpenBSD: auth2.c,v 1.123 2011/03/10 02:52:57 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -274,6 +274,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
 #endif
 
        authctxt->postponed = 0;
+       authctxt->server_caused_failure = 0;
 
        /* try to authenticate user */
        m = authmethod_lookup(method);
@@ -346,7 +347,8 @@ userauth_finish(Authctxt *authctxt, int authenticated, char *method)
        } else {
 
                /* Allow initial try of "none" auth without failure penalty */
-               if (authctxt->attempt > 1 || strcmp(method, "none") != 0)
+               if (!authctxt->server_caused_failure &&
+                   (authctxt->attempt > 1 || strcmp(method, "none") != 0))
                        authctxt->failures++;
                if (authctxt->failures >= options.max_authtries) {
 #ifdef SSH_AUDIT_EVENTS
index c11c3f5..f037e83 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.c,v 1.84 2010/08/31 11:54:45 djm Exp $ */
+/* $OpenBSD: authfd.c,v 1.86 2011/07/06 18:09:21 tedu Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -102,6 +102,7 @@ ssh_get_authentication_socket(void)
        if (!authsocket)
                return -1;
 
+       bzero(&sunaddr, sizeof(sunaddr));
        sunaddr.sun_family = AF_UNIX;
        strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
 
@@ -110,7 +111,7 @@ ssh_get_authentication_socket(void)
                return -1;
 
        /* close on exec */
-       if (fcntl(sock, F_SETFD, 1) == -1) {
+       if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) {
                close(sock);
                return -1;
        }
index f2aec26..1d7e53c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.c,v 1.87 2010/11/29 18:57:04 markus Exp $ */
+/* $OpenBSD: authfile.c,v 1.92 2011/06/14 22:49:18 markus Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -69,6 +69,8 @@
 #include "misc.h"
 #include "atomicio.h"
 
+#define MAX_KEY_FILE_SIZE      (1024 * 1024)
+
 /* Version identification string for SSH v1 identity files. */
 static const char authfile_id_string[] =
     "SSH PRIVATE KEY FILE FORMAT 1.1\n";
@@ -277,6 +279,7 @@ static Key *
 key_parse_public_rsa1(Buffer *blob, char **commentp)
 {
        Key *pub;
+       Buffer copy;
 
        /* Check that it is at least big enough to contain the ID string. */
        if (buffer_len(blob) < sizeof(authfile_id_string)) {
@@ -293,31 +296,33 @@ key_parse_public_rsa1(Buffer *blob, char **commentp)
                debug3("Incorrect RSA1 identifier");
                return NULL;
        }
-       buffer_consume(blob, sizeof(authfile_id_string));
+       buffer_init(&copy);
+       buffer_append(&copy, buffer_ptr(blob), buffer_len(blob));
+       buffer_consume(&copy, sizeof(authfile_id_string));
 
        /* Skip cipher type and reserved data. */
-       (void) buffer_get_char(blob);   /* cipher type */
-       (void) buffer_get_int(blob);            /* reserved */
+       (void) buffer_get_char(&copy);          /* cipher type */
+       (void) buffer_get_int(&copy);           /* reserved */
 
        /* Read the public key from the buffer. */
-       (void) buffer_get_int(blob);
+       (void) buffer_get_int(&copy);
        pub = key_new(KEY_RSA1);
-       buffer_get_bignum(blob, pub->rsa->n);
-       buffer_get_bignum(blob, pub->rsa->e);
+       buffer_get_bignum(&copy, pub->rsa->n);
+       buffer_get_bignum(&copy, pub->rsa->e);
        if (commentp)
-               *commentp = buffer_get_string(blob, NULL);
+               *commentp = buffer_get_string(&copy, NULL);
        /* The encrypted private part is not parsed by this function. */
-       buffer_clear(blob);
+       buffer_free(&copy);
 
        return pub;
 }
 
-/* Load the contents of a key file into a buffer */
-static int
+/* Load a key from a fd into a buffer */
+int
 key_load_file(int fd, const char *filename, Buffer *blob)
 {
+       u_char buf[1024];
        size_t len;
-       u_char *cp;
        struct stat st;
 
        if (fstat(fd, &st) < 0) {
@@ -325,30 +330,45 @@ key_load_file(int fd, const char *filename, Buffer *blob)
                    filename == NULL ? "" : filename,
                    filename == NULL ? "" : " ",
                    strerror(errno));
-               close(fd);
                return 0;
        }
-       if (st.st_size > 1*1024*1024) {
+       if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
+           st.st_size > MAX_KEY_FILE_SIZE) {
+ toobig:
                error("%s: key file %.200s%stoo large", __func__,
                    filename == NULL ? "" : filename,
                    filename == NULL ? "" : " ");
-               close(fd);
                return 0;
        }
-       len = (size_t)st.st_size;               /* truncated */
-
        buffer_init(blob);
-       cp = buffer_append_space(blob, len);
-
-       if (atomicio(read, fd, cp, len) != len) {
-               debug("%s: read from key file %.200s%sfailed: %.100s", __func__,
-                   filename == NULL ? "" : filename,
-                   filename == NULL ? "" : " ",
-                   strerror(errno));
+       for (;;) {
+               if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
+                       if (errno == EPIPE)
+                               break;
+                       debug("%s: read from key file %.200s%sfailed: %.100s",
+                           __func__, filename == NULL ? "" : filename,
+                           filename == NULL ? "" : " ", strerror(errno));
+                       buffer_clear(blob);
+                       bzero(buf, sizeof(buf));
+                       return 0;
+               }
+               buffer_append(blob, buf, len);
+               if (buffer_len(blob) > MAX_KEY_FILE_SIZE) {
+                       buffer_clear(blob);
+                       bzero(buf, sizeof(buf));
+                       goto toobig;
+               }
+       }
+       bzero(buf, sizeof(buf));
+       if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
+           st.st_size != buffer_len(blob)) {
+               debug("%s: key file %.200s%schanged size while reading",
+                   __func__, filename == NULL ? "" : filename,
+                   filename == NULL ? "" : " ");
                buffer_clear(blob);
-               close(fd);
                return 0;
        }
+
        return 1;
 }
 
@@ -403,6 +423,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
        CipherContext ciphercontext;
        Cipher *cipher;
        Key *prv = NULL;
+       Buffer copy;
 
        /* Check that it is at least big enough to contain the ID string. */
        if (buffer_len(blob) < sizeof(authfile_id_string)) {
@@ -419,41 +440,44 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
                debug3("Incorrect RSA1 identifier");
                return NULL;
        }
-       buffer_consume(blob, sizeof(authfile_id_string));
+       buffer_init(&copy);
+       buffer_append(&copy, buffer_ptr(blob), buffer_len(blob));
+       buffer_consume(&copy, sizeof(authfile_id_string));
 
        /* Read cipher type. */
-       cipher_type = buffer_get_char(blob);
-       (void) buffer_get_int(blob);    /* Reserved data. */
+       cipher_type = buffer_get_char(&copy);
+       (void) buffer_get_int(&copy);   /* Reserved data. */
 
        /* Read the public key from the buffer. */
-       (void) buffer_get_int(blob);
+       (void) buffer_get_int(&copy);
        prv = key_new_private(KEY_RSA1);
 
-       buffer_get_bignum(blob, prv->rsa->n);
-       buffer_get_bignum(blob, prv->rsa->e);
+       buffer_get_bignum(&copy, prv->rsa->n);
+       buffer_get_bignum(&copy, prv->rsa->e);
        if (commentp)
-               *commentp = buffer_get_string(blob, NULL);
+               *commentp = buffer_get_string(&copy, NULL);
        else
-               (void)buffer_get_string_ptr(blob, NULL);
+               (void)buffer_get_string_ptr(&copy, NULL);
 
        /* Check that it is a supported cipher. */
        cipher = cipher_by_number(cipher_type);
        if (cipher == NULL) {
                debug("Unsupported RSA1 cipher %d", cipher_type);
+               buffer_free(&copy);
                goto fail;
        }
        /* Initialize space for decrypted data. */
        buffer_init(&decrypted);
-       cp = buffer_append_space(&decrypted, buffer_len(blob));
+       cp = buffer_append_space(&decrypted, buffer_len(&copy));
 
        /* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */
        cipher_set_key_string(&ciphercontext, cipher, passphrase,
            CIPHER_DECRYPT);
        cipher_crypt(&ciphercontext, cp,
-           buffer_ptr(blob), buffer_len(blob));
+           buffer_ptr(&copy), buffer_len(&copy));
        cipher_cleanup(&ciphercontext);
        memset(&ciphercontext, 0, sizeof(ciphercontext));
-       buffer_clear(blob);
+       buffer_free(&copy);
 
        check1 = buffer_get_char(&decrypted);
        check2 = buffer_get_char(&decrypted);
@@ -606,7 +630,7 @@ key_perm_ok(int fd, const char *filename)
                error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                error("Permissions 0%3.3o for '%s' are too open.",
                    (u_int)st.st_mode & 0777, filename);
-               error("It is recommended that your private key files are NOT accessible by others.");
+               error("It is required that your private key files are NOT accessible by others.");
                error("This private key will be ignored.");
                return 0;
        }
@@ -626,6 +650,7 @@ key_parse_private_type(Buffer *blob, int type, const char *passphrase,
        case KEY_UNSPEC:
                return key_parse_private_pem(blob, type, passphrase, commentp);
        default:
+               error("%s: cannot parse key type %d", __func__, type);
                break;
        }
        return NULL;
@@ -669,12 +694,35 @@ key_load_private_type(int type, const char *filename, const char *passphrase,
        return ret;
 }
 
+Key *
+key_parse_private(Buffer *buffer, const char *filename,
+    const char *passphrase, char **commentp)
+{
+       Key *pub, *prv;
+
+       /* it's a SSH v1 key if the public key part is readable */
+       pub = key_parse_public_rsa1(buffer, commentp);
+       if (pub == NULL) {
+               prv = key_parse_private_type(buffer, KEY_UNSPEC,
+                   passphrase, NULL);
+               /* use the filename as a comment for PEM */
+               if (commentp && prv)
+                       *commentp = xstrdup(filename);
+       } else {
+               key_free(pub);
+               /* key_parse_public_rsa1() has already loaded the comment */
+               prv = key_parse_private_type(buffer, KEY_RSA1, passphrase,
+                   NULL);
+       }
+       return prv;
+}
+
 Key *
 key_load_private(const char *filename, const char *passphrase,
     char **commentp)
 {
-       Key *pub, *prv;
-       Buffer buffer, pubcopy;
+       Key *prv;
+       Buffer buffer;
        int fd;
 
        fd = open(filename, O_RDONLY);
@@ -697,23 +745,7 @@ key_load_private(const char *filename, const char *passphrase,
        }
        close(fd);
 
-       buffer_init(&pubcopy);
-       buffer_append(&pubcopy, buffer_ptr(&buffer), buffer_len(&buffer));
-       /* it's a SSH v1 key if the public key part is readable */
-       pub = key_parse_public_rsa1(&pubcopy, commentp);
-       buffer_free(&pubcopy);
-       if (pub == NULL) {
-               prv = key_parse_private_type(&buffer, KEY_UNSPEC,
-                   passphrase, NULL);
-               /* use the filename as a comment for PEM */
-               if (commentp && prv)
-                       *commentp = xstrdup(filename);
-       } else {
-               key_free(pub);
-               /* key_parse_public_rsa1() has already loaded the comment */
-               prv = key_parse_private_type(&buffer, KEY_RSA1, passphrase,
-                   NULL);
-       }
+       prv = key_parse_private(&buffer, filename, passphrase, commentp);
        buffer_free(&buffer);
        return prv;
 }
@@ -737,13 +769,19 @@ key_try_load_public(Key *k, const char *filename, char **commentp)
                        case '\0':
                                continue;
                        }
+                       /* Abort loading if this looks like a private key */
+                       if (strncmp(cp, "-----BEGIN", 10) == 0)
+                               break;
                        /* Skip leading whitespace. */
                        for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
                                ;
                        if (*cp) {
                                if (key_read(k, &cp) == 1) {
-                                       if (commentp)
-                                               *commentp=xstrdup(filename);
+                                       cp[strcspn(cp, "\r\n")] = '\0';
+                                       if (commentp) {
+                                               *commentp = xstrdup(*cp ?
+                                                   cp : filename);
+                                       }
                                        fclose(f);
                                        return 1;
                                }
index 6745dc0..78349be 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.h,v 1.15 2010/08/04 05:42:47 djm Exp $ */
+/* $OpenBSD: authfile.h,v 1.16 2011/05/04 21:15:29 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
 #define AUTHFILE_H
 
 int     key_save_private(Key *, const char *, const char *, const char *);
+int     key_load_file(int, const char *, Buffer *);
 Key    *key_load_cert(const char *);
 Key    *key_load_public(const char *, char **);
 Key    *key_load_public_type(int, const char *, char **);
+Key    *key_parse_private(Buffer *, const char *, const char *, char **);
 Key    *key_load_private(const char *, const char *, char **);
 Key    *key_load_private_cert(int, const char *, const char *, int *);
 Key    *key_load_private_type(int, const char *, const char *, char **, int *);
index 6abe2d0..24d4a9f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.310 2010/11/24 01:24:14 djm Exp $ */
+/* $OpenBSD: channels.c,v 1.311 2011/06/22 22:08:42 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -3562,7 +3562,7 @@ deny_input_open(int type, u_int32_t seq, void *ctxt)
  */
 void
 x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
-    const char *proto, const char *data)
+    const char *proto, const char *data, int want_reply)
 {
        u_int data_len = (u_int) strlen(data) / 2;
        u_int i, value;
@@ -3615,7 +3615,7 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp,
 
        /* Send the request packet. */
        if (compat20) {
-               channel_request_start(client_session_id, "x11-req", 0);
+               channel_request_start(client_session_id, "x11-req", want_reply);
                packet_put_char(0);     /* XXX bool single connection */
        } else {
                packet_start(SSH_CMSG_X11_REQUEST_FORWARDING);
index 0680ed0..e2941c8 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.104 2010/05/14 23:29:23 djm Exp $ */
+/* $OpenBSD: channels.h,v 1.105 2011/06/22 22:08:42 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -271,7 +271,7 @@ int  x11_connect_display(void);
 int     x11_create_display_inet(int, int, int, u_int *, int **);
 void     x11_input_open(int, u_int32_t, void *);
 void    x11_request_forwarding_with_spoofing(int, const char *, const char *,
-            const char *);
+            const char *, int);
 void    deny_input_open(int, u_int32_t, void *);
 
 /* agent forwarding */
index f6c1444..c19b01f 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.c,v 1.231 2011/01/16 12:05:59 djm Exp $ */
+/* $OpenBSD: clientloop.c,v 1.236 2011/06/22 22:08:42 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -130,9 +130,6 @@ extern int muxserver_sock; /* XXX use mux_client_cleanup() instead */
  */
 extern char *host;
 
-/* Force TTY allocation */
-extern int force_tty_flag;
-
 /*
  * Flag to indicate that we have received a window change signal which has
  * not yet been processed.  This will cause a message indicating the new
@@ -179,7 +176,8 @@ struct escape_filter_ctx {
 /* Context for channel confirmation replies */
 struct channel_reply_ctx {
        const char *request_type;
-       int id, do_close;
+       int id;
+       enum confirm_action action;
 };
 
 /* Global request success/failure callbacks */
@@ -265,10 +263,10 @@ static void
 set_control_persist_exit_time(void)
 {
        if (muxserver_sock == -1 || !options.control_persist
-           || options.control_persist_timeout == 0)
+           || options.control_persist_timeout == 0) {
                /* not using a ControlPersist timeout */
                control_persist_exit_time = 0;
-       else if (channel_still_open()) {
+       else if (channel_still_open()) {
                /* some client connections are still open */
                if (control_persist_exit_time > 0)
                        debug2("%s: cancel scheduled exit", __func__);
@@ -662,7 +660,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
                atomicio(vwrite, fileno(stderr), buffer_ptr(berr),
                    buffer_len(berr));
 
-       leave_raw_mode(force_tty_flag);
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 
        /*
         * Free (and clear) the buffer to reduce the amount of data that gets
@@ -683,7 +681,7 @@ client_suspend_self(Buffer *bin, Buffer *bout, Buffer *berr)
        buffer_init(bout);
        buffer_init(berr);
 
-       enter_raw_mode(force_tty_flag);
+       enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 }
 
 static void
@@ -742,6 +740,15 @@ client_status_confirm(int type, Channel *c, void *ctx)
        char errmsg[256];
        int tochan;
 
+       /*
+        * If a TTY was explicitly requested, then a failure to allocate
+        * one is fatal.
+        */
+       if (cr->action == CONFIRM_TTY &&
+           (options.request_tty == REQUEST_TTY_FORCE ||
+           options.request_tty == REQUEST_TTY_YES))
+               cr->action = CONFIRM_CLOSE;
+
        /* XXX supress on mux _client_ quietmode */
        tochan = options.log_level >= SYSLOG_LEVEL_ERROR &&
            c->ctl_chan != -1 && c->extended_usage == CHAN_EXTENDED_WRITE;
@@ -759,14 +766,27 @@ client_status_confirm(int type, Channel *c, void *ctx)
                            cr->request_type, c->self);
                }
                /* If error occurred on primary session channel, then exit */
-               if (cr->do_close && c->self == session_ident)
+               if (cr->action == CONFIRM_CLOSE && c->self == session_ident)
                        fatal("%s", errmsg);
-               /* If error occurred on mux client, append to their stderr */
-               if (tochan)
-                       buffer_append(&c->extended, errmsg, strlen(errmsg));
-               else
+               /*
+                * If error occurred on mux client, append to
+                * their stderr.
+                */
+               if (tochan) {
+                       buffer_append(&c->extended, errmsg,
+                           strlen(errmsg));
+               } else
                        error("%s", errmsg);
-               if (cr->do_close) {
+               if (cr->action == CONFIRM_TTY) {
+                       /*
+                        * If a TTY allocation error occurred, then arrange
+                        * for the correct TTY to leave raw mode.
+                        */
+                       if (c->self == session_ident)
+                               leave_raw_mode(0);
+                       else
+                               mux_tty_alloc_failed(c);
+               } else if (cr->action == CONFIRM_CLOSE) {
                        chan_read_failed(c);
                        chan_write_failed(c);
                }
@@ -780,13 +800,14 @@ client_abandon_status_confirm(Channel *c, void *ctx)
        xfree(ctx);
 }
 
-static void
-client_expect_confirm(int id, const char *request, int do_close)
+void
+client_expect_confirm(int id, const char *request,
+    enum confirm_action action)
 {
        struct channel_reply_ctx *cr = xmalloc(sizeof(*cr));
 
        cr->request_type = request;
-       cr->do_close = do_close;
+       cr->action = action;
 
        channel_register_status_confirm(id, client_status_confirm,
            client_abandon_status_confirm, cr);
@@ -826,7 +847,7 @@ process_cmdline(void)
        bzero(&fwd, sizeof(fwd));
        fwd.listen_host = fwd.connect_host = NULL;
 
-       leave_raw_mode(force_tty_flag);
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
        handler = signal(SIGINT, SIG_IGN);
        cmd = s = read_passphrase("\r\nssh> ", RP_ECHO);
        if (s == NULL)
@@ -930,7 +951,7 @@ process_cmdline(void)
 
 out:
        signal(SIGINT, handler);
-       enter_raw_mode(force_tty_flag);
+       enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
        if (cmd)
                xfree(cmd);
        if (fwd.listen_host != NULL)
@@ -1049,7 +1070,8 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr,
                                 * more new connections).
                                 */
                                /* Restore tty modes. */
-                               leave_raw_mode(force_tty_flag);
+                               leave_raw_mode(
+                                   options.request_tty == REQUEST_TTY_FORCE);
 
                                /* Stop listening for new connections. */
                                channel_stop_listening();
@@ -1344,7 +1366,7 @@ client_channel_closed(int id, void *arg)
 {
        channel_cancel_cleanup(id);
        session_closed = 1;
-       leave_raw_mode(force_tty_flag);
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 }
 
 /*
@@ -1415,18 +1437,21 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
        signal(SIGWINCH, window_change_handler);
 
        if (have_pty)
-               enter_raw_mode(force_tty_flag);
+               enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 
        if (compat20) {
                session_ident = ssh2_chan_id;
-               if (escape_char_arg != SSH_ESCAPECHAR_NONE)
-                       channel_register_filter(session_ident,
-                           client_simple_escape_filter, NULL,
-                           client_filter_cleanup,
-                           client_new_escape_filter_ctx(escape_char_arg));
-               if (session_ident != -1)
+               if (session_ident != -1) {
+                       if (escape_char_arg != SSH_ESCAPECHAR_NONE) {
+                               channel_register_filter(session_ident,
+                                   client_simple_escape_filter, NULL,
+                                   client_filter_cleanup,
+                                   client_new_escape_filter_ctx(
+                                   escape_char_arg));
+                       }
                        channel_register_cleanup(session_ident,
                            client_channel_closed, 0);
+               }
        } else {
                /* Check if we should immediately send eof on stdin. */
                client_check_initial_eof_on_stdin();
@@ -1556,7 +1581,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
        channel_free_all();
 
        if (have_pty)
-               leave_raw_mode(force_tty_flag);
+               leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 
        /* restore blocking io */
        if (!isatty(fileno(stdin)))
@@ -1982,7 +2007,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
                        memset(&ws, 0, sizeof(ws));
 
                channel_request_start(id, "pty-req", 1);
-               client_expect_confirm(id, "PTY allocation", 1);
+               client_expect_confirm(id, "PTY allocation", CONFIRM_TTY);
                packet_put_cstring(term != NULL ? term : "");
                packet_put_int((u_int)ws.ws_col);
                packet_put_int((u_int)ws.ws_row);
@@ -2041,18 +2066,18 @@ client_session2_setup(int id, int want_tty, int want_subsystem,
                        debug("Sending subsystem: %.*s",
                            len, (u_char*)buffer_ptr(cmd));
                        channel_request_start(id, "subsystem", 1);
-                       client_expect_confirm(id, "subsystem", 1);
+                       client_expect_confirm(id, "subsystem", CONFIRM_CLOSE);
                } else {
                        debug("Sending command: %.*s",
                            len, (u_char*)buffer_ptr(cmd));
                        channel_request_start(id, "exec", 1);
-                       client_expect_confirm(id, "exec", 1);
+                       client_expect_confirm(id, "exec", CONFIRM_CLOSE);
                }
                packet_put_string(buffer_ptr(cmd), buffer_len(cmd));
                packet_send();
        } else {
                channel_request_start(id, "shell", 1);
-               client_expect_confirm(id, "shell", 1);
+               client_expect_confirm(id, "shell", CONFIRM_CLOSE);
                packet_send();
        }
 }
@@ -2122,11 +2147,26 @@ client_init_dispatch(void)
                client_init_dispatch_15();
 }
 
+void
+client_stop_mux(void)
+{
+       if (options.control_path != NULL && muxserver_sock != -1)
+               unlink(options.control_path);
+       /*
+        * If we are in persist mode, signal that we should close when all
+        * active channels are closed.
+        */
+       if (options.control_persist) {
+               session_closed = 1;
+               setproctitle("[stopped mux]");
+       }
+}
+
 /* client specific fatal cleanup */
 void
 cleanup_exit(int i)
 {
-       leave_raw_mode(force_tty_flag);
+       leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
        leave_non_blocking();
        if (options.control_path != NULL && muxserver_sock != -1)
                unlink(options.control_path);
index 52115db..a259b5e 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: clientloop.h,v 1.25 2010/06/25 23:15:36 djm Exp $ */
+/* $OpenBSD: clientloop.h,v 1.28 2011/06/22 22:08:42 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -45,6 +45,7 @@ void   client_global_request_reply_fwd(int, u_int32_t, void *);
 void    client_session2_setup(int, int, int, const char *, struct termios *,
            int, Buffer *, char **);
 int     client_request_tun_fwd(int, int, int);
+void    client_stop_mux(void);
 
 /* Escape filter for protocol 2 sessions */
 void   *client_new_escape_filter_ctx(int);
@@ -55,6 +56,10 @@ int   client_simple_escape_filter(Channel *, char *, int);
 typedef void global_confirm_cb(int, u_int32_t seq, void *);
 void    client_register_global_confirm(global_confirm_cb *, void *);
 
+/* Channel request confirmation callbacks */
+enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY };
+void client_expect_confirm(int, const char *, enum confirm_action);
+
 /* Multiplexing protocol version */
 #define SSHMUX_VER                     4
 
@@ -64,7 +69,10 @@ void  client_register_global_confirm(global_confirm_cb *, void *);
 #define SSHMUX_COMMAND_TERMINATE       3       /* Ask master to exit */
 #define SSHMUX_COMMAND_STDIO_FWD       4       /* Open stdio fwd (ssh -W) */
 #define SSHMUX_COMMAND_FORWARD         5       /* Forward only, no command */
+#define SSHMUX_COMMAND_STOP            6       /* Disable mux but not conn */
 
 void   muxserver_listen(void);
 void   muxclient(const char *);
 void   mux_exit_message(Channel *, int);
+void   mux_tty_alloc_failed(Channel *);
+
index cd27306..e4ccc54 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef _DEFINES_H
 #define _DEFINES_H
 
-/* $Id: defines.h,v 1.164 2011/01/17 10:15:31 dtucker Exp $ */
+/* $Id: defines.h,v 1.167 2011/06/03 01:17:49 tim Exp $ */
 
 
 /* Constants */
@@ -45,6 +45,8 @@ enum
 /*
  * Definitions for IP type of service (ip_tos)
  */
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
 #ifndef IPTOS_LOWDELAY
 # define IPTOS_LOWDELAY          0x10
 # define IPTOS_THROUGHPUT        0x08
@@ -56,8 +58,6 @@ enum
 /*
  * Definitions for DiffServ Codepoints as per RFC2474
  */
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
 #ifndef IPTOS_DSCP_AF11
 # define       IPTOS_DSCP_AF11         0x28
 # define       IPTOS_DSCP_AF12         0x30
@@ -131,6 +131,10 @@ enum
 # define O_NONBLOCK      00004 /* Non Blocking Open */
 #endif
 
+#ifndef S_IFSOCK
+# define S_IFSOCK 0
+#endif /* S_IFSOCK */
+
 #ifndef S_ISDIR
 # define S_ISDIR(mode) (((mode) & (_S_IFMT)) == (_S_IFDIR))
 #endif /* S_ISDIR */
@@ -385,18 +389,15 @@ struct winsize {
 # define _PATH_DEVNULL "/dev/null"
 #endif
 
-#ifndef MAIL_DIRECTORY
-# define MAIL_DIRECTORY "/var/spool/mail"
-#endif
+/* user may have set a different path */
+#if defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY)
+# undef _PATH_MAILDIR MAILDIR
+#endif /* defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) */
 
-#ifndef MAILDIR
-# define MAILDIR MAIL_DIRECTORY
+#ifdef MAIL_DIRECTORY
+# define _PATH_MAILDIR MAIL_DIRECTORY
 #endif
 
-#if !defined(_PATH_MAILDIR) && defined(MAILDIR)
-# define _PATH_MAILDIR MAILDIR
-#endif /* !defined(_PATH_MAILDIR) && defined(MAILDIR) */
-
 #ifndef _PATH_NOLOGIN
 # define _PATH_NOLOGIN "/etc/nologin"
 #endif
index a821662..2d6d3ec 100644 (file)
 #include "includes.h"
 
 #include <sys/types.h>
-#include <sys/wait.h>
-
-#ifdef HAVE_SYS_STAT_H
-# include <sys/stat.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_UN_H
+# include <sys/un.h>
 #endif
 
-#ifdef HAVE_FCNTL_H
-# include <fcntl.h>
-#endif
-#include <stdarg.h>
-#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
 #include <signal.h>
+#include <string.h>
 #include <unistd.h>
+#include <stddef.h> /* for offsetof */
 
 #include <openssl/rand.h>
 #include <openssl/crypto.h>
 /*
  * Portable OpenSSH PRNG seeding:
  * If OpenSSL has not "internally seeded" itself (e.g. pulled data from
- * /dev/random), then we execute a "ssh-rand-helper" program which
- * collects entropy and writes it to stdout. The child program must
- * write at least RANDOM_SEED_SIZE bytes. The child is run with stderr
- * attached, so error/debugging output should be visible.
- *
- * XXX: we should tell the child how many bytes we need.
+ * /dev/random), then collect RANDOM_SEED_SIZE bytes of randomness from
+ * PRNGd.
  */
-
 #ifndef OPENSSL_PRNG_ONLY
+
 #define RANDOM_SEED_SIZE 48
-static uid_t original_uid, original_euid;
-#endif
 
-void
-seed_rng(void)
+/*
+ * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon
+ * listening either on 'tcp_port', or via Unix domain socket at *
+ * 'socket_path'.
+ * Either a non-zero tcp_port or a non-null socket_path must be
+ * supplied.
+ * Returns 0 on success, -1 on error
+ */
+int
+get_random_bytes_prngd(unsigned char *buf, int len,
+    unsigned short tcp_port, char *socket_path)
 {
-#ifndef OPENSSL_PRNG_ONLY
-       int devnull;
-       int p[2];
-       pid_t pid;
-       int ret;
-       unsigned char buf[RANDOM_SEED_SIZE];
-       mysig_t old_sigchld;
+       int fd, addr_len, rval, errors;
+       u_char msg[2];
+       struct sockaddr_storage addr;
+       struct sockaddr_in *addr_in = (struct sockaddr_in *)&addr;
+       struct sockaddr_un *addr_un = (struct sockaddr_un *)&addr;
+       mysig_t old_sigpipe;
+
+       /* Sanity checks */
+       if (socket_path == NULL && tcp_port == 0)
+               fatal("You must specify a port or a socket");
+       if (socket_path != NULL &&
+           strlen(socket_path) >= sizeof(addr_un->sun_path))
+               fatal("Random pool path is too long");
+       if (len <= 0 || len > 255)
+               fatal("Too many bytes (%d) to read from PRNGD", len);
+
+       memset(&addr, '\0', sizeof(addr));
+
+       if (tcp_port != 0) {
+               addr_in->sin_family = AF_INET;
+               addr_in->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+               addr_in->sin_port = htons(tcp_port);
+               addr_len = sizeof(*addr_in);
+       } else {
+               addr_un->sun_family = AF_UNIX;
+               strlcpy(addr_un->sun_path, socket_path,
+                   sizeof(addr_un->sun_path));
+               addr_len = offsetof(struct sockaddr_un, sun_path) +
+                   strlen(socket_path) + 1;
+       }
 
-       if (RAND_status() == 1) {
-               debug3("RNG is ready, skipping seeding");
-               return;
+       old_sigpipe = mysignal(SIGPIPE, SIG_IGN);
+
+       errors = 0;
+       rval = -1;
+reopen:
+       fd = socket(addr.ss_family, SOCK_STREAM, 0);
+       if (fd == -1) {
+               error("Couldn't create socket: %s", strerror(errno));
+               goto done;
        }
 
-       debug3("Seeding PRNG from %s", SSH_RAND_HELPER);
-
-       if ((devnull = open("/dev/null", O_RDWR)) == -1)
-               fatal("Couldn't open /dev/null: %s", strerror(errno));
-       if (pipe(p) == -1)
-               fatal("pipe: %s", strerror(errno));
-
-       old_sigchld = signal(SIGCHLD, SIG_DFL);
-       if ((pid = fork()) == -1)
-               fatal("Couldn't fork: %s", strerror(errno));
-       if (pid == 0) {
-               dup2(devnull, STDIN_FILENO);
-               dup2(p[1], STDOUT_FILENO);
-               /* Keep stderr open for errors */
-               close(p[0]);
-               close(p[1]);
-               close(devnull);
-
-               if (original_uid != original_euid &&
-                   ( seteuid(getuid()) == -1 ||
-                     setuid(original_uid) == -1) ) {
-                       fprintf(stderr, "(rand child) setuid(%li): %s\n",
-                           (long int)original_uid, strerror(errno));
-                       _exit(1);
+       if (connect(fd, (struct sockaddr*)&addr, addr_len) == -1) {
+               if (tcp_port != 0) {
+                       error("Couldn't connect to PRNGD port %d: %s",
+                           tcp_port, strerror(errno));
+               } else {
+                       error("Couldn't connect to PRNGD socket \"%s\": %s",
+                           addr_un->sun_path, strerror(errno));
                }
-
-               execl(SSH_RAND_HELPER, "ssh-rand-helper", NULL);
-               fprintf(stderr, "(rand child) Couldn't exec '%s': %s\n",
-                   SSH_RAND_HELPER, strerror(errno));
-               _exit(1);
+               goto done;
        }
 
-       close(devnull);
-       close(p[1]);
+       /* Send blocking read request to PRNGD */
+       msg[0] = 0x02;
+       msg[1] = len;
 
-       memset(buf, '\0', sizeof(buf));
-       ret = atomicio(read, p[0], buf, sizeof(buf));
-       if (ret == -1)
-               fatal("Couldn't read from ssh-rand-helper: %s",
+       if (atomicio(vwrite, fd, msg, sizeof(msg)) != sizeof(msg)) {
+               if (errno == EPIPE && errors < 10) {
+                       close(fd);
+                       errors++;
+                       goto reopen;
+               }
+               error("Couldn't write to PRNGD socket: %s",
                    strerror(errno));
-       if (ret != sizeof(buf))
-               fatal("ssh-rand-helper child produced insufficient data");
-
-       close(p[0]);
+               goto done;
+       }
 
-       if (waitpid(pid, &ret, 0) == -1)
-               fatal("Couldn't wait for ssh-rand-helper completion: %s",
+       if (atomicio(read, fd, buf, len) != (size_t)len) {
+               if (errno == EPIPE && errors < 10) {
+                       close(fd);
+                       errors++;
+                       goto reopen;
+               }
+               error("Couldn't read from PRNGD socket: %s",
                    strerror(errno));
-       signal(SIGCHLD, old_sigchld);
-
-       /* We don't mind if the child exits upon a SIGPIPE */
-       if (!WIFEXITED(ret) &&
-           (!WIFSIGNALED(ret) || WTERMSIG(ret) != SIGPIPE))
-               fatal("ssh-rand-helper terminated abnormally");
-       if (WEXITSTATUS(ret) != 0)
-               fatal("ssh-rand-helper exit with exit status %d", ret);
-
-       RAND_add(buf, sizeof(buf), sizeof(buf));
-       memset(buf, '\0', sizeof(buf));
+               goto done;
+       }
 
-#endif /* OPENSSL_PRNG_ONLY */
-       if (RAND_status() != 1)
-               fatal("PRNG is not seeded");
+       rval = 0;
+done:
+       mysignal(SIGPIPE, old_sigpipe);
+       if (fd != -1)
+               close(fd);
+       return rval;
 }
 
-void
-init_rng(void)
+static int
+seed_from_prngd(unsigned char *buf, size_t bytes)
 {
-       /*
-        * OpenSSL version numbers: MNNFFPPS: major minor fix patch status
-        * We match major, minor, fix and status (not patch)
-        */
-       if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L)
-               fatal("OpenSSL version mismatch. Built against %lx, you "
-                   "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
-
-#ifndef OPENSSL_PRNG_ONLY
-       original_uid = getuid();
-       original_euid = geteuid();
+#ifdef PRNGD_PORT
+       debug("trying egd/prngd port %d", PRNGD_PORT);
+       if (get_random_bytes_prngd(buf, bytes, PRNGD_PORT, NULL) == 0)
+               return 0;
+#endif
+#ifdef PRNGD_SOCKET
+       debug("trying egd/prngd socket %s", PRNGD_SOCKET);
+       if (get_random_bytes_prngd(buf, bytes, 0, PRNGD_SOCKET) == 0)
+               return 0;
 #endif
+       return -1;
 }
 
-#ifndef OPENSSL_PRNG_ONLY
 void
 rexec_send_rng_seed(Buffer *m)
 {
@@ -191,4 +201,34 @@ rexec_recv_rng_seed(Buffer *m)
                RAND_add(buf, len, len);
        }
 }
+#endif /* OPENSSL_PRNG_ONLY */
+
+void
+seed_rng(void)
+{
+#ifndef OPENSSL_PRNG_ONLY
+       unsigned char buf[RANDOM_SEED_SIZE];
 #endif
+       /*
+        * OpenSSL version numbers: MNNFFPPS: major minor fix patch status
+        * We match major, minor, fix and status (not patch)
+        */
+       if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L)
+               fatal("OpenSSL version mismatch. Built against %lx, you "
+                   "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
+
+#ifndef OPENSSL_PRNG_ONLY
+       if (RAND_status() == 1) {
+               debug3("RNG is ready, skipping seeding");
+               return;
+       }
+
+       if (seed_from_prngd(buf, sizeof(buf)) == -1)
+               fatal("Could not obtain seed from PRNGd");
+       RAND_add(buf, sizeof(buf), sizeof(buf));
+       memset(buf, '\0', sizeof(buf));
+
+#endif /* OPENSSL_PRNG_ONLY */
+       if (RAND_status() != 1)
+               fatal("PRNG is not seeded");
+}
index 2ec7ea1..c719c13 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: gss-serv.c,v 1.22 2008/05/08 12:02:23 djm Exp $ */
+/* $OpenBSD: gss-serv.c,v 1.23 2011/08/01 19:18:15 markus Exp $ */
 
 /*
  * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -229,6 +229,8 @@ ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name)
        name->length = get_u32(tok+offset);
        offset += 4;
 
+       if (UINT_MAX - offset < name->length)
+               return GSS_S_FAILURE;
        if (ename->length < offset+name->length)
                return GSS_S_FAILURE;
 
index e3a305e..498cf5a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.c,v 1.96 2011/02/04 00:44:21 djm Exp $ */
+/* $OpenBSD: key.c,v 1.97 2011/05/17 07:13:31 djm Exp $ */
 /*
  * read_bignum():
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1817,6 +1817,9 @@ key_to_certified(Key *k, int legacy)
                k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
                return 0;
        case KEY_ECDSA:
+               if (legacy)
+                       fatal("%s: legacy ECDSA certificates are not supported",
+                           __func__);
                k->cert = cert_new();
                k->type = KEY_ECDSA_CERT;
                return 0;
index 4a8239b..ad5a10b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.c,v 1.41 2008/06/10 04:50:25 dtucker Exp $ */
+/* $OpenBSD: log.c,v 1.42 2011/06/17 21:44:30 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -56,6 +56,8 @@ static LogLevel log_level = SYSLOG_LEVEL_INFO;
 static int log_on_stderr = 1;
 static int log_facility = LOG_AUTH;
 static char *argv0;
+static log_handler_fn *log_handler;
+static void *log_handler_ctx;
 
 extern char *__progname;
 
@@ -260,6 +262,9 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
                exit(1);
        }
 
+       log_handler = NULL;
+       log_handler_ctx = NULL;
+
        log_on_stderr = on_stderr;
        if (on_stderr)
                return;
@@ -326,6 +331,23 @@ log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
 
 #define MSGBUFSIZ 1024
 
+void
+set_log_handler(log_handler_fn *handler, void *ctx)
+{
+       log_handler = handler;
+       log_handler_ctx = ctx;
+}
+
+void
+do_log2(LogLevel level, const char *fmt,...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+       do_log(level, fmt, args);
+       va_end(args);
+}
+
 void
 do_log(LogLevel level, const char *fmt, va_list args)
 {
@@ -337,6 +359,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
        char *txt = NULL;
        int pri = LOG_INFO;
        int saved_errno = errno;
+       log_handler_fn *tmp_handler;
 
        if (level > log_level)
                return;
@@ -375,7 +398,7 @@ do_log(LogLevel level, const char *fmt, va_list args)
                pri = LOG_ERR;
                break;
        }
-       if (txt != NULL) {
+       if (txt != NULL && log_handler == NULL) {
                snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
                vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
        } else {
@@ -383,7 +406,13 @@ do_log(LogLevel level, const char *fmt, va_list args)
        }
        strnvis(fmtbuf, msgbuf, sizeof(fmtbuf),
            log_on_stderr ? LOG_STDERR_VIS : LOG_SYSLOG_VIS);
-       if (log_on_stderr) {
+       if (log_handler != NULL) {
+               /* Avoid recursion */
+               tmp_handler = log_handler;
+               log_handler = NULL;
+               tmp_handler(level, fmtbuf, log_handler_ctx);
+               log_handler = tmp_handler;
+       } else if (log_on_stderr) {
                snprintf(msgbuf, sizeof msgbuf, "%s\r\n", fmtbuf);
                write(STDERR_FILENO, msgbuf, strlen(msgbuf));
        } else {
index 6505827..1b8d214 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: log.h,v 1.17 2008/06/13 00:12:02 dtucker Exp $ */
+/* $OpenBSD: log.h,v 1.18 2011/06/17 21:44:30 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -46,6 +46,8 @@ typedef enum {
        SYSLOG_LEVEL_NOT_SET = -1
 }       LogLevel;
 
+typedef void (log_handler_fn)(LogLevel, const char *, void *);
+
 void     log_init(char *, LogLevel, SyslogFacility, int);
 
 SyslogFacility log_facility_number(char *);
@@ -64,6 +66,10 @@ void     debug(const char *, ...) __attribute__((format(printf, 1, 2)));
 void     debug2(const char *, ...) __attribute__((format(printf, 1, 2)));
 void     debug3(const char *, ...) __attribute__((format(printf, 1, 2)));
 
+
+void    set_log_handler(log_handler_fn *, void *);
+void    do_log2(LogLevel, const char *, ...)
+    __attribute__((format(printf, 2, 3)));
 void    do_log(LogLevel, const char *, va_list);
 void    cleanup_exit(int) __attribute__((noreturn));
 #endif
index fabc3ed..eef50f4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mac.c,v 1.15 2008/06/13 00:51:47 dtucker Exp $ */
+/* $OpenBSD: mac.c,v 1.16 2011/08/02 01:22:11 djm Exp $ */
 /*
  * Copyright (c) 2001 Markus Friedl.  All rights reserved.
  *
@@ -57,6 +57,12 @@ struct {
 } macs[] = {
        { "hmac-sha1",                  SSH_EVP, EVP_sha1, 0, -1, -1 },
        { "hmac-sha1-96",               SSH_EVP, EVP_sha1, 96, -1, -1 },
+#ifdef HAVE_EVP_SHA256
+       { "hmac-sha2-256",              SSH_EVP, EVP_sha256, 0, -1, -1 },
+       { "hmac-sha2-256-96",           SSH_EVP, EVP_sha256, 96, -1, -1 },
+       { "hmac-sha2-512",              SSH_EVP, EVP_sha512, 0, -1, -1 },
+       { "hmac-sha2-512-96",           SSH_EVP, EVP_sha512, 96, -1, -1 },
+#endif
        { "hmac-md5",                   SSH_EVP, EVP_md5, 0, -1, -1 },
        { "hmac-md5-96",                SSH_EVP, EVP_md5, 96, -1, -1 },
        { "hmac-ripemd160",             SSH_EVP, EVP_ripemd160, 0, -1, -1 },
index 919b04e..5f63090 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.84 2010/11/21 01:01:13 djm Exp $ */
+/* $OpenBSD: misc.c,v 1.85 2011/03/29 18:54:17 stevesk Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.
@@ -985,6 +985,19 @@ parse_ipqos(const char *cp)
        return val;
 }
 
+const char *
+iptos2str(int iptos)
+{
+       int i;
+       static char iptos_str[sizeof "0xff"];
+
+       for (i = 0; ipqos[i].name != NULL; i++) {
+               if (ipqos[i].value == iptos)
+                       return ipqos[i].name;
+       }
+       snprintf(iptos_str, sizeof iptos_str, "0x%02x", iptos);
+       return iptos_str;
+}
 void
 sock_set_v6only(int s)
 {
index 65cf4a6..f3142a9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.h,v 1.47 2010/11/21 01:01:13 djm Exp $ */
+/* $OpenBSD: misc.h,v 1.48 2011/03/29 18:54:17 stevesk Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -89,6 +89,7 @@ void bandwidth_limit_init(struct bwlimit *, u_int64_t, size_t);
 void bandwidth_limit(struct bwlimit *, size_t);
 
 int parse_ipqos(const char *);
+const char *iptos2str(int);
 void mktemp_proto(char *, size_t);
 
 /* readpass.c */
index 4a99439..0e01b94 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: moduli.5,v 1.12 2008/06/26 05:57:54 djm Exp $
+.\"    $OpenBSD: moduli.5,v 1.15 2010/10/14 20:41:28 jmc Exp $
 .\"
 .\" Copyright (c) 2008 Damien Miller <djm@mindrot.org>
 .\"
 .\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-.Dd $Mdocdate: June 26 2008 $
+.Dd $Mdocdate: October 14 2010 $
 .Dt MODULI 5
 .Os
 .Sh NAME
 .Nm moduli
-.Nd Diffie Hellman moduli
+.Nd Diffie-Hellman moduli
 .Sh DESCRIPTION
 The
 .Pa /etc/moduli
-file contains prime numbers and generators for use by 
+file contains prime numbers and generators for use by
 .Xr sshd 8
 in the Diffie-Hellman Group Exchange key exchange method.
 .Pp
@@ -31,24 +31,23 @@ New moduli may be generated with
 using a two-step process.
 An initial
 .Em candidate generation
-pass, using 
+pass, using
 .Ic ssh-keygen -G ,
 calculates numbers that are likely to be useful.
 A second
 .Em primality testing
 pass, using
-.Ic ssh-keygen -T
+.Ic ssh-keygen -T ,
 provides a high degree of assurance that the numbers are prime and are
-safe for use in Diffie Hellman operations by
+safe for use in Diffie-Hellman operations by
 .Xr sshd 8 .
 This
 .Nm
 format is used as the output from each pass.
 .Pp
 The file consists of newline-separated records, one per modulus,
-containing seven space separated fields.
+containing seven space-separated fields.
 These fields are as follows:
-.Pp
 .Bl -tag -width Description -offset indent
 .It timestamp
 The time that the modulus was last processed as YYYYMMDDHHMMSS.
@@ -58,7 +57,7 @@ Supported types are:
 .Pp
 .Bl -tag -width 0x00 -compact
 .It 0
-Unknown, not tested
+Unknown, not tested.
 .It 2
 "Safe" prime; (p-1)/2 is also prime.
 .It 4
@@ -68,7 +67,7 @@ Sophie Germain; (p+1)*2 is also prime.
 Moduli candidates initially produced by
 .Xr ssh-keygen 1
 are Sophie Germain primes (type 4).
-Futher primality testing with
+Further primality testing with
 .Xr ssh-keygen 1
 produces safe prime moduli (type 2) that are ready for use in
 .Xr sshd 8 .
@@ -79,13 +78,13 @@ has been subjected to represented as a bitmask of the following values:
 .Pp
 .Bl -tag -width 0x00 -compact
 .It 0x00
-Not tested
+Not tested.
 .It 0x01
-Composite number - not prime.
+Composite number \(en not prime.
 .It 0x02
-Sieve of Eratosthenes
+Sieve of Eratosthenes.
 .It 0x04
-Probabalistic Miller-Rabin primality tests.
+Probabilistic Miller-Rabin primality tests.
 .El
 .Pp
 The
@@ -95,8 +94,8 @@ Subsequent
 .Xr ssh-keygen 1
 primality tests are Miller-Rabin tests (flag 0x04).
 .It trials
-Decimal number indicating of primaility trials that have been performed
-on the modulus.
+Decimal number indicating the number of primality trials
+that have been performed on the modulus.
 .It size
 Decimal number indicating the size of the prime in bits.
 .It generator
@@ -105,18 +104,17 @@ The recommended generator for use with this modulus (hexadecimal).
 The modulus itself in hexadecimal.
 .El
 .Pp
-When performing Diffie Hellman Group Exchange,
+When performing Diffie-Hellman Group Exchange,
 .Xr sshd 8
 first estimates the size of the modulus required to produce enough
-Diffie Hellman output to sufficiently key the selected symmetric cipher.
+Diffie-Hellman output to sufficiently key the selected symmetric cipher.
 .Xr sshd 8
 then randomly selects a modulus from
 .Fa /etc/moduli
 that best meets the size requirement.
-.Pp
 .Sh SEE ALSO
 .Xr ssh-keygen 1 ,
-.Xr sshd 8 ,
+.Xr sshd 8
 .Rs
 .%R RFC 4419
 .%T "Diffie-Hellman Group Exchange for the Secure Shell (SSH) Transport Layer Protocol"
index 29d987c..a166fed 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.110 2010/09/09 10:45:45 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.115 2011/06/23 23:35:42 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+# ifdef HAVE_SYS_POLL_H
+#  include <sys/poll.h>
+# endif
+#endif
 
 #ifdef SKEY
 #include <skey.h>
@@ -52,6 +59,7 @@
 #include <openssl/dh.h>
 
 #include "openbsd-compat/sys-queue.h"
+#include "atomicio.h"
 #include "xmalloc.h"
 #include "ssh.h"
 #include "key.h"
@@ -179,6 +187,8 @@ int mm_answer_audit_event(int, Buffer *);
 int mm_answer_audit_command(int, Buffer *);
 #endif
 
+static int monitor_read_log(struct monitor *);
+
 static Authctxt *authctxt;
 static BIGNUM *ssh1_challenge = NULL;  /* used for ssh1 rsa auth */
 
@@ -346,6 +356,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
 
        debug3("preauth child monitor started");
 
+       close(pmonitor->m_recvfd);
+       close(pmonitor->m_log_sendfd);
+       pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
+
        authctxt = _authctxt;
        memset(authctxt, 0, sizeof(*authctxt));
 
@@ -405,6 +419,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
 #endif
        }
 
+       /* Drain any buffered messages from the child */
+       while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0)
+               ;
+
        if (!authctxt->valid)
                fatal("%s: authenticated invalid user", __func__);
        if (strcmp(auth_method, "unknown") == 0)
@@ -414,6 +432,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
            __func__, authctxt->user);
 
        mm_get_keystate(pmonitor);
+
+       close(pmonitor->m_sendfd);
+       close(pmonitor->m_log_recvfd);
+       pmonitor->m_sendfd = pmonitor->m_log_recvfd = -1;
 }
 
 static void
@@ -431,6 +453,9 @@ monitor_child_handler(int sig)
 void
 monitor_child_postauth(struct monitor *pmonitor)
 {
+       close(pmonitor->m_recvfd);
+       pmonitor->m_recvfd = -1;
+
        monitor_set_child_handler(pmonitor->m_pid);
        signal(SIGHUP, &monitor_child_handler);
        signal(SIGTERM, &monitor_child_handler);
@@ -454,6 +479,9 @@ monitor_child_postauth(struct monitor *pmonitor)
 
        for (;;)
                monitor_read(pmonitor, mon_dispatch, NULL);
+
+       close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
 }
 
 void
@@ -465,6 +493,52 @@ monitor_sync(struct monitor *pmonitor)
        }
 }
 
+static int
+monitor_read_log(struct monitor *pmonitor)
+{
+       Buffer logmsg;
+       u_int len, level;
+       char *msg;
+
+       buffer_init(&logmsg);
+
+       /* Read length */
+       buffer_append_space(&logmsg, 4);
+       if (atomicio(read, pmonitor->m_log_recvfd,
+           buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg)) {
+               if (errno == EPIPE) {
+                       debug("%s: child log fd closed", __func__);
+                       close(pmonitor->m_log_recvfd);
+                       pmonitor->m_log_recvfd = -1;
+                       return -1;
+               }
+               fatal("%s: log fd read: %s", __func__, strerror(errno));
+       }
+       len = buffer_get_int(&logmsg);
+       if (len <= 4 || len > 8192)
+               fatal("%s: invalid log message length %u", __func__, len);
+
+       /* Read severity, message */
+       buffer_clear(&logmsg);
+       buffer_append_space(&logmsg, len);
+       if (atomicio(read, pmonitor->m_log_recvfd,
+           buffer_ptr(&logmsg), buffer_len(&logmsg)) != buffer_len(&logmsg))
+               fatal("%s: log fd read: %s", __func__, strerror(errno));
+
+       /* Log it */
+       level = buffer_get_int(&logmsg);
+       msg = buffer_get_string(&logmsg, NULL);
+       if (log_level_name(level) == NULL)
+               fatal("%s: invalid log level %u (corrupted message?)",
+                   __func__, level);
+       do_log2(level, "%s [preauth]", msg);
+
+       buffer_free(&logmsg);
+       xfree(msg);
+
+       return 0;
+}
+
 int
 monitor_read(struct monitor *pmonitor, struct mon_table *ent,
     struct mon_table **pent)
@@ -472,6 +546,30 @@ monitor_read(struct monitor *pmonitor, struct mon_table *ent,
        Buffer m;
        int ret;
        u_char type;
+       struct pollfd pfd[2];
+
+       for (;;) {
+               bzero(&pfd, sizeof(pfd));
+               pfd[0].fd = pmonitor->m_sendfd;
+               pfd[0].events = POLLIN;
+               pfd[1].fd = pmonitor->m_log_recvfd;
+               pfd[1].events = pfd[1].fd == -1 ? 0 : POLLIN;
+               if (poll(pfd, pfd[1].fd == -1 ? 1 : 2, -1) == -1) {
+                       if (errno == EINTR || errno == EAGAIN)
+                               continue;
+                       fatal("%s: poll: %s", __func__, strerror(errno));
+               }
+               if (pfd[1].revents) {
+                       /*
+                        * Drain all log messages before processing next
+                        * monitor request.
+                        */
+                       monitor_read_log(pmonitor);
+                       continue;
+               }
+               if (pfd[0].revents)
+                       break;  /* Continues below */
+       }
 
        buffer_init(&m);
 
@@ -632,6 +730,7 @@ mm_answer_pwnamallow(int sock, Buffer *m)
        char *username;
        struct passwd *pwent;
        int allowed = 0;
+       u_int i;
 
        debug3("%s", __func__);
 
@@ -671,8 +770,20 @@ mm_answer_pwnamallow(int sock, Buffer *m)
 
  out:
        buffer_put_string(m, &options, sizeof(options));
-       if (options.banner != NULL)
-               buffer_put_cstring(m, options.banner);
+
+#define M_CP_STROPT(x) do { \
+               if (options.x != NULL) \
+                       buffer_put_cstring(m, options.x); \
+       } while (0)
+#define M_CP_STRARRAYOPT(x, nx) do { \
+               for (i = 0; i < options.nx; i++) \
+                       buffer_put_cstring(m, options.x[i]); \
+       } while (0)
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+       
        debug3("%s: sending MONITOR_ANS_PWNAM: %d", __func__, allowed);
        mm_request_send(sock, MONITOR_ANS_PWNAM, m);
 
@@ -684,7 +795,6 @@ mm_answer_pwnamallow(int sock, Buffer *m)
                monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
                monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
        }
-
 #ifdef USE_PAM
        if (options.use_pam)
                monitor_permit(mon_dispatch, MONITOR_REQ_PAM_START, 1);
@@ -1834,22 +1944,31 @@ mm_init_compression(struct mm_master *mm)
 /* XXX */
 
 #define FD_CLOSEONEXEC(x) do { \
-       if (fcntl(x, F_SETFD, 1) == -1) \
+       if (fcntl(x, F_SETFD, FD_CLOEXEC) == -1) \
                fatal("fcntl(%d, F_SETFD)", x); \
 } while (0)
 
 static void
-monitor_socketpair(int *pair)
+monitor_openfds(struct monitor *mon, int do_logfds)
 {
-#ifdef HAVE_SOCKETPAIR
+       int pair[2];
+
        if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
-               fatal("%s: socketpair", __func__);
-#else
-       fatal("%s: UsePrivilegeSeparation=yes not supported",
-           __func__);
-#endif
+               fatal("%s: socketpair: %s", __func__, strerror(errno));
        FD_CLOSEONEXEC(pair[0]);
        FD_CLOSEONEXEC(pair[1]);
+       mon->m_recvfd = pair[0];
+       mon->m_sendfd = pair[1];
+
+       if (do_logfds) {
+               if (pipe(pair) == -1)
+                       fatal("%s: pipe: %s", __func__, strerror(errno));
+               FD_CLOSEONEXEC(pair[0]);
+               FD_CLOSEONEXEC(pair[1]);
+               mon->m_log_recvfd = pair[0];
+               mon->m_log_sendfd = pair[1];
+       } else
+               mon->m_log_recvfd = mon->m_log_sendfd = -1;
 }
 
 #define MM_MEMSIZE     65536
@@ -1858,14 +1977,10 @@ struct monitor *
 monitor_init(void)
 {
        struct monitor *mon;
-       int pair[2];
 
        mon = xcalloc(1, sizeof(*mon));
 
-       monitor_socketpair(pair);
-
-       mon->m_recvfd = pair[0];
-       mon->m_sendfd = pair[1];
+       monitor_openfds(mon, 1);
 
        /* Used to share zlib space across processes */
        if (options.compression) {
@@ -1882,12 +1997,7 @@ monitor_init(void)
 void
 monitor_reinit(struct monitor *mon)
 {
-       int pair[2];
-
-       monitor_socketpair(pair);
-
-       mon->m_recvfd = pair[0];
-       mon->m_sendfd = pair[1];
+       monitor_openfds(mon, 0);
 }
 
 #ifdef GSSAPI
index a8a2c0c..5e7d552 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.h,v 1.15 2008/11/04 08:22:13 djm Exp $ */
+/* $OpenBSD: monitor.h,v 1.16 2011/06/17 21:44:31 djm Exp $ */
 
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -72,6 +72,8 @@ struct mm_master;
 struct monitor {
        int                      m_recvfd;
        int                      m_sendfd;
+       int                      m_log_recvfd;
+       int                      m_log_sendfd;
        struct mm_master        *m_zback;
        struct mm_master        *m_zlib;
        struct Kex              **m_pkex;
index 1a5dda5..1f60658 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.70 2010/08/31 11:54:45 djm Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.73 2011/06/17 21:44:31 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -88,6 +88,32 @@ extern struct monitor *pmonitor;
 extern Buffer loginmsg;
 extern ServerOptions options;
 
+void
+mm_log_handler(LogLevel level, const char *msg, void *ctx)
+{
+       Buffer log_msg;
+       struct monitor *mon = (struct monitor *)ctx;
+
+       if (mon->m_log_sendfd == -1)
+               fatal("%s: no log channel", __func__);
+
+       buffer_init(&log_msg);
+       /*
+        * Placeholder for packet length. Will be filled in with the actual
+        * packet length once the packet has been constucted. This saves
+        * fragile math.
+        */
+       buffer_put_int(&log_msg, 0);
+
+       buffer_put_int(&log_msg, level);
+       buffer_put_cstring(&log_msg, msg);
+       put_u32(buffer_ptr(&log_msg), buffer_len(&log_msg) - 4);
+       if (atomicio(vwrite, mon->m_log_sendfd, buffer_ptr(&log_msg),
+           buffer_len(&log_msg)) != buffer_len(&log_msg))
+               fatal("%s: write: %s", __func__, strerror(errno));
+       buffer_free(&log_msg);
+}
+
 int
 mm_is_monitor(void)
 {
@@ -211,7 +237,7 @@ mm_getpwnamallow(const char *username)
 {
        Buffer m;
        struct passwd *pw;
-       u_int len;
+       u_int len, i;
        ServerOptions *newopts;
 
        debug3("%s entering", __func__);
@@ -245,8 +271,20 @@ out:
        newopts = buffer_get_string(&m, &len);
        if (len != sizeof(*newopts))
                fatal("%s: option block size mismatch", __func__);
-       if (newopts->banner != NULL)
-               newopts->banner = buffer_get_string(&m, NULL);
+
+#define M_CP_STROPT(x) do { \
+               if (newopts->x != NULL) \
+                       newopts->x = buffer_get_string(&m, NULL); \
+       } while (0)
+#define M_CP_STRARRAYOPT(x, nx) do { \
+               for (i = 0; i < newopts->nx; i++) \
+                       newopts->x[i] = buffer_get_string(&m, NULL); \
+       } while (0)
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+#undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
+
        copy_set_server_options(&options, newopts, 1);
        xfree(newopts);
 
index de2d16f..0c7f2e3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.h,v 1.22 2009/03/05 07:18:19 djm Exp $ */
+/* $OpenBSD: monitor_wrap.h,v 1.23 2011/06/17 21:44:31 djm Exp $ */
 
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -37,6 +37,7 @@ struct monitor;
 struct mm_master;
 struct Authctxt;
 
+void mm_log_handler(LogLevel, const char *, void *);
 int mm_is_monitor(void);
 DH *mm_choose_dh(int, int, int);
 int mm_key_sign(Key *, u_char **, u_int *, u_char *, u_int);
index e370462..add0e26 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mux.c,v 1.24 2011/01/13 21:54:53 djm Exp $ */
+/* $OpenBSD: mux.c,v 1.29 2011/06/22 22:08:42 djm Exp $ */
 /*
  * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
  *
@@ -87,7 +87,6 @@
 
 /* from ssh.c */
 extern int tty_flag;
-extern int force_tty_flag;
 extern Options options;
 extern int stdin_null_flag;
 extern char *host;
@@ -146,6 +145,7 @@ struct mux_master_state {
 #define MUX_C_OPEN_FWD         0x10000006
 #define MUX_C_CLOSE_FWD                0x10000007
 #define MUX_C_NEW_STDIO_FWD    0x10000008
+#define MUX_C_STOP_LISTENING   0x10000009
 #define MUX_S_OK               0x80000001
 #define MUX_S_PERMISSION_DENIED        0x80000002
 #define MUX_S_FAILURE          0x80000003
@@ -153,6 +153,7 @@ struct mux_master_state {
 #define MUX_S_ALIVE            0x80000005
 #define MUX_S_SESSION_OPENED   0x80000006
 #define MUX_S_REMOTE_PORT      0x80000007
+#define MUX_S_TTY_ALLOC_FAIL   0x80000008
 
 /* type codes for MUX_C_OPEN_FWD and MUX_C_CLOSE_FWD */
 #define MUX_FWD_LOCAL   1
@@ -168,6 +169,7 @@ static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *);
 static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *);
 static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *);
 static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *);
+static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *);
 
 static const struct {
        u_int type;
@@ -180,6 +182,7 @@ static const struct {
        { MUX_C_OPEN_FWD, process_mux_open_fwd },
        { MUX_C_CLOSE_FWD, process_mux_close_fwd },
        { MUX_C_NEW_STDIO_FWD, process_mux_stdio_fwd },
+       { MUX_C_STOP_LISTENING, process_mux_stop_listening },
        { 0, NULL }
 };
 
@@ -915,6 +918,39 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
        return 0;
 }
 
+static int
+process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
+{
+       debug("%s: channel %d: stop listening", __func__, c->self);
+
+       if (options.control_master == SSHCTL_MASTER_ASK ||
+           options.control_master == SSHCTL_MASTER_AUTO_ASK) {
+               if (!ask_permission("Disable further multiplexing on shared "
+                   "connection to %s? ", host)) {
+                       debug2("%s: stop listen refused by user", __func__);
+                       buffer_put_int(r, MUX_S_PERMISSION_DENIED);
+                       buffer_put_int(r, rid);
+                       buffer_put_cstring(r, "Permission denied");
+                       return 0;
+               }
+       }
+
+       if (mux_listener_channel != NULL) {
+               channel_free(mux_listener_channel);
+               client_stop_mux();
+               xfree(options.control_path);
+               options.control_path = NULL;
+               mux_listener_channel = NULL;
+               muxserver_sock = -1;
+       }
+
+       /* prepare reply */
+       buffer_put_int(r, MUX_S_OK);
+       buffer_put_int(r, rid);
+
+       return 0;
+}
+
 /* Channel callbacks fired on read/write from mux slave fd */
 static int
 mux_master_read_cb(Channel *c)
@@ -1019,6 +1055,27 @@ mux_exit_message(Channel *c, int exitval)
        buffer_free(&m);
 }
 
+void
+mux_tty_alloc_failed(Channel *c)
+{
+       Buffer m;
+       Channel *mux_chan;
+
+       debug3("%s: channel %d: TTY alloc failed", __func__, c->self);
+
+       if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL)
+               fatal("%s: channel %d missing mux channel %d",
+                   __func__, c->self, c->ctl_chan);
+
+       /* Append exit message packet to control socket output queue */
+       buffer_init(&m);
+       buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL);
+       buffer_put_int(&m, c->self);
+
+       buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m));
+       buffer_free(&m);
+}
+
 /* Prepare a mux master to listen on a Unix domain socket. */
 void
 muxserver_listen(void)
@@ -1059,21 +1116,25 @@ muxserver_listen(void)
            strlen(options.control_path) + 1;
 
        if (strlcpy(addr.sun_path, options.control_path,
-           sizeof(addr.sun_path)) >= sizeof(addr.sun_path))
-               fatal("ControlPath too long");
+           sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
+               error("ControlPath \"%s\" too long for Unix domain socket",
+                   options.control_path);
+               goto disable_mux_master;
+       }
 
        if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
                fatal("%s socket(): %s", __func__, strerror(errno));
 
        old_umask = umask(0177);
        if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) {
-               muxserver_sock = -1;
                if (errno == EINVAL || errno == EADDRINUSE) {
                        error("ControlSocket %s already exists, "
                            "disabling multiplexing", options.control_path);
  disable_mux_master:
-                       close(muxserver_sock);
-                       muxserver_sock = -1;
+                       if (muxserver_sock != -1) {
+                               close(muxserver_sock);
+                               muxserver_sock = -1;
+                       }
                        xfree(options.control_path);
                        options.control_path = NULL;
                        options.control_master = SSHCTL_MASTER_NO;
@@ -1153,8 +1214,10 @@ mux_session_confirm(int id, int success, void *arg)
                /* Request forwarding with authentication spoofing. */
                debug("Requesting X11 forwarding with authentication "
                    "spoofing.");
-               x11_request_forwarding_with_spoofing(id, display, proto, data);
-               /* XXX wait for reply */
+               x11_request_forwarding_with_spoofing(id, display, proto,
+                   data, 1);
+               client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN);
+               /* XXX exit_on_forward_failure */
        }
 
        if (cctx->want_agent_fwd && options.forward_agent) {
@@ -1573,7 +1636,7 @@ mux_client_request_session(int fd)
        char *e, *term;
        u_int i, rid, sid, esid, exitval, type, exitval_seen;
        extern char **environ;
-       int devnull;
+       int devnull, rawmode;
 
        debug3("%s: entering", __func__);
 
@@ -1669,8 +1732,9 @@ mux_client_request_session(int fd)
        signal(SIGTERM, control_client_sighandler);
        signal(SIGWINCH, control_client_sigrelay);
 
+       rawmode = tty_flag;
        if (tty_flag)
-               enter_raw_mode(force_tty_flag);
+               enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 
        /*
         * Stick around until the controlee closes the client_fd.
@@ -1684,22 +1748,35 @@ mux_client_request_session(int fd)
                if (mux_client_read_packet(fd, &m) != 0)
                        break;
                type = buffer_get_int(&m);
-               if (type != MUX_S_EXIT_MESSAGE) {
+               switch (type) {
+               case MUX_S_TTY_ALLOC_FAIL:
+                       if ((esid = buffer_get_int(&m)) != sid)
+                               fatal("%s: tty alloc fail on unknown session: "
+                                   "my id %u theirs %u",
+                                   __func__, sid, esid);
+                       leave_raw_mode(options.request_tty ==
+                           REQUEST_TTY_FORCE);
+                       rawmode = 0;
+                       continue;
+               case MUX_S_EXIT_MESSAGE:
+                       if ((esid = buffer_get_int(&m)) != sid)
+                               fatal("%s: exit on unknown session: "
+                                   "my id %u theirs %u",
+                                   __func__, sid, esid);
+                       if (exitval_seen)
+                               fatal("%s: exitval sent twice", __func__);
+                       exitval = buffer_get_int(&m);
+                       exitval_seen = 1;
+                       continue;
+               default:
                        e = buffer_get_string(&m, NULL);
                        fatal("%s: master returned error: %s", __func__, e);
                }
-               if ((esid = buffer_get_int(&m)) != sid)
-                       fatal("%s: exit on unknown session: my id %u theirs %u",
-                           __func__, sid, esid);
-               debug("%s: master session id: %u", __func__, sid);
-               if (exitval_seen)
-                       fatal("%s: exitval sent twice", __func__);
-               exitval = buffer_get_int(&m);
-               exitval_seen = 1;
        }
 
        close(fd);
-       leave_raw_mode(force_tty_flag);
+       if (rawmode)
+               leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
 
        if (muxclient_terminate) {
                debug2("Exiting on signal %d", muxclient_terminate);
@@ -1813,6 +1890,50 @@ mux_client_request_stdio_fwd(int fd)
        fatal("%s: master returned unexpected message %u", __func__, type);
 }
 
+static void
+mux_client_request_stop_listening(int fd)
+{
+       Buffer m;
+       char *e;
+       u_int type, rid;
+
+       debug3("%s: entering", __func__);
+
+       buffer_init(&m);
+       buffer_put_int(&m, MUX_C_STOP_LISTENING);
+       buffer_put_int(&m, muxclient_request_id);
+
+       if (mux_client_write_packet(fd, &m) != 0)
+               fatal("%s: write packet: %s", __func__, strerror(errno));
+
+       buffer_clear(&m);
+
+       /* Read their reply */
+       if (mux_client_read_packet(fd, &m) != 0)
+               fatal("%s: read from master failed: %s",
+                   __func__, strerror(errno));
+
+       type = buffer_get_int(&m);
+       if ((rid = buffer_get_int(&m)) != muxclient_request_id)
+               fatal("%s: out of sequence reply: my id %u theirs %u",
+                   __func__, muxclient_request_id, rid);
+       switch (type) {
+       case MUX_S_OK:
+               break;
+       case MUX_S_PERMISSION_DENIED:
+               e = buffer_get_string(&m, NULL);
+               fatal("Master refused stop listening request: %s", e);
+       case MUX_S_FAILURE:
+               e = buffer_get_string(&m, NULL);
+               fatal("%s: stop listening request failed: %s", __func__, e);
+       default:
+               fatal("%s: unexpected response from master 0x%08x",
+                   __func__, type);
+       }
+       buffer_free(&m);
+       muxclient_request_id++;
+}
+
 /* Multiplex client main loop. */
 void
 muxclient(const char *path)
@@ -1906,6 +2027,10 @@ muxclient(const char *path)
        case SSHMUX_COMMAND_STDIO_FWD:
                mux_client_request_stdio_fwd(sock);
                exit(0);
+       case SSHMUX_COMMAND_STOP:
+               mux_client_request_stop_listening(sock);
+               fprintf(stderr, "Stop listening request sent.\r\n");
+               exit(0);
        default:
                fatal("unrecognised muxclient_command %d", muxclient_command);
        }
index 2c43607..0bc1c77 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: myproposal.h,v 1.27 2010/09/01 22:42:13 djm Exp $ */
+/* $OpenBSD: myproposal.h,v 1.28 2011/08/02 01:22:11 djm Exp $ */
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
        "arcfour256,arcfour128," \
        "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
        "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"
+#ifdef HAVE_EVP_SHA256
+#define        SHA2_HMAC_MODES \
+       "hmac-sha2-256," \
+       "hmac-sha2-256-96," \
+       "hmac-sha2-512," \
+       "hmac-sha2-512-96,"
+#else
+# define SHA2_HMAC_MODES
+#endif
 #define        KEX_DEFAULT_MAC \
-       "hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160," \
+       "hmac-md5," \
+       "hmac-sha1," \
+       "umac-64@openssh.com," \
+       SHA2_HMAC_MODES \
+       "hmac-ripemd160," \
        "hmac-ripemd160@openssh.com," \
-       "hmac-sha1-96,hmac-md5-96"
+       "hmac-sha1-96," \
+       "hmac-md5-96"
+
 #define        KEX_DEFAULT_COMP        "none,zlib@openssh.com,zlib"
 #define        KEX_DEFAULT_LANG        ""
 
index 39b8eb7..48f64b7 100644 (file)
@@ -1,7 +1,7 @@
-/* $Id: bsd-cygwin_util.h,v 1.12 2009/03/08 00:40:28 dtucker Exp $ */
+/* $Id: bsd-cygwin_util.h,v 1.13 2011/08/17 01:31:09 djm Exp $ */
 
 /*
- * Copyright (c) 2000, 2001, Corinna Vinschen <vinschen@cygnus.com>
+ * Copyright (c) 2000, 2001, 2011 Corinna Vinschen <vinschen@redhat.com>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #include <io.h>
 
 int binary_open(const char *, int , ...);
-int binary_pipe(int fd[2]);
 int check_ntsec(const char *);
 char **fetch_windows_environment(void);
 void free_windows_environment(char **);
 
 #define open binary_open
-#define pipe binary_pipe
 
 #endif /* HAVE_CYGWIN */
 
index 6d4f3f2..c5fc24e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: openssl-compat.h,v 1.18 2011/01/21 22:37:06 dtucker Exp $ */
+/* $Id: openssl-compat.h,v 1.19 2011/05/10 01:13:38 dtucker Exp $ */
 
 /*
  * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
@@ -106,10 +106,10 @@ RSA_METHOD *RSA_get_default_method(void);
 #  endif
 
 # ifdef USE_OPENSSL_ENGINE
-#  ifdef SSLeay_add_all_algorithms
-#   undef SSLeay_add_all_algorithms
+#  ifdef OpenSSL_add_all_algorithms
+#   undef OpenSSL_add_all_algorithms
 #  endif
-#  define SSLeay_add_all_algorithms()  ssh_SSLeay_add_all_algorithms()
+#  define OpenSSL_add_all_algorithms()  ssh_OpenSSL_add_all_algorithms()
 # endif
 
 # ifndef HAVE_BN_IS_PRIME_EX
@@ -129,6 +129,6 @@ int ssh_EVP_CipherInit(EVP_CIPHER_CTX *, const EVP_CIPHER *, unsigned char *,
     unsigned char *, int);
 int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int);
 int ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *);
-void ssh_SSLeay_add_all_algorithms(void);
+void ssh_OpenSSL_add_all_algorithms(void);
 #endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */
 
index c2f6184..e3d1004 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: port-linux.h,v 1.4.10.1 2011/02/04 00:42:21 djm Exp $ */
+/* $Id: port-linux.h,v 1.5 2011/01/25 01:16:18 djm Exp $ */
 
 /*
  * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
index b4e01f7..ba93417 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.172 2010/11/13 23:27:50 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.173 2011/05/06 21:14:05 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -422,10 +422,8 @@ packet_set_state(int mode, u_int32_t seqnr, u_int64_t blocks, u_int32_t packets,
        state->bytes = bytes;
 }
 
-/* returns 1 if connection is via ipv4 */
-
-int
-packet_connection_is_ipv4(void)
+static int
+packet_connection_af(void)
 {
        struct sockaddr_storage to;
        socklen_t tolen = sizeof(to);
@@ -439,9 +437,9 @@ packet_connection_is_ipv4(void)
 #ifdef IPV4_IN_IPV6
        if (to.ss_family == AF_INET6 &&
            IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&to)->sin6_addr))
-               return 1;
+               return AF_INET;
 #endif
-       return 0;
+       return to.ss_family;
 }
 
 /* Sets the connection into non-blocking mode. */
@@ -1752,16 +1750,30 @@ packet_not_very_much_data_to_write(void)
 static void
 packet_set_tos(int tos)
 {
-#if defined(IP_TOS) && !defined(IP_TOS_IS_BROKEN)
-       if (!packet_connection_is_on_socket() ||
-           !packet_connection_is_ipv4())
+#ifndef IP_TOS_IS_BROKEN
+       if (!packet_connection_is_on_socket())
                return;
-       debug3("%s: set IP_TOS 0x%02x", __func__, tos);
-       if (setsockopt(active_state->connection_in, IPPROTO_IP, IP_TOS, &tos,
-           sizeof(tos)) < 0)
-               error("setsockopt IP_TOS %d: %.100s:",
-                   tos, strerror(errno));
-#endif
+       switch (packet_connection_af()) {
+# ifdef IP_TOS
+       case AF_INET:
+               debug3("%s: set IP_TOS 0x%02x", __func__, tos);
+               if (setsockopt(active_state->connection_in,
+                   IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)
+                       error("setsockopt IP_TOS %d: %.100s:",
+                           tos, strerror(errno));
+               break;
+# endif /* IP_TOS */
+# ifdef IPV6_TCLASS
+       case AF_INET6:
+               debug3("%s: set IPV6_TCLASS 0x%02x", __func__, tos);
+               if (setsockopt(active_state->connection_in,
+                   IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof(tos)) < 0)
+                       error("setsockopt IPV6_TCLASS %d: %.100s:",
+                           tos, strerror(errno));
+               break;
+# endif /* IPV6_TCLASS */
+       }
+#endif /* IP_TOS_IS_BROKEN */
 }
 
 /* Informs that the current session is interactive.  Sets IP flags for that. */
index d516aae..90eec17 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.55 2010/11/13 23:27:50 djm Exp $ */
+/* $OpenBSD: packet.h,v 1.56 2011/05/06 21:14:05 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -92,7 +92,6 @@ int      packet_have_data_to_write(void);
 int      packet_not_very_much_data_to_write(void);
 
 int     packet_connection_is_on_socket(void);
-int     packet_connection_is_ipv4(void);
 int     packet_remaining(void);
 void    packet_send_ignore(int);
 void    packet_add_padding(u_char);
index e2dd49a..c3d9abf 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: pathnames.h,v 1.20 2010/08/31 11:54:45 djm Exp $ */
+/* $OpenBSD: pathnames.h,v 1.22 2011/05/23 03:30:07 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
index eb4a8b9..91dfa56 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.190 2010/11/13 23:27:50 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.193 2011/05/24 07:15:47 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -134,7 +134,7 @@ typedef enum {
        oHashKnownHosts,
        oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
        oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
-       oKexAlgorithms, oIPQoS,
+       oKexAlgorithms, oIPQoS, oRequestTTY,
        oDeprecated, oUnsupported
 } OpCodes;
 
@@ -193,9 +193,9 @@ static struct {
        { "host", oHost },
        { "escapechar", oEscapeChar },
        { "globalknownhostsfile", oGlobalKnownHostsFile },
-       { "globalknownhostsfile2", oGlobalKnownHostsFile2 },    /* obsolete */
+       { "globalknownhostsfile2", oDeprecated },
        { "userknownhostsfile", oUserKnownHostsFile },
-       { "userknownhostsfile2", oUserKnownHostsFile2 },        /* obsolete */
+       { "userknownhostsfile2", oDeprecated }, 
        { "connectionattempts", oConnectionAttempts },
        { "batchmode", oBatchMode },
        { "checkhostip", oCheckHostIP },
@@ -245,6 +245,7 @@ static struct {
 #endif
        { "kexalgorithms", oKexAlgorithms },
        { "ipqos", oIPQoS },
+       { "requesttty", oRequestTTY },
 
        { NULL, oBadOption }
 };
@@ -353,8 +354,10 @@ process_config_line(Options *options, const char *host,
                    char *line, const char *filename, int linenum,
                    int *activep)
 {
-       char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
-       int opcode, *intptr, value, value2, scale;
+       char *s, **charptr, *endofnumber, *keyword, *arg, *arg2;
+       char **cpptr, fwdarg[256];
+       u_int *uintptr, max_entries = 0;
+       int negated, opcode, *intptr, value, value2, scale;
        LogLevel *log_level_ptr;
        long long orig, val64;
        size_t len;
@@ -597,26 +600,33 @@ parse_yesnoask:
 parse_string:
                arg = strdelim(&s);
                if (!arg || *arg == '\0')
-                       fatal("%.200s line %d: Missing argument.", filename, linenum);
+                       fatal("%.200s line %d: Missing argument.",
+                           filename, linenum);
                if (*activep && *charptr == NULL)
                        *charptr = xstrdup(arg);
                break;
 
        case oGlobalKnownHostsFile:
-               charptr = &options->system_hostfile;
-               goto parse_string;
+               cpptr = (char **)&options->system_hostfiles;
+               uintptr = &options->num_system_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+parse_char_array:
+               if (*activep && *uintptr == 0) {
+                       while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                               if ((*uintptr) >= max_entries)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               cpptr[(*uintptr)++] = xstrdup(arg);
+                       }
+               }
+               return 0;
 
        case oUserKnownHostsFile:
-               charptr = &options->user_hostfile;
-               goto parse_string;
-
-       case oGlobalKnownHostsFile2:
-               charptr = &options->system_hostfile2;
-               goto parse_string;
-
-       case oUserKnownHostsFile2:
-               charptr = &options->user_hostfile2;
-               goto parse_string;
+               cpptr = (char **)&options->user_hostfiles;
+               uintptr = &options->num_user_hostfiles;
+               max_entries = SSH_MAX_HOSTS_FILES;
+               goto parse_char_array;
 
        case oHostName:
                charptr = &options->hostname;
@@ -793,12 +803,28 @@ parse_int:
 
        case oHost:
                *activep = 0;
-               while ((arg = strdelim(&s)) != NULL && *arg != '\0')
+               arg2 = NULL;
+               while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
+                       negated = *arg == '!';
+                       if (negated)
+                               arg++;
                        if (match_pattern(host, arg)) {
-                               debug("Applying options for %.100s", arg);
+                               if (negated) {
+                                       debug("%.200s line %d: Skipping Host "
+                                           "block because of negated match "
+                                           "for %.100s", filename, linenum,
+                                           arg);
+                                       *activep = 0;
+                                       break;
+                               }
+                               if (!*activep)
+                                       arg2 = arg; /* logged below */
                                *activep = 1;
-                               break;
                        }
+               }
+               if (*activep)
+                       debug("%.200s line %d: Applying options for %.100s",
+                           filename, linenum, arg2);
                /* Avoid garbage check below, as strdelim is done. */
                return 0;
 
@@ -997,6 +1023,26 @@ parse_int:
                intptr = &options->use_roaming;
                goto parse_flag;
 
+       case oRequestTTY:
+               arg = strdelim(&s);
+               if (!arg || *arg == '\0')
+                       fatal("%s line %d: missing argument.",
+                           filename, linenum);
+               intptr = &options->request_tty;
+               if (strcasecmp(arg, "yes") == 0)
+                       value = REQUEST_TTY_YES;
+               else if (strcasecmp(arg, "no") == 0)
+                       value = REQUEST_TTY_NO;
+               else if (strcasecmp(arg, "force") == 0)
+                       value = REQUEST_TTY_FORCE;
+               else if (strcasecmp(arg, "auto") == 0)
+                       value = REQUEST_TTY_AUTO;
+               else
+                       fatal("Unsupported RequestTTY \"%s\"", arg);
+               if (*activep && *intptr == -1)
+                       *intptr = value;
+               break;
+
        case oDeprecated:
                debug("%s line %d: Deprecated option \"%s\"",
                    filename, linenum, keyword);
@@ -1121,10 +1167,8 @@ initialize_options(Options * options)
        options->proxy_command = NULL;
        options->user = NULL;
        options->escape_char = -1;
-       options->system_hostfile = NULL;
-       options->user_hostfile = NULL;
-       options->system_hostfile2 = NULL;
-       options->user_hostfile2 = NULL;
+       options->num_system_hostfiles = 0;
+       options->num_user_hostfiles = 0;
        options->local_forwards = NULL;
        options->num_local_forwards = 0;
        options->remote_forwards = NULL;
@@ -1157,6 +1201,7 @@ initialize_options(Options * options)
        options->zero_knowledge_password_authentication = -1;
        options->ip_qos_interactive = -1;
        options->ip_qos_bulk = -1;
+       options->request_tty = -1;
 }
 
 /*
@@ -1263,14 +1308,18 @@ fill_default_options(Options * options)
        }
        if (options->escape_char == -1)
                options->escape_char = '~';
-       if (options->system_hostfile == NULL)
-               options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
-       if (options->user_hostfile == NULL)
-               options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
-       if (options->system_hostfile2 == NULL)
-               options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
-       if (options->user_hostfile2 == NULL)
-               options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
+       if (options->num_system_hostfiles == 0) {
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
+               options->system_hostfiles[options->num_system_hostfiles++] =
+                   xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
+       }
+       if (options->num_user_hostfiles == 0) {
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE);
+               options->user_hostfiles[options->num_user_hostfiles++] =
+                   xstrdup(_PATH_SSH_USER_HOSTFILE2);
+       }
        if (options->log_level == SYSLOG_LEVEL_NOT_SET)
                options->log_level = SYSLOG_LEVEL_INFO;
        if (options->clear_forwardings == 1)
@@ -1315,6 +1364,8 @@ fill_default_options(Options * options)
                options->ip_qos_interactive = IPTOS_LOWDELAY;
        if (options->ip_qos_bulk == -1)
                options->ip_qos_bulk = IPTOS_THROUGHPUT;
+       if (options->request_tty == -1)
+               options->request_tty = REQUEST_TTY_AUTO;
        /* options->local_command should not be set by default */
        /* options->proxy_command should not be set by default */
        /* options->user will be set in the main program if appropriate */
index ee160df..5944cff 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.88 2010/11/13 23:27:50 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.90 2011/05/24 07:15:47 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -27,7 +27,8 @@ typedef struct {
 }       Forward;
 /* Data structure for representing option data. */
 
-#define MAX_SEND_ENV   256
+#define MAX_SEND_ENV           256
+#define SSH_MAX_HOSTS_FILES    256
 
 typedef struct {
        int     forward_agent;  /* Forward authentication agent. */
@@ -83,10 +84,10 @@ typedef struct {
        char   *user;           /* User to log in as. */
        int     escape_char;    /* Escape character; -2 = none */
 
-       char   *system_hostfile;/* Path for /etc/ssh/ssh_known_hosts. */
-       char   *user_hostfile;  /* Path for $HOME/.ssh/known_hosts. */
-       char   *system_hostfile2;
-       char   *user_hostfile2;
+       u_int   num_system_hostfiles;   /* Paths for /etc/ssh/ssh_known_hosts */
+       char   *system_hostfiles[SSH_MAX_HOSTS_FILES];
+       u_int   num_user_hostfiles;     /* Path for $HOME/.ssh/known_hosts */
+       char   *user_hostfiles[SSH_MAX_HOSTS_FILES];
        char   *preferred_authentications;
        char   *bind_address;   /* local socket address for connection to sshd */
        char   *pkcs11_provider; /* PKCS#11 provider */
@@ -132,6 +133,7 @@ typedef struct {
 
        int     use_roaming;
 
+       int     request_tty;
 }       Options;
 
 #define SSHCTL_MASTER_NO       0
@@ -140,6 +142,11 @@ typedef struct {
 #define SSHCTL_MASTER_ASK      3
 #define SSHCTL_MASTER_AUTO_ASK 4
 
+#define REQUEST_TTY_AUTO       0
+#define REQUEST_TTY_NO         1
+#define REQUEST_TTY_YES                2
+#define REQUEST_TTY_FORCE      3
+
 void     initialize_options(Options *);
 void     fill_default_options(Options *);
 int     read_config_file(const char *, const char *, Options *, int);
diff --git a/crypto/openssh/sandbox-rlimit.c b/crypto/openssh/sandbox-rlimit.c
new file mode 100644 (file)
index 0000000..761e928
--- /dev/null
@@ -0,0 +1,93 @@
+/* $OpenBSD: sandbox-rlimit.c,v 1.3 2011/06/23 09:34:13 djm Exp $ */
+/*
+ * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#ifdef SANDBOX_RLIMIT
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "ssh-sandbox.h"
+#include "xmalloc.h"
+
+/* Minimal sandbox that sets zero nfiles, nprocs and filesize rlimits */
+
+struct ssh_sandbox {
+       pid_t child_pid;
+};
+
+struct ssh_sandbox *
+ssh_sandbox_init(void)
+{
+       struct ssh_sandbox *box;
+
+       /*
+        * Strictly, we don't need to maintain any state here but we need
+        * to return non-NULL to satisfy the API.
+        */
+       debug3("%s: preparing rlimit sandbox", __func__);
+       box = xcalloc(1, sizeof(*box));
+       box->child_pid = 0;
+
+       return box;
+}
+
+void
+ssh_sandbox_child(struct ssh_sandbox *box)
+{
+       struct rlimit rl_zero;
+
+       rl_zero.rlim_cur = rl_zero.rlim_max = 0;
+
+       if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1)
+               fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s",
+                       __func__, strerror(errno));
+       if (setrlimit(RLIMIT_NOFILE, &rl_zero) == -1)
+               fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s",
+                       __func__, strerror(errno));
+#ifdef HAVE_RLIMIT_NPROC
+       if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1)
+               fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s",
+                       __func__, strerror(errno));
+#endif
+}
+
+void
+ssh_sandbox_parent_finish(struct ssh_sandbox *box)
+{
+       free(box);
+       debug3("%s: finished", __func__);
+}
+
+void
+ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid)
+{
+       box->child_pid = child_pid;
+}
+
+#endif /* SANDBOX_RLIMIT */
index e2f20a3..91986e5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.c,v 1.213 2010/11/13 23:27:50 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.222 2011/06/22 21:57:01 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -126,8 +126,7 @@ initialize_server_options(ServerOptions *options)
        options->use_dns = -1;
        options->client_alive_interval = -1;
        options->client_alive_count_max = -1;
-       options->authorized_keys_file = NULL;
-       options->authorized_keys_file2 = NULL;
+       options->num_authkeys_files = 0;
        options->num_accept_env = 0;
        options->permit_tun = -1;
        options->num_permitted_opens = -1;
@@ -264,15 +263,12 @@ fill_default_server_options(ServerOptions *options)
                options->client_alive_interval = 0;
        if (options->client_alive_count_max == -1)
                options->client_alive_count_max = 3;
-       if (options->authorized_keys_file2 == NULL) {
-               /* authorized_keys_file2 falls back to authorized_keys_file */
-               if (options->authorized_keys_file != NULL)
-                       options->authorized_keys_file2 = xstrdup(options->authorized_keys_file);
-               else
-                       options->authorized_keys_file2 = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
+       if (options->num_authkeys_files == 0) {
+               options->authorized_keys_files[options->num_authkeys_files++] =
+                   xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
+               options->authorized_keys_files[options->num_authkeys_files++] =
+                   xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
        }
-       if (options->authorized_keys_file == NULL)
-               options->authorized_keys_file = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
        if (options->permit_tun == -1)
                options->permit_tun = SSH_TUNMODE_NO;
        if (options->zero_knowledge_password_authentication == -1)
@@ -284,7 +280,7 @@ fill_default_server_options(ServerOptions *options)
 
        /* Turn privilege separation on by default */
        if (use_privsep == -1)
-               use_privsep = 1;
+               use_privsep = PRIVSEP_ON;
 
 #ifndef HAVE_MMAP
        if (use_privsep && options->compression == 1) {
@@ -321,7 +317,7 @@ typedef enum {
        sMaxStartups, sMaxAuthTries, sMaxSessions,
        sBanner, sUseDNS, sHostbasedAuthentication,
        sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
-       sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
+       sClientAliveCountMax, sAuthorizedKeysFile,
        sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
        sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
        sUsePrivilegeSeparation, sAllowAgentForwarding,
@@ -438,7 +434,7 @@ static struct {
        { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
        { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
        { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
-       { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL },
+       { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
        { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
        { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
        { "permittunnel", sPermitTunnel, SSHCFG_ALL },
@@ -675,6 +671,43 @@ match_cfg_line(char **condition, int line, const char *user, const char *host,
 
 #define WHITESPACE " \t\r\n"
 
+/* Multistate option parsing */
+struct multistate {
+       char *key;
+       int value;
+};
+static const struct multistate multistate_addressfamily[] = {
+       { "inet",                       AF_INET },
+       { "inet6",                      AF_INET6 },
+       { "any",                        AF_UNSPEC },
+       { NULL, -1 }
+};
+static const struct multistate multistate_permitrootlogin[] = {
+       { "without-password",           PERMIT_NO_PASSWD },
+       { "forced-commands-only",       PERMIT_FORCED_ONLY },
+       { "yes",                        PERMIT_YES },
+       { "no",                         PERMIT_NO },
+       { NULL, -1 }
+};
+static const struct multistate multistate_compression[] = {
+       { "delayed",                    COMP_DELAYED },
+       { "yes",                        COMP_ZLIB },
+       { "no",                         COMP_NONE },
+       { NULL, -1 }
+};
+static const struct multistate multistate_gatewayports[] = {
+       { "clientspecified",            2 },
+       { "yes",                        1 },
+       { "no",                         0 },
+       { NULL, -1 }
+};
+static const struct multistate multistate_privsep[] = {
+       { "sandbox",                    PRIVSEP_SANDBOX },
+       { "yes",                        PRIVSEP_ON },
+       { "no",                         PRIVSEP_OFF },
+       { NULL, -1 }
+};
+
 int
 process_server_config_line(ServerOptions *options, char *line,
     const char *filename, int linenum, int *activep, const char *user,
@@ -688,6 +721,7 @@ process_server_config_line(ServerOptions *options, char *line,
        int port;
        u_int i, flags = 0;
        size_t len;
+       const struct multistate *multistate_ptr;
 
        cp = line;
        if ((arg = strdelim(&cp)) == NULL)
@@ -803,24 +837,27 @@ process_server_config_line(ServerOptions *options, char *line,
                break;
 
        case sAddressFamily:
+               intptr = &options->address_family;
+               multistate_ptr = multistate_addressfamily;
+               if (options->listen_addrs != NULL)
+                       fatal("%s line %d: address family must be specified "
+                           "before ListenAddress.", filename, linenum);
+ parse_multistate:
                arg = strdelim(&cp);
                if (!arg || *arg == '\0')
-                       fatal("%s line %d: missing address family.",
+                       fatal("%s line %d: missing argument.",
                            filename, linenum);
-               intptr = &options->address_family;
-               if (options->listen_addrs != NULL)
-                       fatal("%s line %d: address family must be specified before "
-                           "ListenAddress.", filename, linenum);
-               if (strcasecmp(arg, "inet") == 0)
-                       value = AF_INET;
-               else if (strcasecmp(arg, "inet6") == 0)
-                       value = AF_INET6;
-               else if (strcasecmp(arg, "any") == 0)
-                       value = AF_UNSPEC;
-               else
-                       fatal("%s line %d: unsupported address family \"%s\".",
+               value = -1;
+               for (i = 0; multistate_ptr[i].key != NULL; i++) {
+                       if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
+                               value = multistate_ptr[i].value;
+                               break;
+                       }
+               }
+               if (value == -1)
+                       fatal("%s line %d: unsupported option \"%s\".",
                            filename, linenum, arg);
-               if (*intptr == -1)
+               if (*activep && *intptr == -1)
                        *intptr = value;
                break;
 
@@ -859,27 +896,8 @@ process_server_config_line(ServerOptions *options, char *line,
 
        case sPermitRootLogin:
                intptr = &options->permit_root_login;
-               arg = strdelim(&cp);
-               if (!arg || *arg == '\0')
-                       fatal("%s line %d: missing yes/"
-                           "without-password/forced-commands-only/no "
-                           "argument.", filename, linenum);
-               value = 0;      /* silence compiler */
-               if (strcmp(arg, "without-password") == 0)
-                       value = PERMIT_NO_PASSWD;
-               else if (strcmp(arg, "forced-commands-only") == 0)
-                       value = PERMIT_FORCED_ONLY;
-               else if (strcmp(arg, "yes") == 0)
-                       value = PERMIT_YES;
-               else if (strcmp(arg, "no") == 0)
-                       value = PERMIT_NO;
-               else
-                       fatal("%s line %d: Bad yes/"
-                           "without-password/forced-commands-only/no "
-                           "argument: %s", filename, linenum, arg);
-               if (*activep && *intptr == -1)
-                       *intptr = value;
-               break;
+               multistate_ptr = multistate_permitrootlogin;
+               goto parse_multistate;
 
        case sIgnoreRhosts:
                intptr = &options->ignore_rhosts;
@@ -1010,43 +1028,13 @@ process_server_config_line(ServerOptions *options, char *line,
 
        case sCompression:
                intptr = &options->compression;
-               arg = strdelim(&cp);
-               if (!arg || *arg == '\0')
-                       fatal("%s line %d: missing yes/no/delayed "
-                           "argument.", filename, linenum);
-               value = 0;      /* silence compiler */
-               if (strcmp(arg, "delayed") == 0)
-                       value = COMP_DELAYED;
-               else if (strcmp(arg, "yes") == 0)
-                       value = COMP_ZLIB;
-               else if (strcmp(arg, "no") == 0)
-                       value = COMP_NONE;
-               else
-                       fatal("%s line %d: Bad yes/no/delayed "
-                           "argument: %s", filename, linenum, arg);
-               if (*intptr == -1)
-                       *intptr = value;
-               break;
+               multistate_ptr = multistate_compression;
+               goto parse_multistate;
 
        case sGatewayPorts:
                intptr = &options->gateway_ports;
-               arg = strdelim(&cp);
-               if (!arg || *arg == '\0')
-                       fatal("%s line %d: missing yes/no/clientspecified "
-                           "argument.", filename, linenum);
-               value = 0;      /* silence compiler */
-               if (strcmp(arg, "clientspecified") == 0)
-                       value = 2;
-               else if (strcmp(arg, "yes") == 0)
-                       value = 1;
-               else if (strcmp(arg, "no") == 0)
-                       value = 0;
-               else
-                       fatal("%s line %d: Bad yes/no/clientspecified "
-                           "argument: %s", filename, linenum, arg);
-               if (*activep && *intptr == -1)
-                       *intptr = value;
-               break;
+               multistate_ptr = multistate_gatewayports;
+               goto parse_multistate;
 
        case sUseDNS:
                intptr = &options->use_dns;
@@ -1084,7 +1072,8 @@ process_server_config_line(ServerOptions *options, char *line,
 
        case sUsePrivilegeSeparation:
                intptr = &use_privsep;
-               goto parse_flag;
+               multistate_ptr = multistate_privsep;
+               goto parse_multistate;
 
        case sAllowUsers:
                while ((arg = strdelim(&cp)) && *arg != '\0') {
@@ -1250,14 +1239,22 @@ process_server_config_line(ServerOptions *options, char *line,
         * AuthorizedKeysFile   /etc/ssh_keys/%u
         */
        case sAuthorizedKeysFile:
-               charptr = &options->authorized_keys_file;
-               goto parse_tilde_filename;
-       case sAuthorizedKeysFile2:
-               charptr = &options->authorized_keys_file2;
-               goto parse_tilde_filename;
+               if (*activep && options->num_authkeys_files == 0) {
+                       while ((arg = strdelim(&cp)) && *arg != '\0') {
+                               if (options->num_authkeys_files >=
+                                   MAX_AUTHKEYS_FILES)
+                                       fatal("%s line %d: "
+                                           "too many authorized keys files.",
+                                           filename, linenum);
+                               options->authorized_keys_files[
+                                   options->num_authkeys_files++] =
+                                   tilde_expand_filename(arg, getuid());
+                       }
+               }
+               return 0;
+
        case sAuthorizedPrincipalsFile:
                charptr = &options->authorized_principals_file;
- parse_tilde_filename:
                arg = strdelim(&cp);
                if (!arg || *arg == '\0')
                        fatal("%s line %d: missing file name.",
@@ -1476,6 +1473,12 @@ parse_server_match_config(ServerOptions *options, const char *user,
                dst->n = src->n; \
        } \
 } while(0)
+#define M_CP_STRARRAYOPT(n, num_n) do {\
+       if (src->num_n != 0) { \
+               for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
+                       dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
+       } \
+} while(0)
 
 /*
  * Copy any supported values that are set.
@@ -1511,20 +1514,23 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
        M_CP_INTOPT(ip_qos_interactive);
        M_CP_INTOPT(ip_qos_bulk);
 
-       M_CP_STROPT(banner);
+       /* See comment in servconf.h */
+       COPY_MATCH_STRING_OPTS();
+
+       /*
+        * The only things that should be below this point are string options
+        * which are only used after authentication.
+        */
        if (preauth)
                return;
+
        M_CP_STROPT(adm_forced_command);
        M_CP_STROPT(chroot_directory);
-       M_CP_STROPT(trusted_user_ca_keys);
-       M_CP_STROPT(revoked_keys_file);
-       M_CP_STROPT(authorized_keys_file);
-       M_CP_STROPT(authorized_keys_file2);
-       M_CP_STROPT(authorized_principals_file);
 }
 
 #undef M_CP_INTOPT
 #undef M_CP_STROPT
+#undef M_CP_STRARRAYOPT
 
 void
 parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
@@ -1550,31 +1556,34 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
 }
 
 static const char *
-fmt_intarg(ServerOpCodes code, int val)
+fmt_multistate_int(int val, const struct multistate *m)
 {
-       if (code == sAddressFamily) {
-               switch (val) {
-               case AF_INET:
-                       return "inet";
-               case AF_INET6:
-                       return "inet6";
-               case AF_UNSPEC:
-                       return "any";
-               default:
-                       return "UNKNOWN";
-               }
-       }
-       if (code == sPermitRootLogin) {
-               switch (val) {
-               case PERMIT_NO_PASSWD:
-                       return "without-password";
-               case PERMIT_FORCED_ONLY:
-                       return "forced-commands-only";
-               case PERMIT_YES:
-                       return "yes";
-               }
+       u_int i;
+
+       for (i = 0; m[i].key != NULL; i++) {
+               if (m[i].value == val)
+                       return m[i].key;
        }
-       if (code == sProtocol) {
+       return "UNKNOWN";
+}
+
+static const char *
+fmt_intarg(ServerOpCodes code, int val)
+{
+       if (val == -1)
+               return "unset";
+       switch (code) {
+       case sAddressFamily:
+               return fmt_multistate_int(val, multistate_addressfamily);
+       case sPermitRootLogin:
+               return fmt_multistate_int(val, multistate_permitrootlogin);
+       case sGatewayPorts:
+               return fmt_multistate_int(val, multistate_gatewayports);
+       case sCompression:
+               return fmt_multistate_int(val, multistate_compression);
+       case sUsePrivilegeSeparation:
+               return fmt_multistate_int(val, multistate_privsep);
+       case sProtocol:
                switch (val) {
                case SSH_PROTO_1:
                        return "1";
@@ -1585,20 +1594,16 @@ fmt_intarg(ServerOpCodes code, int val)
                default:
                        return "UNKNOWN";
                }
+       default:
+               switch (val) {
+               case 0:
+                       return "no";
+               case 1:
+                       return "yes";
+               default:
+                       return "UNKNOWN";
+               }
        }
-       if (code == sGatewayPorts && val == 2)
-               return "clientspecified";
-       if (code == sCompression && val == COMP_DELAYED)
-               return "delayed";
-       switch (val) {
-       case -1:
-               return "unset";
-       case 0:
-               return "no";
-       case 1:
-               return "yes";
-       }
-       return "UNKNOWN";
 }
 
 static const char *
@@ -1638,7 +1643,18 @@ dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
        u_int i;
 
        for (i = 0; i < count; i++)
-               printf("%s %s\n", lookup_opcode_name(code),  vals[i]);
+               printf("%s %s\n", lookup_opcode_name(code), vals[i]);
+}
+
+static void
+dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
+{
+       u_int i;
+
+       printf("%s", lookup_opcode_name(code));
+       for (i = 0; i < count; i++)
+               printf(" %s",  vals[i]);
+       printf("\n");
 }
 
 void
@@ -1736,8 +1752,6 @@ dump_config(ServerOptions *o)
        dump_cfg_string(sCiphers, o->ciphers);
        dump_cfg_string(sMacs, o->macs);
        dump_cfg_string(sBanner, o->banner);
-       dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
-       dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
        dump_cfg_string(sForceCommand, o->adm_forced_command);
        dump_cfg_string(sChrootDirectory, o->chroot_directory);
        dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
@@ -1750,6 +1764,8 @@ dump_config(ServerOptions *o)
        dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
 
        /* string array arguments */
+       dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
+           o->authorized_keys_files);
        dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
             o->host_key_files);
        dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
@@ -1775,7 +1791,8 @@ dump_config(ServerOptions *o)
                }
        dump_cfg_string(sPermitTunnel, s);
 
-       printf("ipqos 0x%02x 0x%02x\n", o->ip_qos_interactive, o->ip_qos_bulk);
+       printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
+       printf("%s\n", iptos2str(o->ip_qos_bulk));
 
        channel_print_adm_permitted_opens();
 }
index 5a058a4..89f38e2 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: servconf.h,v 1.95 2010/11/13 23:27:50 djm Exp $ */
+/* $OpenBSD: servconf.h,v 1.99 2011/06/22 21:57:01 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -27,6 +27,7 @@
 #define MAX_HOSTCERTS          256     /* Max # host certificates. */
 #define MAX_ACCEPT_ENV         256     /* Max # of env vars. */
 #define MAX_MATCH_GROUPS       256     /* Max # of groups for Match. */
+#define MAX_AUTHKEYS_FILES     256     /* Max # of authorized_keys files. */
 
 /* permit_root_login */
 #define        PERMIT_NOT_SET          -1
 #define        PERMIT_NO_PASSWD        2
 #define        PERMIT_YES              3
 
+/* use_privsep */
+#define PRIVSEP_OFF            0
+#define PRIVSEP_ON             1
+#define PRIVSEP_SANDBOX                2
+
 #define DEFAULT_AUTH_FAIL_MAX  6       /* Default for MaxAuthTries */
 #define DEFAULT_SESSIONS_MAX   10      /* Default for MaxSessions */
 
@@ -145,8 +151,8 @@ typedef struct {
                                         * disconnect the session
                                         */
 
-       char   *authorized_keys_file;   /* File containing public keys */
-       char   *authorized_keys_file2;
+       u_int num_authkeys_files;       /* Files containing public keys */
+       char   *authorized_keys_files[MAX_AUTHKEYS_FILES];
 
        char   *adm_forced_command;
 
@@ -162,6 +168,20 @@ typedef struct {
        char   *authorized_principals_file;
 }       ServerOptions;
 
+/*
+ * These are string config options that must be copied between the
+ * Match sub-config and the main config, and must be sent from the
+ * privsep slave to the privsep master. We use a macro to ensure all
+ * the options are copied and the copies are done in the correct order.
+ */
+#define COPY_MATCH_STRING_OPTS() do { \
+               M_CP_STROPT(banner); \
+               M_CP_STROPT(trusted_user_ca_keys); \
+               M_CP_STROPT(revoked_keys_file); \
+               M_CP_STROPT(authorized_principals_file); \
+               M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
+       } while (0)
+
 void    initialize_server_options(ServerOptions *);
 void    fill_default_server_options(ServerOptions *);
 int     process_server_config_line(ServerOptions *, char *, const char *, int,
index 8be01c5..19b84ff 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.159 2009/05/28 16:50:16 andreas Exp $ */
+/* $OpenBSD: serverloop.c,v 1.160 2011/05/15 08:09:01 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -131,8 +131,8 @@ notify_setup(void)
 {
        if (pipe(notify_pipe) < 0) {
                error("pipe(notify_pipe) failed %s", strerror(errno));
-       } else if ((fcntl(notify_pipe[0], F_SETFD, 1) == -1) ||
-           (fcntl(notify_pipe[1], F_SETFD, 1) == -1)) {
+       } else if ((fcntl(notify_pipe[0], F_SETFD, FD_CLOEXEC) == -1) ||
+           (fcntl(notify_pipe[1], F_SETFD, FD_CLOEXEC) == -1)) {
                error("fcntl(notify_pipe, F_SETFD) failed %s", strerror(errno));
                close(notify_pipe[0]);
                close(notify_pipe[1]);
index fff31b0..6a70400 100644 (file)
 #include <kafs.h>
 #endif
 
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#endif
+
 #define IS_INTERNAL_SFTP(c) \
        (!strncmp(c, INTERNAL_SFTP_NAME, sizeof(INTERNAL_SFTP_NAME) - 1) && \
         (c[sizeof(INTERNAL_SFTP_NAME) - 1] == '\0' || \
@@ -1531,6 +1535,9 @@ do_pwchange(Session *s)
        if (s->ttyfd != -1) {
                fprintf(stderr,
                    "You must change your password now and login again!\n");
+#ifdef WITH_SELINUX
+               setexeccon(NULL);
+#endif
 #ifdef PASSWD_NEEDS_USERNAME
                execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name,
                    (char *)NULL);
index b268d08..9d01c7d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-server.c,v 1.93 2010/12/04 00:18:01 djm Exp $ */
+/* $OpenBSD: sftp-server.c,v 1.94 2011/06/17 21:46:16 djm Exp $ */
 /*
  * Copyright (c) 2000-2004 Markus Friedl.  All rights reserved.
  *
@@ -68,7 +68,7 @@ Buffer iqueue;
 Buffer oqueue;
 
 /* Version of client */
-int version;
+u_int version;
 
 /* Disable writes */
 int readonly;
@@ -522,7 +522,7 @@ process_init(void)
        Buffer msg;
 
        version = get_int();
-       verbose("received client version %d", version);
+       verbose("received client version %u", version);
        buffer_init(&msg);
        buffer_put_char(&msg, SSH2_FXP_VERSION);
        buffer_put_int(&msg, SSH2_FILEXFER_VERSION);
index 89b5d35..eb88014 100644 (file)
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sftp.1,v 1.88 2010/12/04 00:18:01 djm Exp $
+.\" $OpenBSD: sftp.1,v 1.90 2011/08/07 12:55:30 dtucker Exp $
 .\"
 .\" Copyright (c) 2001 Damien Miller.  All rights reserved.
 .\"
@@ -22,7 +22,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: December 4 2010 $
+.Dd $Mdocdate: August 7 2011 $
 .Dt SFTP 1
 .Os
 .Sh NAME
@@ -89,6 +89,10 @@ to obviate the need to enter a password at connection time (see
 and
 .Xr ssh-keygen 1
 for details).
+.Pp
+Since some usage formats use colon characters to delimit host names from path
+names, IPv6 addresses must be enclosed in square brackets to avoid ambiguity.
+.Pp
 The options are as follows:
 .Bl -tag -width Ds
 .It Fl 1
@@ -479,7 +483,7 @@ is specified, then
 .Ar remote-path
 must specify a directory.
 .Pp
-If ether the
+If either the
 .Fl P
 or
 .Fl p
index 125d664..6d5e2a9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-add.c,v 1.100 2010/08/31 12:33:38 djm Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.101 2011/05/04 21:15:29 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -145,8 +145,12 @@ add_file(AuthenticationConnection *ac, const char *filename)
        char *comment = NULL;
        char msg[1024], *certpath;
        int fd, perms_ok, ret = -1;
+       Buffer keyblob;
 
-       if ((fd = open(filename, O_RDONLY)) < 0) {
+       if (strcmp(filename, "-") == 0) {
+               fd = STDIN_FILENO;
+               filename = "(stdin)";
+       } else if ((fd = open(filename, O_RDONLY)) < 0) {
                perror(filename);
                return -1;
        }
@@ -155,18 +159,28 @@ add_file(AuthenticationConnection *ac, const char *filename)
         * Since we'll try to load a keyfile multiple times, permission errors
         * will occur multiple times, so check perms first and bail if wrong.
         */
-       perms_ok = key_perm_ok(fd, filename);
-       close(fd);
-       if (!perms_ok)
+       if (fd != STDIN_FILENO) {
+               perms_ok = key_perm_ok(fd, filename);
+               if (!perms_ok) {
+                       close(fd);
+                       return -1;
+               }
+       }
+       buffer_init(&keyblob);
+       if (!key_load_file(fd, filename, &keyblob)) {
+               buffer_free(&keyblob);
+               close(fd);
                return -1;
+       }
+       close(fd);
 
        /* At first, try empty passphrase */
-       private = key_load_private(filename, "", &comment);
+       private = key_parse_private(&keyblob, filename, "", &comment);
        if (comment == NULL)
                comment = xstrdup(filename);
        /* try last */
        if (private == NULL && pass != NULL)
-               private = key_load_private(filename, pass, NULL);
+               private = key_parse_private(&keyblob, filename, pass, NULL);
        if (private == NULL) {
                /* clear passphrase since it did not work */
                clear_pass();
@@ -177,9 +191,11 @@ add_file(AuthenticationConnection *ac, const char *filename)
                        if (strcmp(pass, "") == 0) {
                                clear_pass();
                                xfree(comment);
+                               buffer_free(&keyblob);
                                return -1;
                        }
-                       private = key_load_private(filename, pass, &comment);
+                       private = key_parse_private(&keyblob, filename, pass,
+                           &comment);
                        if (private != NULL)
                                break;
                        clear_pass();
@@ -187,6 +203,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
                            "Bad passphrase, try again for %.200s: ", comment);
                }
        }
+       buffer_free(&keyblob);
 
        if (ssh_add_identity_constrained(ac, private, comment, lifetime,
            confirm)) {
@@ -372,7 +389,6 @@ main(int argc, char **argv)
        sanitise_stdfd();
 
        __progname = ssh_get_progname(argv[0]);
-       init_rng();
        seed_rng();
 
        OpenSSL_add_all_algorithms();
index afba413..b9498e6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-agent.c,v 1.171 2010/11/21 01:01:13 djm Exp $ */
+/* $OpenBSD: ssh-agent.c,v 1.172 2011/06/03 01:37:40 dtucker Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1097,7 +1097,11 @@ cleanup_handler(int sig)
 static void
 check_parent_exists(void)
 {
-       if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
+       /*
+        * If our parent has exited then getppid() will return (pid_t)1,
+        * so testing for that should be safe.
+        */
+       if (parent_pid != -1 && getppid() != parent_pid) {
                /* printf("Parent has died - Authentication agent exiting.\n"); */
                cleanup_socket();
                _exit(2);
@@ -1154,7 +1158,6 @@ main(int ac, char **av)
        OpenSSL_add_all_algorithms();
 
        __progname = ssh_get_progname(av[0]);
-       init_rng();
        seed_rng();
 
        while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
index 205f741..ede3792 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ssh-keygen.1,v 1.101 2010/10/28 18:33:28 jmc Exp $
+.\"    $OpenBSD: ssh-keygen.1,v 1.106 2011/04/13 04:09:37 djm Exp $
 .\"
 .\" Author: Tatu Ylonen <ylo@cs.hut.fi>
 .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,7 +35,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: October 28 2010 $
+.Dd $Mdocdate: April 13 2011 $
 .Dt SSH-KEYGEN 1
 .Os
 .Sh NAME
 .Nm ssh-keygen
 .Fl L
 .Op Fl f Ar input_keyfile
+.Nm ssh-keygen
+.Fl A
 .Ek
 .Sh DESCRIPTION
 .Nm
@@ -173,9 +175,8 @@ The passphrase can be changed later by using the
 option.
 .Pp
 There is no way to recover a lost passphrase.
-If the passphrase is
-lost or forgotten, a new key must be generated and copied to the
-corresponding public key to other machines.
+If the passphrase is lost or forgotten, a new key must be generated
+and the corresponding public key copied to other machines.
 .Pp
 For RSA1 keys,
 there is also a comment field in the key file that is only for
@@ -192,6 +193,13 @@ should be placed to be activated.
 .Pp
 The options are as follows:
 .Bl -tag -width Ds
+.It Fl A
+For each of the key types (rsa1, rsa, dsa and ecdsa) for which host keys
+do not exist, generate the host keys with the default key file path,
+an empty passphrase, default bits for the key type, and default comment.
+This is used by
+.Pa /etc/rc
+to generate new host keys.
 .It Fl a Ar trials
 Specifies the number of primality tests to perform when screening DH-GEX
 candidates using the
@@ -204,6 +212,12 @@ Specifies the number of bits in the key to create.
 For RSA keys, the minimum size is 768 bits and the default is 2048 bits.
 Generally, 2048 bits is considered sufficient.
 DSA keys must be exactly 1024 bits as specified by FIPS 186-2.
+For ECDSA keys, the
+.Fl b
+flag determines they key length by selecting from one of three elliptic
+curve sizes: 256, 384 or 521 bits.
+Attempting to use bit lengths other than these three values for ECDSA keys
+will fail.
 .It Fl C Ar comment
 Provides a new comment.
 .It Fl c
@@ -393,9 +407,6 @@ new passphrase.
 .It Fl q
 Silence
 .Nm ssh-keygen .
-Used by
-.Pa /etc/rc
-when creating a new key.
 .It Fl R Ar hostname
 Removes all keys belonging to
 .Ar hostname
index c95e4ab..4b6218b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.205 2011/01/11 06:13:10 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.210 2011/04/18 00:46:05 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 #include "hostfile.h"
 #include "dns.h"
 #include "ssh2.h"
-
-#ifdef ENABLE_PKCS11
 #include "ssh-pkcs11.h"
-#endif
 
 /* Number of bits in the RSA/DSA key.  This value can be set on the command line. */
 #define DEFAULT_BITS           2048
@@ -159,6 +156,38 @@ char hostname[MAXHOSTNAMELEN];
 int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
 int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);
 
+static void
+type_bits_valid(int type, u_int32_t *bitsp)
+{
+       u_int maxbits;
+
+       if (type == KEY_UNSPEC) {
+               fprintf(stderr, "unknown key type %s\n", key_type_name);
+               exit(1);
+       }
+       if (*bitsp == 0) {
+               if (type == KEY_DSA)
+                       *bitsp = DEFAULT_BITS_DSA;
+               else if (type == KEY_ECDSA)
+                       *bitsp = DEFAULT_BITS_ECDSA;
+               else
+                       *bitsp = DEFAULT_BITS;
+       }
+       maxbits = (type == KEY_DSA) ?
+           OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
+       if (*bitsp > maxbits) {
+               fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
+               exit(1);
+       }
+       if (type == KEY_DSA && *bitsp != 1024)
+               fatal("DSA keys must be 1024 bits");
+       else if (type != KEY_ECDSA && *bitsp < 768)
+               fatal("Key must at least be 768 bits");
+       else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1)
+               fatal("Invalid ECDSA key length - valid lengths are "
+                   "256, 384 or 521 bits");
+}
+
 static void
 ask_filename(struct passwd *pw, const char *prompt)
 {
@@ -817,6 +846,98 @@ do_fingerprint(struct passwd *pw)
        exit(0);
 }
 
+static void
+do_gen_all_hostkeys(struct passwd *pw)
+{
+       struct {
+               char *key_type;
+               char *key_type_display;
+               char *path;
+       } key_types[] = {
+               { "rsa1", "RSA1", _PATH_HOST_KEY_FILE },
+               { "rsa", "RSA" ,_PATH_HOST_RSA_KEY_FILE },
+               { "dsa", "DSA", _PATH_HOST_DSA_KEY_FILE },
+               { "ecdsa", "ECDSA",_PATH_HOST_ECDSA_KEY_FILE },
+               { NULL, NULL, NULL }
+       };
+
+       int first = 0;
+       struct stat st;
+       Key *private, *public;
+       char comment[1024];
+       int i, type, fd;
+       FILE *f;
+
+       for (i = 0; key_types[i].key_type; i++) {
+               if (stat(key_types[i].path, &st) == 0)
+                       continue;
+               if (errno != ENOENT) {
+                       printf("Could not stat %s: %s", key_types[i].path,
+                           strerror(errno));
+                       first = 0;
+                       continue;
+               }
+
+               if (first == 0) {
+                       first = 1;
+                       printf("%s: generating new host keys: ", __progname);
+               }
+               printf("%s ", key_types[i].key_type_display);
+               fflush(stdout);
+               arc4random_stir();
+               type = key_type_from_name(key_types[i].key_type);
+               strlcpy(identity_file, key_types[i].path, sizeof(identity_file));
+               bits = 0;
+               type_bits_valid(type, &bits);
+               private = key_generate(type, bits);
+               if (private == NULL) {
+                       fprintf(stderr, "key_generate failed\n");
+                       first = 0;
+                       continue;
+               }
+               public  = key_from_private(private);
+               snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
+                   hostname);
+               if (!key_save_private(private, identity_file, "", comment)) {
+                       printf("Saving the key failed: %s.\n", identity_file);
+                       key_free(private);
+                       key_free(public);
+                       first = 0;
+                       continue;
+               }
+               key_free(private);
+               arc4random_stir();
+               strlcat(identity_file, ".pub", sizeof(identity_file));
+               fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+               if (fd == -1) {
+                       printf("Could not save your public key in %s\n",
+                           identity_file);
+                       key_free(public);
+                       first = 0;
+                       continue;
+               }
+               f = fdopen(fd, "w");
+               if (f == NULL) {
+                       printf("fdopen %s failed\n", identity_file);
+                       key_free(public);
+                       first = 0;
+                       continue;
+               }
+               if (!key_write(public, f)) {
+                       fprintf(stderr, "write key failed\n");
+                       key_free(public);
+                       first = 0;
+                       continue;
+               }
+               fprintf(f, " %s\n", comment);
+               fclose(f);
+               key_free(public);
+
+       }
+       if (first != 0)
+               printf("\n");
+}
+
 static void
 printhost(FILE *f, const char *name, Key *public, int ca, int hash)
 {
@@ -1329,6 +1450,9 @@ prepare_options_buf(Buffer *c, int which)
        if ((which & OPTIONS_CRITICAL) != 0 &&
            certflags_command != NULL)
                add_string_option(c, "force-command", certflags_command);
+       if ((which & OPTIONS_EXTENSIONS) != 0 &&
+           (certflags_flags & CERTOPT_X_FWD) != 0)
+               add_flag_option(c, "permit-X11-forwarding");
        if ((which & OPTIONS_EXTENSIONS) != 0 &&
            (certflags_flags & CERTOPT_AGENT_FWD) != 0)
                add_flag_option(c, "permit-agent-forwarding");
@@ -1341,9 +1465,6 @@ prepare_options_buf(Buffer *c, int which)
        if ((which & OPTIONS_EXTENSIONS) != 0 &&
            (certflags_flags & CERTOPT_USER_RC) != 0)
                add_flag_option(c, "permit-user-rc");
-       if ((which & OPTIONS_EXTENSIONS) != 0 &&
-           (certflags_flags & CERTOPT_X_FWD) != 0)
-               add_flag_option(c, "permit-X11-forwarding");
        if ((which & OPTIONS_CRITICAL) != 0 &&
            certflags_src_addr != NULL)
                add_string_option(c, "source-address", certflags_src_addr);
@@ -1593,7 +1714,7 @@ add_cert_option(char *opt)
 {
        char *val;
 
-       if (strcmp(opt, "clear") == 0)
+       if (strcasecmp(opt, "clear") == 0)
                certflags_flags = 0;
        else if (strcasecmp(opt, "no-x11-forwarding") == 0)
                certflags_flags &= ~CERTOPT_X_FWD;
@@ -1745,6 +1866,7 @@ usage(void)
 {
        fprintf(stderr, "usage: %s [options]\n", __progname);
        fprintf(stderr, "Options:\n");
+       fprintf(stderr, "  -A          Generate non-existent host keys for all key types.\n");
        fprintf(stderr, "  -a trials   Number of trials for screening DH-GEX moduli.\n");
        fprintf(stderr, "  -B          Show bubblebabble digest of key file.\n");
        fprintf(stderr, "  -b bits     Number of bits in the key to create.\n");
@@ -1799,9 +1921,9 @@ main(int argc, char **argv)
        struct passwd *pw;
        struct stat st;
        int opt, type, fd;
-       u_int maxbits;
        u_int32_t memory = 0, generator_wanted = 0, trials = 100;
        int do_gen_candidates = 0, do_screen_candidates = 0;
+       int gen_all_hostkeys = 0;
        BIGNUM *start = NULL;
        FILE *f;
        const char *errstr;
@@ -1817,7 +1939,6 @@ main(int argc, char **argv)
        OpenSSL_add_all_algorithms();
        log_init(argv[0], SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_USER, 1);
 
-       init_rng();
        seed_rng();
 
        /* we need this for the home * directory.  */
@@ -1831,9 +1952,12 @@ main(int argc, char **argv)
                exit(1);
        }
 
-       while ((opt = getopt(argc, argv, "degiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
+       while ((opt = getopt(argc, argv, "AegiqpclBHLhvxXyF:b:f:t:D:I:P:m:N:n:"
            "O:C:r:g:R:T:G:M:S:s:a:V:W:z:")) != -1) {
                switch (opt) {
+               case 'A':
+                       gen_all_hostkeys = 1;
+                       break;
                case 'b':
                        bits = (u_int32_t)strtonum(optarg, 256, 32768, &errstr);
                        if (errstr)
@@ -1928,9 +2052,6 @@ main(int argc, char **argv)
                case 'y':
                        print_public = 1;
                        break;
-               case 'd':
-                       key_type_name = "dsa";
-                       break;
                case 's':
                        ca_key_path = optarg;
                        break;
@@ -2109,37 +2230,19 @@ main(int argc, char **argv)
                return (0);
        }
 
+       if (gen_all_hostkeys) {
+               do_gen_all_hostkeys(pw);
+               return (0);
+       }
+
        arc4random_stir();
 
        if (key_type_name == NULL)
                key_type_name = "rsa";
 
        type = key_type_from_name(key_type_name);
-       if (type == KEY_UNSPEC) {
-               fprintf(stderr, "unknown key type %s\n", key_type_name);
-               exit(1);
-       }
-       if (bits == 0) {
-               if (type == KEY_DSA)
-                       bits = DEFAULT_BITS_DSA;
-               else if (type == KEY_ECDSA)
-                       bits = DEFAULT_BITS_ECDSA;
-               else
-                       bits = DEFAULT_BITS;
-       }
-       maxbits = (type == KEY_DSA) ?
-           OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS;
-       if (bits > maxbits) {
-               fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
-               exit(1);
-       }
-       if (type == KEY_DSA && bits != 1024)
-               fatal("DSA keys must be 1024 bits");
-       else if (type != KEY_ECDSA && bits < 768)
-               fatal("Key must at least be 768 bits");
-       else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(bits) == -1)
-               fatal("Invalid ECDSA key length - valid lengths are "
-                   "256, 384 or 521 bits");
+       type_bits_valid(type, &bits);
+
        if (!quiet)
                printf("Generating public/private %s key pair.\n", key_type_name);
        private = key_generate(type, bits);
index 25d7ac6..b085dd4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keyscan.c,v 1.84 2011/01/04 20:44:13 otto Exp $ */
+/* $OpenBSD: ssh-keyscan.c,v 1.85 2011/03/15 10:36:02 okan Exp $ */
 /*
  * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
  *
@@ -535,7 +535,7 @@ conloop(void)
                        seltime.tv_sec--;
                }
        } else
-               seltime.tv_sec = seltime.tv_usec = 0;
+               timerclear(&seltime);
 
        r = xcalloc(read_wait_nfdset, sizeof(fd_mask));
        e = xcalloc(read_wait_nfdset, sizeof(fd_mask));
@@ -620,7 +620,6 @@ main(int argc, char **argv)
        extern char *optarg;
 
        __progname = ssh_get_progname(argv[0]);
-       init_rng();
        seed_rng();
        TAILQ_INIT(&tq);
 
index d051560..1deb7e1 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keysign.c,v 1.35 2010/08/31 12:33:38 djm Exp $ */
+/* $OpenBSD: ssh-keysign.c,v 1.36 2011/02/16 00:31:14 djm Exp $ */
 /*
  * Copyright (c) 2002 Markus Friedl.  All rights reserved.
  *
@@ -150,9 +150,10 @@ main(int argc, char **argv)
 {
        Buffer b;
        Options options;
-       Key *keys[2], *key = NULL;
+#define NUM_KEYTYPES 3
+       Key *keys[NUM_KEYTYPES], *key = NULL;
        struct passwd *pw;
-       int key_fd[2], i, found, version = 2, fd;
+       int key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
        u_char *signature, *data;
        char *host;
        u_int slen, dlen;
@@ -165,8 +166,10 @@ main(int argc, char **argv)
        if (fd > 2)
                close(fd);
 
-       key_fd[0] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
-       key_fd[1] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
+       i = 0;
+       key_fd[i++] = open(_PATH_HOST_DSA_KEY_FILE, O_RDONLY);
+       key_fd[i++] = open(_PATH_HOST_ECDSA_KEY_FILE, O_RDONLY);
+       key_fd[i++] = open(_PATH_HOST_RSA_KEY_FILE, O_RDONLY);
 
        original_real_uid = getuid();   /* XXX readconf.c needs this */
        if ((pw = getpwuid(original_real_uid)) == NULL)
@@ -175,7 +178,6 @@ main(int argc, char **argv)
 
        permanently_set_uid(pw);
 
-       init_rng();
        seed_rng();
        arc4random_stir();
 
@@ -191,7 +193,11 @@ main(int argc, char **argv)
                fatal("ssh-keysign not enabled in %s",
                    _PATH_HOST_CONFIG_FILE);
 
-       if (key_fd[0] == -1 && key_fd[1] == -1)
+       for (i = found = 0; i < NUM_KEYTYPES; i++) {
+               if (key_fd[i] != -1)
+                       found = 1;
+       }
+       if (found == 0)
                fatal("could not open any host key");
 
        OpenSSL_add_all_algorithms();
@@ -200,7 +206,7 @@ main(int argc, char **argv)
        RAND_seed(rnd, sizeof(rnd));
 
        found = 0;
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < NUM_KEYTYPES; i++) {
                keys[i] = NULL;
                if (key_fd[i] == -1)
                        continue;
@@ -230,7 +236,7 @@ main(int argc, char **argv)
        xfree(host);
 
        found = 0;
-       for (i = 0; i < 2; i++) {
+       for (i = 0; i < NUM_KEYTYPES; i++) {
                if (keys[i] != NULL &&
                    key_equal_public(key, keys[i])) {
                        found = 1;
index 8e3f57a..cd33515 100644 (file)
@@ -280,7 +280,6 @@ main(int argc, char **argv)
        TAILQ_INIT(&pkcs11_keylist);
        pkcs11_init(0);
 
-       init_rng();
        seed_rng();
        __progname = ssh_get_progname(argv[0]);
 
index 286c232..1f4c1c8 100644 (file)
@@ -590,4 +590,18 @@ fail:
        return (-1);
 }
 
+#else
+
+int
+pkcs11_init(int interactive)
+{
+       return (0);
+}
+
+void
+pkcs11_terminate(void)
+{
+       return;
+}
+
 #endif /* ENABLE_PKCS11 */
similarity index 58%
copy from crypto/openssh/openbsd-compat/port-linux.h
copy to crypto/openssh/ssh-sandbox.h
index c2f6184..dfecd5a 100644 (file)
@@ -1,7 +1,6 @@
-/* $Id: port-linux.h,v 1.4.10.1 2011/02/04 00:42:21 djm Exp $ */
-
+/* $OpenBSD: ssh-sandbox.h,v 1.1 2011/06/23 09:34:13 djm Exp $ */
 /*
- * Copyright (c) 2006 Damien Miller <djm@openbsd.org>
+ * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#ifndef _PORT_LINUX_H
-#define _PORT_LINUX_H
-
-#ifdef WITH_SELINUX
-int ssh_selinux_enabled(void);
-void ssh_selinux_setup_pty(char *, const char *);
-void ssh_selinux_setup_exec_context(char *);
-void ssh_selinux_change_context(const char *);
-void ssh_selinux_setfscreatecon(const char *);
-#endif
-
-#ifdef LINUX_OOM_ADJUST
-void oom_adjust_restore(void);
-void oom_adjust_setup(void);
-#endif
+struct ssh_sandbox;
 
-#endif /* ! _PORT_LINUX_H */
+struct ssh_sandbox *ssh_sandbox_init(void);
+void ssh_sandbox_child(struct ssh_sandbox *);
+void ssh_sandbox_parent_finish(struct ssh_sandbox *);
+void ssh_sandbox_parent_preauth(struct ssh_sandbox *, pid_t);
index e3a42b5..9c1ca4b 100644 (file)
@@ -33,8 +33,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: ssh.1,v 1.316 2010/11/18 15:01:00 jmc Exp $
-.Dd $Mdocdate: November 18 2010 $
+.\" $OpenBSD: ssh.1,v 1.320 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
 .Dt SSH 1
 .Os
 .Sh NAME
@@ -392,9 +392,11 @@ Valid commands are:
 .Dq check
 (check that the master process is running),
 .Dq forward
-(request forwardings without command execution) and
+(request forwardings without command execution),
 .Dq exit
-(request the master to exit).
+(request the master to exit), and
+.Dq stop
+(request the master to stop accepting further multiplexing requests).
 .It Fl o Ar option
 Can be used to give options in the format used in the configuration file.
 This is useful for specifying options for which there is no separate
@@ -454,6 +456,7 @@ For full details of the options listed below, and their possible values, see
 .It PubkeyAuthentication
 .It RekeyLimit
 .It RemoteForward
+.It RequestTTY
 .It RhostsRSAAuthentication
 .It RSAAuthentication
 .It SendEnv
@@ -664,7 +667,9 @@ Both protocols support similar authentication methods,
 but protocol 2 is the default since
 it provides additional mechanisms for confidentiality
 (the traffic is encrypted using AES, 3DES, Blowfish, CAST128, or Arcfour)
-and integrity (hmac-md5, hmac-sha1, umac-64, hmac-ripemd160).
+and integrity (hmac-md5, hmac-sha1,
+hmac-sha2-256, hmac-sha2-512,
+umac-64, hmac-ripemd160).
 Protocol 1 lacks a strong mechanism for ensuring the
 integrity of the connection.
 .Pp
index d32ef78..c717dcf 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.356 2011/01/06 22:23:53 djm Exp $ */
+/* $OpenBSD: ssh.c,v 1.364 2011/08/02 23:15:03 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 
 extern char *__progname;
 
+/* Saves a copy of argv for setproctitle emulation */
+#ifndef HAVE_SETPROCTITLE
+static char **saved_av;
+#endif
+
 /* Flag indicating whether debug mode is on.  May be set on the command line. */
 int debug_flag = 0;
 
-/* Flag indicating whether a tty should be allocated */
+/* Flag indicating whether a tty should be requested */
 int tty_flag = 0;
-int no_tty_flag = 0;
-int force_tty_flag = 0;
 
 /* don't exec a shell */
 int no_shell_flag = 0;
@@ -135,7 +138,7 @@ int stdin_null_flag = 0;
 int need_controlpersist_detach = 0;
 
 /* Copies of flags for ControlPersist foreground slave */
-int ostdin_null_flag, ono_shell_flag, ono_tty_flag, otty_flag;
+int ostdin_null_flag, ono_shell_flag, otty_flag, orequest_tty;
 
 /*
  * Flag indicating that ssh should fork after authentication.  This is useful
@@ -214,6 +217,20 @@ static void main_sigchld_handler(int);
 void muxclient(const char *);
 void muxserver_listen(void);
 
+/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */
+static void
+tilde_expand_paths(char **paths, u_int num_paths)
+{
+       u_int i;
+       char *cp;
+
+       for (i = 0; i < num_paths; i++) {
+               cp = tilde_expand_filename(paths[i], original_real_uid);
+               xfree(paths[i]);
+               paths[i] = cp;
+       }
+}
+
 /*
  * Main program for the ssh client.
  */
@@ -222,11 +239,13 @@ main(int ac, char **av)
 {
        int i, r, opt, exit_status, use_syslog;
        char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg;
+       char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
        struct stat st;
        struct passwd *pw;
        int dummy, timeout_ms;
        extern int optind, optreset;
        extern char *optarg;
+
        struct servent *sp;
        Forward fwd;
 
@@ -234,7 +253,17 @@ main(int ac, char **av)
        sanitise_stdfd();
 
        __progname = ssh_get_progname(av[0]);
-       init_rng();
+
+#ifndef HAVE_SETPROCTITLE
+       /* Prepare for later setproctitle emulation */
+       /* Save argv so it isn't clobbered by setproctitle() emulation */
+       saved_av = xcalloc(ac + 1, sizeof(*saved_av));
+       for (i = 0; i < ac; i++)
+               saved_av[i] = xstrdup(av[i]);
+       saved_av[i] = NULL;
+       compat_init_setproctitle(ac, av);
+       av = saved_av;
+#endif
 
        /*
         * Discard other fds that are hanging around. These can cause problem
@@ -346,6 +375,8 @@ main(int ac, char **av)
                                muxclient_command = SSHMUX_COMMAND_FORWARD;
                        else if (strcmp(optarg, "exit") == 0)
                                muxclient_command = SSHMUX_COMMAND_TERMINATE;
+                       else if (strcmp(optarg, "stop") == 0)
+                               muxclient_command = SSHMUX_COMMAND_STOP;
                        else
                                fatal("Invalid multiplex command.");
                        break;
@@ -387,9 +418,10 @@ main(int ac, char **av)
 #endif
                        break;
                case 't':
-                       if (tty_flag)
-                               force_tty_flag = 1;
-                       tty_flag = 1;
+                       if (options.request_tty == REQUEST_TTY_YES)
+                               options.request_tty = REQUEST_TTY_FORCE;
+                       else
+                               options.request_tty = REQUEST_TTY_YES;
                        break;
                case 'v':
                        if (debug_flag == 0) {
@@ -432,7 +464,7 @@ main(int ac, char **av)
                                    optarg);
                                exit(255);
                        }
-                       no_tty_flag = 1;
+                       options.request_tty = REQUEST_TTY_NO;
                        no_shell_flag = 1;
                        options.clear_forwardings = 1;
                        options.exit_on_forward_failure = 1;
@@ -541,10 +573,10 @@ main(int ac, char **av)
                        break;
                case 'N':
                        no_shell_flag = 1;
-                       no_tty_flag = 1;
+                       options.request_tty = REQUEST_TTY_NO;
                        break;
                case 'T':
-                       no_tty_flag = 1;
+                       options.request_tty = REQUEST_TTY_NO;
                        break;
                case 'o':
                        dummy = 1;
@@ -604,6 +636,10 @@ main(int ac, char **av)
        /* Initialize the command to execute on remote host. */
        buffer_init(&command);
 
+       if (options.request_tty == REQUEST_TTY_YES ||
+           options.request_tty == REQUEST_TTY_FORCE)
+               tty_flag = 1;
+
        /*
         * Save the command to execute on the remote host in a buffer. There
         * is no limit on the length of the command, except by the maximum
@@ -611,7 +647,7 @@ main(int ac, char **av)
         */
        if (!ac) {
                /* No command specified - execute shell on a tty. */
-               tty_flag = 1;
+               tty_flag = options.request_tty != REQUEST_TTY_NO;
                if (subsystem_flag) {
                        fprintf(stderr,
                            "You must specify a subsystem to invoke.\n");
@@ -634,13 +670,14 @@ main(int ac, char **av)
 
        /* Allocate a tty by default if no command specified. */
        if (buffer_len(&command) == 0)
-               tty_flag = 1;
+               tty_flag = options.request_tty != REQUEST_TTY_NO;
 
        /* Force no tty */
-       if (no_tty_flag || muxclient_command != 0)
+       if (options.request_tty == REQUEST_TTY_NO || muxclient_command != 0)
                tty_flag = 0;
        /* Do not allocate a tty if stdin is not a tty. */
-       if ((!isatty(fileno(stdin)) || stdin_null_flag) && !force_tty_flag) {
+       if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
+           options.request_tty != REQUEST_TTY_FORCE) {
                if (tty_flag)
                        logit("Pseudo-terminal will not be allocated because "
                            "stdin is not a terminal.");
@@ -669,7 +706,7 @@ main(int ac, char **av)
                if (r > 0 && (size_t)r < sizeof(buf))
                        (void)read_config_file(buf, host, &options, 1);
 
-               /* Read systemwide configuration file after use config. */
+               /* Read systemwide configuration file after user config. */
                (void)read_config_file(_PATH_HOST_CONFIG_FILE, host,
                    &options, 0);
        }
@@ -700,17 +737,19 @@ main(int ac, char **av)
                    "h", host, (char *)NULL);
        }
 
-       if (options.local_command != NULL) {
-               char thishost[NI_MAXHOST];
+       if (gethostname(thishost, sizeof(thishost)) == -1)
+               fatal("gethostname: %s", strerror(errno));
+       strlcpy(shorthost, thishost, sizeof(shorthost));
+       shorthost[strcspn(thishost, ".")] = '\0';
+       snprintf(portstr, sizeof(portstr), "%d", options.port);
 
-               if (gethostname(thishost, sizeof(thishost)) == -1)
-                       fatal("gethostname: %s", strerror(errno));
-               snprintf(buf, sizeof(buf), "%d", options.port);
+       if (options.local_command != NULL) {
                debug3("expanding LocalCommand: %s", options.local_command);
                cp = options.local_command;
                options.local_command = percent_expand(cp, "d", pw->pw_dir,
                    "h", host, "l", thishost, "n", host_arg, "r", options.user,
-                   "p", buf, "u", pw->pw_name, (char *)NULL);
+                   "p", portstr, "u", pw->pw_name, "L", shorthost,
+                   (char *)NULL);
                debug3("expanded LocalCommand: %s", options.local_command);
                xfree(cp);
        }
@@ -734,16 +773,13 @@ main(int ac, char **av)
        }
 
        if (options.control_path != NULL) {
-               char thishost[NI_MAXHOST];
-
-               if (gethostname(thishost, sizeof(thishost)) == -1)
-                       fatal("gethostname: %s", strerror(errno));
-               snprintf(buf, sizeof(buf), "%d", options.port);
                cp = tilde_expand_filename(options.control_path,
                    original_real_uid);
                xfree(options.control_path);
-               options.control_path = percent_expand(cp, "p", buf, "h", host,
-                   "r", options.user, "l", thishost, (char *)NULL);
+               options.control_path = percent_expand(cp, "h", host,
+                   "l", thishost, "n", host_arg, "r", options.user,
+                   "p", portstr, "u", pw->pw_name, "L", shorthost,
+                   (char *)NULL);
                xfree(cp);
        }
        if (muxclient_command != 0 && options.control_path == NULL)
@@ -864,15 +900,9 @@ main(int ac, char **av)
        load_public_identity_files();
 
        /* Expand ~ in known host file names. */
-       /* XXX mem-leaks: */
-       options.system_hostfile =
-           tilde_expand_filename(options.system_hostfile, original_real_uid);
-       options.user_hostfile =
-           tilde_expand_filename(options.user_hostfile, original_real_uid);
-       options.system_hostfile2 =
-           tilde_expand_filename(options.system_hostfile2, original_real_uid);
-       options.user_hostfile2 =
-           tilde_expand_filename(options.user_hostfile2, original_real_uid);
+       tilde_expand_paths(options.system_hostfiles,
+           options.num_system_hostfiles);
+       tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
 
        signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
        signal(SIGCHLD, main_sigchld_handler);
@@ -945,8 +975,7 @@ control_persist_detach(void)
                /* Parent: set up mux slave to connect to backgrounded master */
                debug2("%s: background process is %ld", __func__, (long)pid);
                stdin_null_flag = ostdin_null_flag;
-               no_shell_flag = ono_shell_flag;
-               no_tty_flag = ono_tty_flag;
+               options.request_tty = orequest_tty;
                tty_flag = otty_flag;
                close(muxserver_sock);
                muxserver_sock = -1;
@@ -965,6 +994,7 @@ control_persist_detach(void)
                if (devnull > STDERR_FILENO)
                        close(devnull);
        }
+       setproctitle("%s [mux]", options.control_path);
 }
 
 /* Do fork() after authentication. Used by "ssh -f" */
@@ -1209,8 +1239,8 @@ ssh_session(void)
                /* Request forwarding with authentication spoofing. */
                debug("Requesting X11 forwarding with authentication "
                    "spoofing.");
-               x11_request_forwarding_with_spoofing(0, display, proto, data);
-
+               x11_request_forwarding_with_spoofing(0, display, proto,
+                   data, 0);
                /* Read response from the server. */
                type = packet_read();
                if (type == SSH_SMSG_SUCCESS) {
@@ -1308,9 +1338,11 @@ ssh_session2_setup(int id, int success, void *arg)
                /* Request forwarding with authentication spoofing. */
                debug("Requesting X11 forwarding with authentication "
                    "spoofing.");
-               x11_request_forwarding_with_spoofing(id, display, proto, data);
+               x11_request_forwarding_with_spoofing(id, display, proto,
+                   data, 1);
+               client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN);
+               /* XXX exit_on_forward_failure */
                interactive = 1;
-               /* XXX wait for reply */
        }
 
        check_agent_present();
@@ -1393,11 +1425,10 @@ ssh_session2(void)
        if (options.control_persist && muxserver_sock != -1) {
                ostdin_null_flag = stdin_null_flag;
                ono_shell_flag = no_shell_flag;
-               ono_tty_flag = no_tty_flag;
+               orequest_tty = options.request_tty;
                otty_flag = tty_flag;
                stdin_null_flag = 1;
                no_shell_flag = 1;
-               no_tty_flag = 1;
                tty_flag = 0;
                if (!fork_after_authentication_flag)
                        need_controlpersist_detach = 1;
index 50bcae8..a782d6f 100644 (file)
@@ -33,8 +33,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: ssh_config.5,v 1.146 2010/12/08 04:02:47 djm Exp $
-.Dd $Mdocdate: December 8 2010 $
+.\" $OpenBSD: ssh_config.5,v 1.153 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
 .Dt SSH_CONFIG 5
 .Os
 .Sh NAME
@@ -112,6 +112,15 @@ The host is the
 argument given on the command line (i.e. the name is not converted to
 a canonicalized host name before matching).
 .Pp
+A pattern entry may be negated by prefixing it with an exclamation mark
+.Pq Sq !\& .
+If a negated entry is matched, then the
+.Cm Host
+entry is ignored, regardless of whether any other patterns on the line
+match.
+Negated matches are therefore useful to provide exceptions for wildcard
+matches.
+.Pp
 See
 .Sx PATTERNS
 for more information on patterns.
@@ -305,14 +314,22 @@ section above or the string
 .Dq none
 to disable connection sharing.
 In the path,
+.Ql %L
+will be substituted by the first component of the local host name,
 .Ql %l
-will be substituted by the local host name,
+will be substituted by the local host name (including any domain name),
 .Ql %h
 will be substituted by the target host name,
+.Ql %n
+will be substituted by the original target host name
+specified on the command line,
 .Ql %p
-the port, and
+the port,
 .Ql %r
-by the remote login username.
+by the remote login username, and
+.Ql %u
+by the username of the user running
+.Xr ssh 1 .
 It is recommended that any
 .Cm ControlPath
 used for opportunistic connection sharing include
@@ -500,9 +517,11 @@ or
 The default is
 .Dq no .
 .It Cm GlobalKnownHostsFile
-Specifies a file to use for the global
-host key database instead of
-.Pa /etc/ssh/ssh_known_hosts .
+Specifies one or more files to use for the global
+host key database, separated by whitespace.
+The default is
+.Pa /etc/ssh/ssh_known_hosts ,
+.Pa /etc/ssh/ssh_known_hosts2 .
 .It Cm GSSAPIAuthentication
 Specifies whether user authentication based on GSSAPI is allowed.
 The default is
@@ -569,7 +588,7 @@ Specifies the real host name to log into.
 This can be used to specify nicknames or abbreviations for hosts.
 If the hostname contains the character sequence
 .Ql %h ,
-then this will be replaced with the host name specified on the commandline
+then this will be replaced with the host name specified on the command line
 (this is useful for manipulating unqualified names).
 The default is the name given on the command line.
 Numeric IP addresses are also permitted (both on the command line and in
@@ -629,6 +648,10 @@ escape characters:
 It is possible to have
 multiple identity files specified in configuration files; all these
 identities will be tried in sequence.
+Multiple
+.Cm IdentityFile
+directives will add to the list of identities tried (this behaviour
+differs from that of other configuration directives).
 .It Cm IPQoS
 Specifies the IPv4 type-of-service or DSCP class for connections.
 Accepted values are
@@ -770,7 +793,9 @@ Multiple algorithms must be comma-separated.
 The default is:
 .Bd -literal -offset indent
 hmac-md5,hmac-sha1,umac-64@openssh.com,
-hmac-ripemd160,hmac-sha1-96,hmac-md5-96
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha2-256-96,hmac-sha2-512,
+hmac-sha2-512-96
 .Ed
 .It Cm NoHostAuthenticationForLocalhost
 This option can be used if the home directory is shared across machines.
@@ -943,6 +968,23 @@ will only succeed if the server's
 .Cm GatewayPorts
 option is enabled (see
 .Xr sshd_config 5 ) .
+.It Cm RequestTTY
+Specifies whether to request a pseudo-tty for the session.
+The argument may be one of:
+.Dq no
+(never request a TTY),
+.Dq yes
+(always request a TTY when standard input is a TTY),
+.Dq force
+(always request a TTY) or
+.Dq auto
+(request a TTY when opening a login session).
+This option mirrors the
+.Fl t
+and
+.Fl T
+flags for
+.Xr ssh 1 .
 .It Cm RhostsRSAAuthentication
 Specifies whether to try rhosts based authentication with RSA host
 authentication.
@@ -1137,9 +1179,11 @@ This can be useful when a different user name is used on different machines.
 This saves the trouble of
 having to remember to give the user name on the command line.
 .It Cm UserKnownHostsFile
-Specifies a file to use for the user
-host key database instead of
-.Pa ~/.ssh/known_hosts .
+Specifies one or more files to use for the user
+host key database, separated by whitespace.
+The default is
+.Pa ~/.ssh/known_hosts ,
+.Pa ~/.ssh/known_hosts2 .
 .It Cm VerifyHostKeyDNS
 Specifies whether to verify the remote key using DNS and SSHFP resource
 records.
index 74643a8..0ee7266 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect.c,v 1.232 2011/01/16 11:50:36 djm Exp $ */
+/* $OpenBSD: sshconnect.c,v 1.234 2011/05/24 07:15:47 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -683,28 +683,30 @@ get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
 
 /*
  * check whether the supplied host key is valid, return -1 if the key
- * is not valid. the user_hostfile will not be updated if 'readonly' is true.
+ * is not valid. user_hostfile[0] will not be updated if 'readonly' is true.
  */
 #define RDRW   0
 #define RDONLY 1
 #define ROQUIET        2
 static int
 check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
-    Key *host_key, int readonly, char *user_hostfile,
-    char *system_hostfile)
+    Key *host_key, int readonly,
+    char **user_hostfiles, u_int num_user_hostfiles,
+    char **system_hostfiles, u_int num_system_hostfiles)
 {
+       HostStatus host_status;
+       HostStatus ip_status;
        Key *raw_key = NULL;
-       const char *type;
        char *ip = NULL, *host = NULL;
        char hostline[1000], *hostp, *fp, *ra;
-       HostStatus host_status;
-       HostStatus ip_status;
-       int r, want_cert = key_is_cert(host_key), host_ip_differ = 0;
-       int local = sockaddr_is_local(hostaddr);
        char msg[1024];
+       const char *type;
+       const struct hostkey_entry *host_found, *ip_found;
        int len, cancelled_forwarding = 0;
+       int local = sockaddr_is_local(hostaddr);
+       int r, want_cert = key_is_cert(host_key), host_ip_differ = 0;
        struct hostkeys *host_hostkeys, *ip_hostkeys;
-       const struct hostkey_entry *host_found, *ip_found;
+       u_int i;
 
        /*
         * Force accepting of the host key for loopback/localhost. The
@@ -736,14 +738,18 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
                options.check_host_ip = 0;
 
        host_hostkeys = init_hostkeys();
-       load_hostkeys(host_hostkeys, host, user_hostfile);
-       load_hostkeys(host_hostkeys, host, system_hostfile);
+       for (i = 0; i < num_user_hostfiles; i++)
+               load_hostkeys(host_hostkeys, host, user_hostfiles[i]);
+       for (i = 0; i < num_system_hostfiles; i++)
+               load_hostkeys(host_hostkeys, host, system_hostfiles[i]);
 
        ip_hostkeys = NULL;
        if (!want_cert && options.check_host_ip) {
                ip_hostkeys = init_hostkeys();
-               load_hostkeys(ip_hostkeys, ip, user_hostfile);
-               load_hostkeys(ip_hostkeys, ip, system_hostfile);
+               for (i = 0; i < num_user_hostfiles; i++)
+                       load_hostkeys(ip_hostkeys, ip, user_hostfiles[i]);
+               for (i = 0; i < num_system_hostfiles; i++)
+                       load_hostkeys(ip_hostkeys, ip, system_hostfiles[i]);
        }
 
  retry:
@@ -788,11 +794,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
                                logit("%s host key for IP address "
                                    "'%.128s' not in list of known hosts.",
                                    type, ip);
-                       else if (!add_host_to_hostfile(user_hostfile, ip,
+                       else if (!add_host_to_hostfile(user_hostfiles[0], ip,
                            host_key, options.hash_known_hosts))
                                logit("Failed to add the %s host key for IP "
                                    "address '%.128s' to the list of known "
-                                   "hosts (%.30s).", type, ip, user_hostfile);
+                                   "hosts (%.30s).", type, ip,
+                                   user_hostfiles[0]);
                        else
                                logit("Warning: Permanently added the %s host "
                                    "key for IP address '%.128s' to the list "
@@ -811,7 +818,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
                    port != SSH_DEFAULT_PORT) {
                        debug("checking without port identifier");
                        if (check_host_key(hostname, hostaddr, 0, host_key,
-                           ROQUIET, user_hostfile, system_hostfile) == 0) {
+                           ROQUIET, user_hostfiles, num_user_hostfiles,
+                           system_hostfiles, num_system_hostfiles) == 0) {
                                debug("found matching key w/out port");
                                break;
                        }
@@ -876,25 +884,25 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
                        hostp = hostline;
                        if (options.hash_known_hosts) {
                                /* Add hash of host and IP separately */
-                               r = add_host_to_hostfile(user_hostfile, host,
-                                   host_key, options.hash_known_hosts) &&
-                                   add_host_to_hostfile(user_hostfile, ip,
+                               r = add_host_to_hostfile(user_hostfiles[0],
+                                   host, host_key, options.hash_known_hosts) &&
+                                   add_host_to_hostfile(user_hostfiles[0], ip,
                                    host_key, options.hash_known_hosts);
                        } else {
                                /* Add unhashed "host,ip" */
-                               r = add_host_to_hostfile(user_hostfile,
+                               r = add_host_to_hostfile(user_hostfiles[0],
                                    hostline, host_key,
                                    options.hash_known_hosts);
                        }
                } else {
-                       r = add_host_to_hostfile(user_hostfile, host, host_key,
-                           options.hash_known_hosts);
+                       r = add_host_to_hostfile(user_hostfiles[0], host,
+                           host_key, options.hash_known_hosts);
                        hostp = host;
                }
 
                if (!r)
                        logit("Failed to add the host to the list of known "
-                           "hosts (%.500s).", user_hostfile);
+                           "hosts (%.500s).", user_hostfiles[0]);
                else
                        logit("Warning: Permanently added '%.200s' (%s) to the "
                            "list of known hosts.", hostp, type);
@@ -955,7 +963,7 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
                /* The host key has changed. */
                warn_changed_key(host_key);
                error("Add correct host key in %.100s to get rid of this message.",
-                   user_hostfile);
+                   user_hostfiles[0]);
                error("Offending %s key in %s:%lu", key_type(host_found->key),
                    host_found->file, host_found->line);
 
@@ -1100,7 +1108,6 @@ fail:
 int
 verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
 {
-       struct stat st;
        int flags = 0;
        char *fp;
 
@@ -1111,7 +1118,6 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
        /* XXX certs are not yet supported for DNS */
        if (!key_is_cert(host_key) && options.verify_host_key_dns &&
            verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
-
                if (flags & DNS_VERIFY_FOUND) {
 
                        if (options.verify_host_key_dns == 1 &&
@@ -1129,16 +1135,9 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
                }
        }
 
-       /* return ok if the key can be found in an old keyfile */
-       if (stat(options.system_hostfile2, &st) == 0 ||
-           stat(options.user_hostfile2, &st) == 0) {
-               if (check_host_key(host, hostaddr, options.port, host_key,
-                   RDONLY, options.user_hostfile2,
-                   options.system_hostfile2) == 0)
-                       return 0;
-       }
-       return check_host_key(host, hostaddr, options.port, host_key,
-           RDRW, options.user_hostfile, options.system_hostfile);
+       return check_host_key(host, hostaddr, options.port, host_key, RDRW,
+           options.user_hostfiles, options.num_user_hostfiles,
+           options.system_hostfiles, options.num_system_hostfiles);
 }
 
 /*
index 3cb9b10..c24b202 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshconnect2.c,v 1.186 2010/11/29 23:45:51 djm Exp $ */
+/* $OpenBSD: sshconnect2.c,v 1.188 2011/05/24 07:15:47 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2008 Damien Miller.  All rights reserved.
@@ -109,14 +109,15 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
        size_t maxlen;
        struct hostkeys *hostkeys;
        int ktype;
+       u_int i;
 
        /* Find all hostkeys for this hostname */
        get_hostfile_hostname_ipaddr(host, hostaddr, port, &hostname, NULL);
        hostkeys = init_hostkeys();
-       load_hostkeys(hostkeys, hostname, options.user_hostfile2);
-       load_hostkeys(hostkeys, hostname, options.system_hostfile2);
-       load_hostkeys(hostkeys, hostname, options.user_hostfile);
-       load_hostkeys(hostkeys, hostname, options.system_hostfile);
+       for (i = 0; i < options.num_user_hostfiles; i++)
+               load_hostkeys(hostkeys, hostname, options.user_hostfiles[i]);
+       for (i = 0; i < options.num_system_hostfiles; i++)
+               load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]);
 
        oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG);
        maxlen = strlen(avail) + 1;
@@ -1888,9 +1889,12 @@ authmethod_get(char *authlist)
                    authmethod_is_enabled(current)) {
                        debug3("authmethod_is_enabled %s", name);
                        debug("Next authentication method: %s", name);
+                       xfree(name);
                        return current;
                }
        }
+       if (name != NULL)
+               xfree(name);
 }
 
 static char *
index 5503b13..a91be0f 100644 (file)
@@ -33,8 +33,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: sshd.8,v 1.260 2010/10/28 18:33:28 jmc Exp $
-.Dd $Mdocdate: October 28 2010 $
+.\" $OpenBSD: sshd.8,v 1.263 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
 .Dt SSHD 8
 .Os
 .Sh NAME
@@ -314,7 +314,8 @@ The client selects the encryption algorithm
 to use from those offered by the server.
 Additionally, session integrity is provided
 through a cryptographic message authentication code
-(hmac-md5, hmac-sha1, umac-64 or hmac-ripemd160).
+(hmac-md5, hmac-sha1, umac-64, hmac-ripemd160,
+hmac-sha2-256 or hmac-sha2-512).
 .Pp
 Finally, the server and the client enter an authentication dialog.
 The client tries to authenticate itself using
@@ -462,10 +463,12 @@ is run, and if that
 does not exist either, xauth is used to add the cookie.
 .Sh AUTHORIZED_KEYS FILE FORMAT
 .Cm AuthorizedKeysFile
-specifies the file containing public keys for
+specifies the files containing public keys for
 public key authentication;
 if none is specified, the default is
-.Pa ~/.ssh/authorized_keys .
+.Pa ~/.ssh/authorized_keys
+and
+.Pa ~/.ssh/authorized_keys2 .
 Each line of the file contains one
 key (empty lines and lines starting with a
 .Ql #
index cb45cec..cc10395 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.381 2011/01/11 06:13:10 djm Exp $ */
+/* $OpenBSD: sshd.c,v 1.385 2011/06/23 09:34:13 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 #endif
 #include "monitor_wrap.h"
 #include "roaming.h"
+#include "ssh-sandbox.h"
 #include "version.h"
 
 #ifdef LIBWRAP
@@ -624,42 +625,62 @@ privsep_preauth(Authctxt *authctxt)
 {
        int status;
        pid_t pid;
+       struct ssh_sandbox *box = NULL;
 
        /* Set up unprivileged child process to deal with network data */
        pmonitor = monitor_init();
        /* Store a pointer to the kex for later rekeying */
        pmonitor->m_pkex = &xxx_kex;
 
+       if (use_privsep == PRIVSEP_SANDBOX)
+               box = ssh_sandbox_init();
        pid = fork();
        if (pid == -1) {
                fatal("fork of unprivileged child failed");
        } else if (pid != 0) {
                debug2("Network child is on pid %ld", (long)pid);
 
-               close(pmonitor->m_recvfd);
+               if (box != NULL)
+                       ssh_sandbox_parent_preauth(box, pid);
                pmonitor->m_pid = pid;
                monitor_child_preauth(authctxt, pmonitor);
-               close(pmonitor->m_sendfd);
 
                /* Sync memory */
                monitor_sync(pmonitor);
 
                /* Wait for the child's exit status */
-               while (waitpid(pid, &status, 0) < 0)
+               while (waitpid(pid, &status, 0) < 0) {
                        if (errno != EINTR)
-                               break;
-               return (1);
+                               fatal("%s: waitpid: %s", __func__,
+                                   strerror(errno));
+               }
+               if (WIFEXITED(status)) {
+                       if (WEXITSTATUS(status) != 0)
+                               fatal("%s: preauth child exited with status %d",
+                                   __func__, WEXITSTATUS(status));
+               } else if (WIFSIGNALED(status))
+                       fatal("%s: preauth child terminated by signal %d",
+                           __func__, WTERMSIG(status));
+               if (box != NULL)
+                       ssh_sandbox_parent_finish(box);
+               return 1;
        } else {
                /* child */
-
                close(pmonitor->m_sendfd);
+               close(pmonitor->m_log_recvfd);
+
+               /* Arrange for logging to be sent to the monitor */
+               set_log_handler(mm_log_handler, pmonitor);
 
                /* Demote the child */
                if (getuid() == 0 || geteuid() == 0)
                        privsep_preauth_child();
                setproctitle("%s", "[net]");
+               if (box != NULL)
+                       ssh_sandbox_child(box);
+
+               return 0;
        }
-       return (0);
 }
 
 static void
@@ -685,7 +706,6 @@ privsep_postauth(Authctxt *authctxt)
                fatal("fork of unprivileged child failed");
        else if (pmonitor->m_pid != 0) {
                verbose("User child is on pid %ld", (long)pmonitor->m_pid);
-               close(pmonitor->m_recvfd);
                buffer_clear(&loginmsg);
                monitor_child_postauth(pmonitor);
 
@@ -693,7 +713,10 @@ privsep_postauth(Authctxt *authctxt)
                exit(0);
        }
 
+       /* child */
+
        close(pmonitor->m_sendfd);
+       pmonitor->m_sendfd = -1;
 
        /* Demote the private keys to public keys. */
        demote_sensitive_data();
@@ -1115,7 +1138,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
                            (int) received_sigterm);
                        close_listen_socks();
                        unlink(options.pid_file);
-                       exit(255);
+                       exit(received_sigterm == SIGTERM ? 0 : 255);
                }
                if (key_used && key_do_regen) {
                        generate_ephemeral_server_key();
@@ -1306,7 +1329,6 @@ main(int ac, char **av)
        (void)set_auth_parameters(ac, av);
 #endif
        __progname = ssh_get_progname(av[0]);
-       init_rng();
 
        /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
        saved_argc = ac;
index 4534841..473e866 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: sshd_config,v 1.82 2010/09/06 17:10:19 naddy Exp $
+#      $OpenBSD: sshd_config,v 1.84 2011/05/23 03:30:07 djm Exp $
 
 # This is the sshd server system-wide configuration file.  See
 # sshd_config(5) for more information.
@@ -7,7 +7,7 @@
 
 # The strategy used for options in the default sshd_config shipped with
 # OpenSSH is to specify options with their default value where
-# possible, but leave them commented.  Uncommented options change a
+# possible, but leave them commented.  Uncommented options override the
 # default value.
 
 #Port 22
 
 #RSAAuthentication yes
 #PubkeyAuthentication yes
-#AuthorizedKeysFile    .ssh/authorized_keys
+
+# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
+# but this is overridden so installations will only check .ssh/authorized_keys
+AuthorizedKeysFile     .ssh/authorized_keys
 
 # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
 #RhostsRSAAuthentication no
index c3d6df3..a6c3787 100644 (file)
@@ -33,8 +33,8 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: sshd_config.5,v 1.131 2010/12/08 04:02:47 djm Exp $
-.Dd $Mdocdate: December 8 2010 $
+.\" $OpenBSD: sshd_config.5,v 1.135 2011/08/02 01:22:11 djm Exp $
+.Dd $Mdocdate: August 2 2011 $
 .Dt SSHD_CONFIG 5
 .Os
 .Sh NAME
@@ -168,8 +168,9 @@ After expansion,
 .Cm AuthorizedKeysFile
 is taken to be an absolute path or one relative to the user's home
 directory.
+Multiple files may be listed, separated by whitespace.
 The default is
-.Dq .ssh/authorized_keys .
+.Dq .ssh/authorized_keys .ssh/authorized_keys2 .
 .It Cm AuthorizedPrincipalsFile
 Specifies a file that lists principal names that are accepted for
 certificate authentication.
@@ -654,7 +655,9 @@ Multiple algorithms must be comma-separated.
 The default is:
 .Bd -literal -offset indent
 hmac-md5,hmac-sha1,umac-64@openssh.com,
-hmac-ripemd160,hmac-sha1-96,hmac-md5-96
+hmac-ripemd160,hmac-sha1-96,hmac-md5-96,
+hmac-sha2-256,hmac-sha256-96,hmac-sha2-512,
+hmac-sha2-512-96
 .Ed
 .It Cm Match
 Introduces a conditional block.
@@ -1070,6 +1073,12 @@ The goal of privilege separation is to prevent privilege
 escalation by containing any corruption within the unprivileged processes.
 The default is
 .Dq yes .
+If
+.Cm UsePrivilegeSeparation
+is set to
+.Dq sandbox
+then the pre-authentication unprivileged process is subject to additional
+restrictions.
 .It Cm X11DisplayOffset
 Specifies the first display number available for
 .Xr sshd 8 Ns 's