]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream commit
authordjm@openbsd.org <djm@openbsd.org>
Mon, 7 Mar 2016 19:02:43 +0000 (19:02 +0000)
committerDamien Miller <djm@mindrot.org>
Mon, 7 Mar 2016 19:20:35 +0000 (06:20 +1100)
refactor canohost.c: move functions that cache results closer
 to the places that use them (authn and session code). After this, no state is
 cached in canohost.c

feedback and ok markus@

Upstream-ID: 5f2e4df88d4803fc8ec59ec53629105e23ce625e

21 files changed:
auth-options.c
auth-rh-rsa.c
auth-rhosts.c
auth.c
auth.h
auth2-hostbased.c
canohost.c
canohost.h
channels.c
monitor.c
monitor_wrap.c
monitor_wrap.h
opacket.h
packet.c
packet.h
servconf.c
serverloop.c
session.c
session.h
ssh.c
sshd.c

index edbaf80bbf0921b6597eb28c131e8fbef18a72ab..b399b91e3906384170443246436cb068641047e4 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-options.c,v 1.70 2015/12/10 17:08:40 mmcc Exp $ */
+/* $OpenBSD: auth-options.c,v 1.71 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -29,6 +29,7 @@
 #include "ssherr.h"
 #include "log.h"
 #include "canohost.h"
+#include "packet.h"
 #include "sshbuf.h"
 #include "misc.h"
 #include "channels.h"
@@ -120,6 +121,7 @@ match_flag(const char *opt, int allow_negate, char **optsp, const char *msg)
 int
 auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
 {
+       struct ssh *ssh = active_state;         /* XXX */
        const char *cp;
        int i, r;
 
@@ -273,9 +275,9 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
                }
                cp = "from=\"";
                if (strncasecmp(opts, cp, strlen(cp)) == 0) {
-                       const char *remote_ip = get_remote_ipaddr();
-                       const char *remote_host = get_canonical_hostname(
-                           options.use_dns);
+                       const char *remote_ip = ssh_remote_ipaddr(ssh);
+                       const char *remote_host = auth_get_canonical_hostname(
+                           ssh, options.use_dns);
                        char *patterns = xmalloc(strlen(opts) + 1);
 
                        opts += strlen(cp);
@@ -457,6 +459,7 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
     char **cert_forced_command,
     int *cert_source_address_done)
 {
+       struct ssh *ssh = active_state;         /* XXX */
        char *command, *allowed;
        const char *remote_ip;
        char *name = NULL;
@@ -530,7 +533,7 @@ parse_option_list(struct sshbuf *oblob, struct passwd *pw,
                                        free(allowed);
                                        goto out;
                                }
-                               remote_ip = get_remote_ipaddr();
+                               remote_ip = ssh_remote_ipaddr(ssh);
                                result = addr_match_cidr_list(remote_ip,
                                    allowed);
                                free(allowed);
index 2e20396ea7795634627c10bb8e8b54943bdc9b47..057335ba4fe906cc925d53d4c5c51e92bb2f13cb 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
+/* $OpenBSD: auth-rh-rsa.c,v 1.45 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,8 +42,8 @@
 extern ServerOptions options;
 
 int
-auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
-    Key *client_host_key)
+auth_rhosts_rsa_key_allowed(struct passwd *pw, const char *cuser,
+    const char *chost, Key *client_host_key)
 {
        HostStatus host_status;
 
@@ -68,7 +68,8 @@ auth_rhosts_rsa_key_allowed(struct passwd *pw, char *cuser, char *chost,
 int
 auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key)
 {
-       char *chost;
+       struct ssh *ssh = active_state; /* XXX */
+       const char *chost;
        struct passwd *pw = authctxt->pw;
 
        debug("Trying rhosts with RSA host authentication for client user %.100s",
@@ -78,7 +79,7 @@ auth_rhosts_rsa(Authctxt *authctxt, char *cuser, Key *client_host_key)
            client_host_key->rsa == NULL)
                return 0;
 
-       chost = (char *)get_canonical_hostname(options.use_dns);
+       chost = auth_get_canonical_hostname(ssh, options.use_dns);
        debug("Rhosts RSA authentication: canonical host %.900s", chost);
 
        if (!PRIVSEP(auth_rhosts_rsa_key_allowed(pw, cuser, chost, client_host_key))) {
index ee9e827afd086eb56d6f2c52bef2beb535977d32..0ef344712db5a86d6291b8c8bfaa8fdea816009a 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth-rhosts.c,v 1.46 2014/12/23 22:42:48 djm Exp $ */
+/* $OpenBSD: auth-rhosts.c,v 1.47 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 #include <unistd.h>
 
 #include "packet.h"
-#include "buffer.h"
 #include "uidswap.h"
 #include "pathnames.h"
 #include "log.h"
 #include "misc.h"
+#include "buffer.h" /* XXX */
+#include "key.h" /* XXX */
 #include "servconf.h"
 #include "canohost.h"
-#include "key.h"
+#include "sshkey.h"
 #include "hostfile.h"
 #include "auth.h"
 
@@ -189,10 +190,11 @@ check_rhosts_file(const char *filename, const char *hostname,
 int
 auth_rhosts(struct passwd *pw, const char *client_user)
 {
+       struct ssh *ssh = active_state; /* XXX */
        const char *hostname, *ipaddr;
 
-       hostname = get_canonical_hostname(options.use_dns);
-       ipaddr = get_remote_ipaddr();
+       hostname = auth_get_canonical_hostname(ssh, options.use_dns);
+       ipaddr = ssh_remote_ipaddr(ssh);
        return auth_rhosts2(pw, client_user, hostname, ipaddr);
 }
 
diff --git a/auth.c b/auth.c
index 214c2c70841d6f95319c3a92cb6c472ed08876a4..aae0593e7c419a12bda751b80483024a5d306771 100644 (file)
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.c,v 1.113 2015/08/21 03:42:19 djm Exp $ */
+/* $OpenBSD: auth.c,v 1.114 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -27,6 +27,7 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/socket.h>
 
 #include <netinet/in.h>
 
@@ -50,6 +51,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <limits.h>
+#include <netdb.h>
 
 #include "xmalloc.h"
 #include "match.h"
@@ -97,6 +99,7 @@ int auth_debug_init;
 int
 allowed_user(struct passwd * pw)
 {
+       struct ssh *ssh = active_state; /* XXX */
        struct stat st;
        const char *hostname = NULL, *ipaddr = NULL, *passwd = NULL;
        u_int i;
@@ -182,8 +185,8 @@ allowed_user(struct passwd * pw)
 
        if (options.num_deny_users > 0 || options.num_allow_users > 0 ||
            options.num_deny_groups > 0 || options.num_allow_groups > 0) {
-               hostname = get_canonical_hostname(options.use_dns);
-               ipaddr = get_remote_ipaddr();
+               hostname = auth_get_canonical_hostname(ssh, options.use_dns);
+               ipaddr = ssh_remote_ipaddr(ssh);
        }
 
        /* Return false if user is listed in DenyUsers */
@@ -274,6 +277,7 @@ void
 auth_log(Authctxt *authctxt, int authenticated, int partial,
     const char *method, const char *submethod)
 {
+       struct ssh *ssh = active_state; /* XXX */
        void (*authlog) (const char *fmt,...) = verbose;
        char *authmsg;
 
@@ -300,8 +304,8 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
            submethod != NULL ? "/" : "", submethod == NULL ? "" : submethod,
            authctxt->valid ? "" : "invalid user ",
            authctxt->user,
-           get_remote_ipaddr(),
-           get_remote_port(),
+           ssh_remote_ipaddr(ssh),
+           ssh_remote_port(ssh),
            compat20 ? "ssh2" : "ssh1",
            authctxt->info != NULL ? ": " : "",
            authctxt->info != NULL ? authctxt->info : "");
@@ -331,12 +335,14 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
 void
 auth_maxtries_exceeded(Authctxt *authctxt)
 {
+       struct ssh *ssh = active_state; /* XXX */
+
        error("maximum authentication attempts exceeded for "
            "%s%.100s from %.200s port %d %s",
            authctxt->valid ? "" : "invalid user ",
            authctxt->user,
-           get_remote_ipaddr(),
-           get_remote_port(),
+           ssh_remote_ipaddr(ssh),
+           ssh_remote_port(ssh),
            compat20 ? "ssh2" : "ssh1");
        packet_disconnect("Too many authentication failures");
        /* NOTREACHED */
@@ -348,6 +354,8 @@ auth_maxtries_exceeded(Authctxt *authctxt)
 int
 auth_root_allowed(const char *method)
 {
+       struct ssh *ssh = active_state; /* XXX */
+
        switch (options.permit_root_login) {
        case PERMIT_YES:
                return 1;
@@ -364,7 +372,8 @@ auth_root_allowed(const char *method)
                }
                break;
        }
-       logit("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
+       logit("ROOT LOGIN REFUSED FROM %.200s port %d",
+           ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
        return 0;
 }
 
@@ -604,6 +613,7 @@ auth_openprincipals(const char *file, struct passwd *pw, int strict_modes)
 struct passwd *
 getpwnamallow(const char *user)
 {
+       struct ssh *ssh = active_state; /* XXX */
 #ifdef HAVE_LOGIN_CAP
        extern login_cap_t *lc;
 #ifdef BSD_AUTH
@@ -639,8 +649,8 @@ getpwnamallow(const char *user)
        }
 #endif
        if (pw == NULL) {
-               logit("Invalid user %.100s from %.100s",
-                   user, get_remote_ipaddr());
+               logit("Invalid user %.100s from %.100s port %d",
+                   user, ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
 #ifdef CUSTOM_FAILED_LOGIN
                record_failed_login(user,
                    get_canonical_hostname(options.use_dns), "ssh");
@@ -773,3 +783,118 @@ fakepw(void)
 
        return (&fake);
 }
+
+/*
+ * Returns the remote DNS hostname as a string. The returned string must not
+ * be freed. NB. this will usually trigger a DNS query the first time it is
+ * called.
+ * This function does additional checks on the hostname to mitigate some
+ * attacks on legacy rhosts-style authentication.
+ * XXX is RhostsRSAAuthentication vulnerable to these?
+ * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?)
+ */
+
+static char *
+remote_hostname(struct ssh *ssh)
+{
+       struct sockaddr_storage from;
+       socklen_t fromlen;
+       struct addrinfo hints, *ai, *aitop;
+       char name[NI_MAXHOST], ntop2[NI_MAXHOST];
+       const char *ntop = ssh_remote_ipaddr(ssh);
+
+       /* Get IP address of client. */
+       fromlen = sizeof(from);
+       memset(&from, 0, sizeof(from));
+       if (getpeername(ssh_packet_get_connection_in(ssh),
+           (struct sockaddr *)&from, &fromlen) < 0) {
+               debug("getpeername failed: %.100s", strerror(errno));
+               return strdup(ntop);
+       }
+
+       ipv64_normalise_mapped(&from, &fromlen);
+       if (from.ss_family == AF_INET6)
+               fromlen = sizeof(struct sockaddr_in6);
+
+       debug3("Trying to reverse map address %.100s.", ntop);
+       /* Map the IP address to a host name. */
+       if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
+           NULL, 0, NI_NAMEREQD) != 0) {
+               /* Host name not found.  Use ip address. */
+               return strdup(ntop);
+       }
+
+       /*
+        * if reverse lookup result looks like a numeric hostname,
+        * someone is trying to trick us by PTR record like following:
+        *      1.1.1.10.in-addr.arpa.  IN PTR  2.3.4.5
+        */
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+       hints.ai_flags = AI_NUMERICHOST;
+       if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
+               logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
+                   name, ntop);
+               freeaddrinfo(ai);
+               return strdup(ntop);
+       }
+
+       /* Names are stored in lowercase. */
+       lowercase(name);
+
+       /*
+        * Map it back to an IP address and check that the given
+        * address actually is an address of this host.  This is
+        * necessary because anyone with access to a name server can
+        * define arbitrary names for an IP address. Mapping from
+        * name to IP address can be trusted better (but can still be
+        * fooled if the intruder has access to the name server of
+        * the domain).
+        */
+       memset(&hints, 0, sizeof(hints));
+       hints.ai_family = from.ss_family;
+       hints.ai_socktype = SOCK_STREAM;
+       if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
+               logit("reverse mapping checking getaddrinfo for %.700s "
+                   "[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop);
+               return strdup(ntop);
+       }
+       /* Look for the address from the list of addresses. */
+       for (ai = aitop; ai; ai = ai->ai_next) {
+               if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
+                   sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
+                   (strcmp(ntop, ntop2) == 0))
+                               break;
+       }
+       freeaddrinfo(aitop);
+       /* If we reached the end of the list, the address was not there. */
+       if (ai == NULL) {
+               /* Address not found for the host name. */
+               logit("Address %.100s maps to %.600s, but this does not "
+                   "map back to the address - POSSIBLE BREAK-IN ATTEMPT!",
+                   ntop, name);
+               return strdup(ntop);
+       }
+       return strdup(name);
+}
+
+/*
+ * Return the canonical name of the host in the other side of the current
+ * connection.  The host name is cached, so it is efficient to call this
+ * several times.
+ */
+
+const char *
+auth_get_canonical_hostname(struct ssh *ssh, int use_dns)
+{
+       static char *dnsname;
+
+       if (!use_dns)
+               return ssh_remote_ipaddr(ssh);
+       else if (dnsname != NULL)
+               return dnsname;
+       else {
+               dnsname = remote_hostname(ssh);
+               return dnsname;
+       }
+}
diff --git a/auth.h b/auth.h
index 2160154f495c288d5e3b000436f3db1ed4070a66..038b59293a6c93793798e3220fc24aeb8079322b 100644 (file)
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth.h,v 1.86 2015/12/04 16:41:28 markus Exp $ */
+/* $OpenBSD: auth.h,v 1.87 2016/03/07 19:02:43 djm Exp $ */
 
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
@@ -197,6 +197,8 @@ FILE        *auth_openkeyfile(const char *, struct passwd *, int);
 FILE   *auth_openprincipals(const char *, struct passwd *, int);
 int     auth_key_is_revoked(Key *);
 
+const char     *auth_get_canonical_hostname(struct ssh *, int);
+
 HostStatus
 check_key_in_hostfiles(struct passwd *, Key *, const char *,
     const char *, const char *);
index e2327cf77fba9b86ec6e1361f9fc7bdf4e051e41..1b3c3b20297f2e16852490f8244f0b2e71cbaeaf 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: auth2-hostbased.c,v 1.25 2015/05/04 06:10:48 djm Exp $ */
+/* $OpenBSD: auth2-hostbased.c,v 1.26 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *
@@ -160,6 +160,7 @@ int
 hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
     Key *key)
 {
+       struct ssh *ssh = active_state; /* XXX */
        const char *resolvedname, *ipaddr, *lookup, *reason;
        HostStatus host_status;
        int len;
@@ -168,8 +169,8 @@ hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost,
        if (auth_key_is_revoked(key))
                return 0;
 
-       resolvedname = get_canonical_hostname(options.use_dns);
-       ipaddr = get_remote_ipaddr();
+       resolvedname = auth_get_canonical_hostname(ssh, options.use_dns);
+       ipaddr = ssh_remote_ipaddr(ssh);
 
        debug2("%s: chost %s resolvedname %s ipaddr %s", __func__,
            chost, resolvedname, ipaddr);
index 223964ea3bc38bb033e65fb33a1dce9be228f327..f71a08568ed9fa0883a96126e08c1cbc11029bc3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.c,v 1.72 2015/03/01 15:44:40 millert Exp $ */
+/* $OpenBSD: canohost.c,v 1.73 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
 #include "canohost.h"
 #include "misc.h"
 
-static void check_ip_options(int, char *);
-static char *canonical_host_ip = NULL;
-static int cached_port = -1;
-
-/*
- * Return the canonical name of the host at the other end of the socket. The
- * caller should free the returned string.
- */
-
-static char *
-get_remote_hostname(int sock, int use_dns)
-{
-       struct sockaddr_storage from;
-       socklen_t fromlen;
-       struct addrinfo hints, *ai, *aitop;
-       char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
-
-       /* Get IP address of client. */
-       fromlen = sizeof(from);
-       memset(&from, 0, sizeof(from));
-       if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
-               debug("getpeername failed: %.100s", strerror(errno));
-               cleanup_exit(255);
-       }
-
-       if (from.ss_family == AF_INET)
-               check_ip_options(sock, ntop);
-
-       ipv64_normalise_mapped(&from, &fromlen);
-
-       if (from.ss_family == AF_INET6)
-               fromlen = sizeof(struct sockaddr_in6);
-
-       if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
-           NULL, 0, NI_NUMERICHOST) != 0)
-               fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
-
-       if (!use_dns)
-               return xstrdup(ntop);
-
-       debug3("Trying to reverse map address %.100s.", ntop);
-       /* Map the IP address to a host name. */
-       if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
-           NULL, 0, NI_NAMEREQD) != 0) {
-               /* Host name not found.  Use ip address. */
-               return xstrdup(ntop);
-       }
-
-       /*
-        * if reverse lookup result looks like a numeric hostname,
-        * someone is trying to trick us by PTR record like following:
-        *      1.1.1.10.in-addr.arpa.  IN PTR  2.3.4.5
-        */
-       memset(&hints, 0, sizeof(hints));
-       hints.ai_socktype = SOCK_DGRAM; /*dummy*/
-       hints.ai_flags = AI_NUMERICHOST;
-       if (getaddrinfo(name, NULL, &hints, &ai) == 0) {
-               logit("Nasty PTR record \"%s\" is set up for %s, ignoring",
-                   name, ntop);
-               freeaddrinfo(ai);
-               return xstrdup(ntop);
-       }
-
-       /* Names are stores in lowercase. */
-       lowercase(name);
-
-       /*
-        * Map it back to an IP address and check that the given
-        * address actually is an address of this host.  This is
-        * necessary because anyone with access to a name server can
-        * define arbitrary names for an IP address. Mapping from
-        * name to IP address can be trusted better (but can still be
-        * fooled if the intruder has access to the name server of
-        * the domain).
-        */
-       memset(&hints, 0, sizeof(hints));
-       hints.ai_family = from.ss_family;
-       hints.ai_socktype = SOCK_STREAM;
-       if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
-               logit("reverse mapping checking getaddrinfo for %.700s "
-                   "[%s] failed - POSSIBLE BREAK-IN ATTEMPT!", name, ntop);
-               return xstrdup(ntop);
-       }
-       /* Look for the address from the list of addresses. */
-       for (ai = aitop; ai; ai = ai->ai_next) {
-               if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
-                   sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
-                   (strcmp(ntop, ntop2) == 0))
-                               break;
-       }
-       freeaddrinfo(aitop);
-       /* If we reached the end of the list, the address was not there. */
-       if (!ai) {
-               /* Address not found for the host name. */
-               logit("Address %.100s maps to %.600s, but this does not "
-                   "map back to the address - POSSIBLE BREAK-IN ATTEMPT!",
-                   ntop, name);
-               return xstrdup(ntop);
-       }
-       return xstrdup(name);
-}
-
-/*
- * If IP options are supported, make sure there are none (log and
- * disconnect them if any are found).  Basically we are worried about
- * source routing; it can be used to pretend you are somebody
- * (ip-address) you are not. That itself may be "almost acceptable"
- * under certain circumstances, but rhosts autentication is useless
- * if source routing is accepted. Notice also that if we just dropped
- * source routing here, the other side could use IP spoofing to do
- * rest of the interaction and could still bypass security.  So we
- * exit here if we detect any IP options.
- */
-/* IPv4 only */
-static void
-check_ip_options(int sock, char *ipaddr)
-{
-#ifdef IP_OPTIONS
-       u_char options[200];
-       char text[sizeof(options) * 3 + 1];
-       socklen_t option_size, i;
-       int ipproto;
-       struct protoent *ip;
-
-       if ((ip = getprotobyname("ip")) != NULL)
-               ipproto = ip->p_proto;
-       else
-               ipproto = IPPROTO_IP;
-       option_size = sizeof(options);
-       if (getsockopt(sock, ipproto, IP_OPTIONS, options,
-           &option_size) >= 0 && option_size != 0) {
-               text[0] = '\0';
-               for (i = 0; i < option_size; i++)
-                       snprintf(text + i*3, sizeof(text) - i*3,
-                           " %2.2x", options[i]);
-               fatal("Connection from %.100s with IP options:%.800s",
-                   ipaddr, text);
-       }
-#endif /* IP_OPTIONS */
-}
-
 void
 ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
 {
@@ -201,38 +60,6 @@ ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len)
        a4->sin_port = port;
 }
 
-/*
- * Return the canonical name of the host in the other side of the current
- * connection.  The host name is cached, so it is efficient to call this
- * several times.
- */
-
-const char *
-get_canonical_hostname(int use_dns)
-{
-       char *host;
-       static char *canonical_host_name = NULL;
-       static char *remote_ip = NULL;
-
-       /* Check if we have previously retrieved name with same option. */
-       if (use_dns && canonical_host_name != NULL)
-               return canonical_host_name;
-       if (!use_dns && remote_ip != NULL)
-               return remote_ip;
-
-       /* Get the real hostname if socket; otherwise return UNKNOWN. */
-       if (packet_connection_is_on_socket())
-               host = get_remote_hostname(packet_get_connection_in(), use_dns);
-       else
-               host = "UNKNOWN";
-
-       if (use_dns)
-               canonical_host_name = host;
-       else
-               remote_ip = host;
-       return host;
-}
-
 /*
  * Returns the local/remote IP-address/hostname of socket as a string.
  * The returned string must be freed.
@@ -250,12 +77,10 @@ get_socket_address(int sock, int remote, int flags)
        memset(&addr, 0, sizeof(addr));
 
        if (remote) {
-               if (getpeername(sock, (struct sockaddr *)&addr, &addrlen)
-                   < 0)
+               if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) != 0)
                        return NULL;
        } else {
-               if (getsockname(sock, (struct sockaddr *)&addr, &addrlen)
-                   < 0)
+               if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0)
                        return NULL;
        }
 
@@ -271,7 +96,7 @@ get_socket_address(int sock, int remote, int flags)
                /* Get the address in ascii. */
                if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
                    sizeof(ntop), NULL, 0, flags)) != 0) {
-                       error("get_socket_address: getnameinfo %d failed: %s",
+                       error("%s: getnameinfo %d failed: %s", __func__,
                            flags, ssh_gai_strerror(r));
                        return NULL;
                }
@@ -316,7 +141,8 @@ get_local_name(int fd)
 
        /* Handle the case where we were passed a pipe */
        if (gethostname(myname, sizeof(myname)) == -1) {
-               verbose("get_local_name: gethostname: %s", strerror(errno));
+               verbose("%s: gethostname: %s", __func__, strerror(errno));
+               host = xstrdup("UNKNOWN");
        } else {
                host = xstrdup(myname);
        }
@@ -324,51 +150,9 @@ get_local_name(int fd)
        return host;
 }
 
-void
-clear_cached_addr(void)
-{
-       free(canonical_host_ip);
-       canonical_host_ip = NULL;
-       cached_port = -1;
-}
-
-/*
- * Returns the IP-address of the remote host as a string.  The returned
- * string must not be freed.
- */
-
-const char *
-get_remote_ipaddr(void)
-{
-       /* Check whether we have cached the ipaddr. */
-       if (canonical_host_ip == NULL) {
-               if (packet_connection_is_on_socket()) {
-                       canonical_host_ip =
-                           get_peer_ipaddr(packet_get_connection_in());
-                       if (canonical_host_ip == NULL)
-                               cleanup_exit(255);
-               } else {
-                       /* If not on socket, return UNKNOWN. */
-                       canonical_host_ip = xstrdup("UNKNOWN");
-               }
-       }
-       return canonical_host_ip;
-}
-
-const char *
-get_remote_name_or_ip(u_int utmp_len, int use_dns)
-{
-       static const char *remote = "";
-       if (utmp_len > 0)
-               remote = get_canonical_hostname(use_dns);
-       if (utmp_len == 0 || strlen(remote) > utmp_len)
-               remote = get_remote_ipaddr();
-       return remote;
-}
-
 /* Returns the local/remote port for the socket. */
 
-int
+static int
 get_sock_port(int sock, int local)
 {
        struct sockaddr_storage from;
@@ -402,27 +186,11 @@ get_sock_port(int sock, int local)
        /* Return port number. */
        if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
            strport, sizeof(strport), NI_NUMERICSERV)) != 0)
-               fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed: %s",
+               fatal("%s: getnameinfo NI_NUMERICSERV failed: %s", __func__,
                    ssh_gai_strerror(r));
        return atoi(strport);
 }
 
-/* Returns remote/local port number for the current connection. */
-
-static int
-get_port(int local)
-{
-       /*
-        * If the connection is not a socket, return 65535.  This is
-        * intentionally chosen to be an unprivileged port number.
-        */
-       if (!packet_connection_is_on_socket())
-               return 65535;
-
-       /* Get socket and return the port number. */
-       return get_sock_port(packet_get_connection_in(), local);
-}
-
 int
 get_peer_port(int sock)
 {
@@ -430,17 +198,7 @@ get_peer_port(int sock)
 }
 
 int
-get_remote_port(void)
-{
-       /* Cache to avoid getpeername() on a dead connection */
-       if (cached_port == -1)
-               cached_port = get_port(0);
-
-       return cached_port;
-}
-
-int
-get_local_port(void)
+get_local_port(int sock)
 {
-       return get_port(1);
+       return get_sock_port(sock, 1);
 }
index 4c8636f42dd4b8e9aa13607578e0ad1635affe7b..26d62855a935443741836dd958ce808e0b5c5ff6 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: canohost.h,v 1.11 2009/05/27 06:31:25 andreas Exp $ */
+/* $OpenBSD: canohost.h,v 1.12 2016/03/07 19:02:43 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * called by a name other than "ssh" or "Secure Shell".
  */
 
-const char     *get_canonical_hostname(int);
-const char     *get_remote_ipaddr(void);
-const char     *get_remote_name_or_ip(u_int, int);
+#ifndef _CANOHOST_H
+#define _CANOHOST_H
 
 char           *get_peer_ipaddr(int);
 int             get_peer_port(int);
 char           *get_local_ipaddr(int);
 char           *get_local_name(int);
+int            get_local_port(int);
 
-int             get_remote_port(void);
-int             get_local_port(void);
-int             get_sock_port(int, int);
-void            clear_cached_addr(void);
+#endif /* _CANOHOST_H */
 
 void            ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *);
index c9d2015eea39a87b2ef7dfd7d20f63d3c10afb6c..7ee1f98d005a58f2c7101d2eff4eeb0eed7b3509 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.349 2016/02/05 13:28:19 naddy Exp $ */
+/* $OpenBSD: channels.c,v 1.350 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1416,7 +1416,7 @@ port_open_helper(Channel *c, char *rtype)
 {
        char buf[1024];
        char *local_ipaddr = get_local_ipaddr(c->sock);
-       int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
+       int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock);
        char *remote_ipaddr = get_peer_ipaddr(c->sock);
        int remote_port = get_peer_port(c->sock);
 
@@ -2935,7 +2935,7 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
                if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
                    allocated_listen_port != NULL &&
                    *allocated_listen_port == 0) {
-                       *allocated_listen_port = get_sock_port(sock, 1);
+                       *allocated_listen_port = get_local_port(sock);
                        debug("Allocated listen port %d",
                            *allocated_listen_port);
                }
index ac7dd309974c9fdd88ffb082e3db2893d064cac7..6b780e48020bbfdf5aa95685ac8ba9c072781b0b 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor.c,v 1.157 2016/02/15 23:32:37 djm Exp $ */
+/* $OpenBSD: monitor.c,v 1.158 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -1469,6 +1469,7 @@ mm_answer_keyverify(int sock, Buffer *m)
 static void
 mm_record_login(Session *s, struct passwd *pw)
 {
+       struct ssh *ssh = active_state; /* XXX */
        socklen_t fromlen;
        struct sockaddr_storage from;
 
@@ -1490,7 +1491,7 @@ mm_record_login(Session *s, struct passwd *pw)
        }
        /* Record that there was a login on that tty from the remote host. */
        record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
-           get_remote_name_or_ip(utmp_len, options.use_dns),
+           session_get_remote_name_or_ip(ssh, utmp_len, options.use_dns),
            (struct sockaddr *)&from, fromlen);
 }
 
index c5db6df483b78d6588928c20ad4de4600aea41da..552004902b2c511daec7083ddc0cc74e7de94a1d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.c,v 1.87 2016/01/14 16:17:40 markus Exp $ */
+/* $OpenBSD: monitor_wrap.c,v 1.88 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
  * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -378,15 +378,15 @@ mm_user_key_allowed(struct passwd *pw, Key *key, int pubkey_auth_attempt)
 }
 
 int
-mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host,
+mm_hostbased_key_allowed(struct passwd *pw, const char *user, const char *host,
     Key *key)
 {
        return (mm_key_allowed(MM_HOSTKEY, user, host, key, 0));
 }
 
 int
-mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
-    char *host, Key *key)
+mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, const char *user,
+    const char *host, Key *key)
 {
        int ret;
 
@@ -397,8 +397,8 @@ mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user,
 }
 
 int
-mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key,
-    int pubkey_auth_attempt)
+mm_key_allowed(enum mm_keytype type, const char *user, const char *host,
+    Key *key, int pubkey_auth_attempt)
 {
        Buffer m;
        u_char *blob;
index eb820aeea743a9b2630801d02cbda21518681039..9fd02b30c9a2817599a236a67fe5baa868280c79 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: monitor_wrap.h,v 1.29 2015/12/04 16:41:28 markus Exp $ */
+/* $OpenBSD: monitor_wrap.h,v 1.30 2016/03/07 19:02:43 djm Exp $ */
 
 /*
  * Copyright 2002 Niels Provos <provos@citi.umich.edu>
@@ -45,10 +45,12 @@ void mm_inform_authserv(char *, char *);
 struct passwd *mm_getpwnamallow(const char *);
 char *mm_auth2_read_banner(void);
 int mm_auth_password(struct Authctxt *, char *);
-int mm_key_allowed(enum mm_keytype, char *, char *, Key *, int);
+int mm_key_allowed(enum mm_keytype, const char *, const char *, Key *, int);
 int mm_user_key_allowed(struct passwd *, Key *, int);
-int mm_hostbased_key_allowed(struct passwd *, char *, char *, Key *);
-int mm_auth_rhosts_rsa_key_allowed(struct passwd *, char *, char *, Key *);
+int mm_hostbased_key_allowed(struct passwd *, const char *,
+    const char *, Key *);
+int mm_auth_rhosts_rsa_key_allowed(struct passwd *, const char *,
+    const char *, Key *);
 int mm_key_verify(Key *, u_char *, u_int, u_char *, u_int);
 int mm_auth_rsa_key_allowed(struct passwd *, BIGNUM *, Key **);
 int mm_auth_rsa_verify_response(Key *, BIGNUM *, u_char *);
index c26ade44c7f25ef6bbec89c5bd23d80dfa7b7ea7..16322ec6fbf077171867e50700fcccf65048e985 100644 (file)
--- a/opacket.h
+++ b/opacket.h
@@ -144,10 +144,6 @@ void       packet_disconnect(const char *, ...)
        ssh_packet_get_state(active_state, m)
 #define packet_set_state(m) \
        ssh_packet_set_state(active_state, m)
-#if 0
-#define get_remote_ipaddr() \
-       ssh_remote_ipaddr(active_state)
-#endif
 #define packet_get_raw(lenp) \
         sshpkt_ptr(active_state, lenp)
 #define packet_get_ecpoint(c,p) \
index f406c0755a547fc8ff412d2f42b12e9a26cacc4d..48111bb151d4c4ee58db6aa110312be4cb9131e5 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.229 2016/02/17 22:20:14 djm Exp $ */
+/* $OpenBSD: packet.c,v 1.230 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -52,6 +52,7 @@
 #include <arpa/inet.h>
 
 #include <errno.h>
+#include <netdb.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -296,7 +297,7 @@ ssh_packet_set_connection(struct ssh *ssh, int fd_in, int fd_out)
            (r = cipher_init(&state->receive_context, none,
            (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0) {
                error("%s: cipher_init failed: %s", __func__, ssh_err(r));
-               free(ssh);
+               free(ssh); /* XXX need ssh_free_session_state? */
                return NULL;
        }
        state->newkeys[MODE_IN] = state->newkeys[MODE_OUT] = NULL;
@@ -379,6 +380,9 @@ ssh_packet_connection_is_on_socket(struct ssh *ssh)
        struct sockaddr_storage from, to;
        socklen_t fromlen, tolen;
 
+       if (state->connection_in == -1 || state->connection_out == -1)
+               return 0;
+
        /* filedescriptors in and out are the same, so it's a socket */
        if (state->connection_in == state->connection_out)
                return 1;
@@ -468,10 +472,14 @@ ssh_remote_ipaddr(struct ssh *ssh)
        if (ssh->remote_ipaddr == NULL) {
                if (ssh_packet_connection_is_on_socket(ssh)) {
                        ssh->remote_ipaddr = get_peer_ipaddr(sock);
-                       ssh->remote_port = get_sock_port(sock, 0);
+                       ssh->remote_port = get_peer_port(sock);
+                       ssh->local_ipaddr = get_local_ipaddr(sock);
+                       ssh->local_port = get_local_port(sock);
                } else {
                        ssh->remote_ipaddr = strdup("UNKNOWN");
-                       ssh->remote_port = 0;
+                       ssh->remote_port = 65535;
+                       ssh->local_ipaddr = strdup("UNKNOWN");
+                       ssh->local_port = 65535;
                }
        }
        return ssh->remote_ipaddr;
@@ -486,6 +494,27 @@ ssh_remote_port(struct ssh *ssh)
        return ssh->remote_port;
 }
 
+/*
+ * Returns the IP-address of the local host as a string.  The returned
+ * string must not be freed.
+ */
+
+const char *
+ssh_local_ipaddr(struct ssh *ssh)
+{
+       (void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
+       return ssh->local_ipaddr;
+}
+
+/* Returns the port number of the local host. */
+
+int
+ssh_local_port(struct ssh *ssh)
+{
+       (void)ssh_remote_ipaddr(ssh); /* Will lookup and cache. */
+       return ssh->local_port;
+}
+
 /* Closes the connection and clears and frees internal data structures. */
 
 void
index 28516a553a2054ad227f2f71aff2eaa08f82c17d..464d83b1a1389d4be979510fd636c8fe510bf8ea 100644 (file)
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.h,v 1.70 2016/02/08 10:57:07 djm Exp $ */
+/* $OpenBSD: packet.h,v 1.71 2016/03/07 19:02:43 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -56,9 +56,11 @@ struct ssh {
        /* Key exchange */
        struct kex *kex;
 
-       /* cached remote ip address and port*/
+       /* cached local and remote ip addresses and ports */
        char *remote_ipaddr;
        int remote_port;
+       char *local_ipaddr;
+       int local_port;
 
        /* Dispatcher table */
        dispatch_fn *dispatch[DISPATCH_MAX];
@@ -145,6 +147,8 @@ int  ssh_packet_set_state(struct ssh *, struct sshbuf *);
 
 const char *ssh_remote_ipaddr(struct ssh *);
 int     ssh_remote_port(struct ssh *);
+const char *ssh_local_ipaddr(struct ssh *);
+int     ssh_local_port(struct ssh *);
 
 void    ssh_packet_set_rekey_limits(struct ssh *, u_int64_t, time_t);
 time_t  ssh_packet_get_rekey_timeout(struct ssh *);
index b19d30e18303492654917714ab97eb0b59465bed..ba39dce1dffe894cdbd4faf7617c8f1e71f312cd 100644 (file)
@@ -1,5 +1,5 @@
 
-/* $OpenBSD: servconf.c,v 1.285 2016/02/17 05:29:04 djm Exp $ */
+/* $OpenBSD: servconf.c,v 1.286 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -706,14 +706,15 @@ process_queued_listen_addrs(ServerOptions *options)
 struct connection_info *
 get_connection_info(int populate, int use_dns)
 {
+       struct ssh *ssh = active_state; /* XXX */
        static struct connection_info ci;
 
        if (!populate)
                return &ci;
-       ci.host = get_canonical_hostname(use_dns);
-       ci.address = get_remote_ipaddr();
-       ci.laddress = get_local_ipaddr(packet_get_connection_in());
-       ci.lport = get_local_port();
+       ci.host = auth_get_canonical_hostname(ssh, use_dns);
+       ci.address = ssh_remote_ipaddr(ssh);
+       ci.laddress = ssh_local_ipaddr(ssh);
+       ci.lport = ssh_local_port(ssh);
        return &ci;
 }
 
index e6a92476f7fdad6d391d9745176bbebe89c965e6..f9e3e5d14688624328e9e9cc0adf927cd4837cca 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.183 2016/03/04 03:35:44 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.184 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -395,6 +395,7 @@ wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, int *maxfdp,
 static void
 process_input(fd_set *readset)
 {
+       struct ssh *ssh = active_state; /* XXX */
        int len;
        char buf[16384];
 
@@ -402,8 +403,8 @@ process_input(fd_set *readset)
        if (FD_ISSET(connection_in, readset)) {
                len = read(connection_in, buf, sizeof(buf));
                if (len == 0) {
-                       verbose("Connection closed by %.100s",
-                           get_remote_ipaddr());
+                       verbose("Connection closed by %.100s port %d",
+                           ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
                        connection_closed = 1;
                        if (compat20)
                                return;
@@ -412,8 +413,9 @@ process_input(fd_set *readset)
                        if (errno != EINTR && errno != EAGAIN &&
                            errno != EWOULDBLOCK) {
                                verbose("Read error from remote host "
-                                   "%.100s: %.100s",
-                                   get_remote_ipaddr(), strerror(errno));
+                                   "%.100s port %d: %.100s",
+                                   ssh_remote_ipaddr(ssh),
+                                   ssh_remote_port(ssh), strerror(errno));
                                cleanup_exit(255);
                        }
                } else {
index 7a02500ab68fbd90bfe0830e0ad30c5ccad48771..9a75c622ecf0e1251bc29d40513a9bdbee97644d 100644 (file)
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.c,v 1.280 2016/02/16 03:37:48 djm Exp $ */
+/* $OpenBSD: session.c,v 1.281 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved
@@ -778,6 +778,7 @@ do_pre_login(Session *s)
 int
 do_exec(Session *s, const char *command)
 {
+       struct ssh *ssh = active_state; /* XXX */
        int ret;
        const char *forced = NULL, *tty = NULL;
        char session_type[1024];
@@ -820,8 +821,8 @@ do_exec(Session *s, const char *command)
            tty == NULL ? "" : " on ",
            tty == NULL ? "" : tty,
            s->pw->pw_name,
-           get_remote_ipaddr(),
-           get_remote_port(),
+           ssh_remote_ipaddr(ssh),
+           ssh_remote_port(ssh),
            s->self);
 
 #ifdef SSH_AUDIT_EVENTS
@@ -856,6 +857,7 @@ do_exec(Session *s, const char *command)
 void
 do_login(Session *s, const char *command)
 {
+       struct ssh *ssh = active_state; /* XXX */
        socklen_t fromlen;
        struct sockaddr_storage from;
        struct passwd * pw = s->pw;
@@ -878,7 +880,7 @@ do_login(Session *s, const char *command)
        /* Record that there was a login on that tty from the remote host. */
        if (!use_privsep)
                record_login(pid, s->tty, pw->pw_name, pw->pw_uid,
-                   get_remote_name_or_ip(utmp_len,
+                   session_get_remote_name_or_ip(ssh, utmp_len,
                    options.use_dns),
                    (struct sockaddr *)&from, fromlen);
 
@@ -1139,6 +1141,7 @@ copy_environment(char **source, char ***env, u_int *envsize)
 static char **
 do_setup_env(Session *s, const char *shell)
 {
+       struct ssh *ssh = active_state; /* XXX */
        char buf[256];
        u_int i, envsize;
        char **env, *laddr;
@@ -1240,12 +1243,14 @@ do_setup_env(Session *s, const char *shell)
 
        /* SSH_CLIENT deprecated */
        snprintf(buf, sizeof buf, "%.50s %d %d",
-           get_remote_ipaddr(), get_remote_port(), get_local_port());
+           ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+           ssh_local_port(ssh));
        child_set_env(&env, &envsize, "SSH_CLIENT", buf);
 
        laddr = get_local_ipaddr(packet_get_connection_in());
        snprintf(buf, sizeof buf, "%.50s %d %.50s %d",
-           get_remote_ipaddr(), get_remote_port(), laddr, get_local_port());
+           ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+           laddr, ssh_local_port(ssh));
        free(laddr);
        child_set_env(&env, &envsize, "SSH_CONNECTION", buf);
 
@@ -1662,6 +1667,7 @@ child_close_fds(void)
 void
 do_child(Session *s, const char *command)
 {
+       struct ssh *ssh = active_state; /* XXX */
        extern char **environ;
        char **env;
        char *argv[ARGV_MAX];
@@ -1738,14 +1744,14 @@ do_child(Session *s, const char *command)
 
        /* we have to stash the hostname before we close our socket. */
        if (options.use_login)
-               hostname = get_remote_name_or_ip(utmp_len,
+               hostname = session_get_remote_name_or_ip(ssh, utmp_len,
                    options.use_dns);
        /*
         * Close the connection descriptors; note that this is the child, and
         * the server will still have the socket open, and it is important
         * that we do not shutdown it.  Note that the descriptors cannot be
         * closed before building the environment, as we call
-        * get_remote_ipaddr there.
+        * ssh_remote_ipaddr there.
         */
        child_close_fds();
 
@@ -2498,12 +2504,13 @@ session_exit_message(Session *s, int status)
 void
 session_close(Session *s)
 {
+       struct ssh *ssh = active_state; /* XXX */
        u_int i;
 
        verbose("Close session: user %s from %.200s port %d id %d",
            s->pw->pw_name,
-           get_remote_ipaddr(),
-           get_remote_port(),
+           ssh_remote_ipaddr(ssh),
+           ssh_remote_port(ssh),
            s->self);
 
        if (s->ttyfd != -1)
@@ -2772,3 +2779,18 @@ do_cleanup(Authctxt *authctxt)
        if (!use_privsep || mm_is_monitor())
                session_destroy_all(session_pty_cleanup2);
 }
+
+/* Return a name for the remote host that fits inside utmp_size */
+
+const char *
+session_get_remote_name_or_ip(struct ssh *ssh, u_int utmp_size, int use_dns)
+{
+       const char *remote = "";
+
+       if (utmp_size > 0)
+               remote = auth_get_canonical_hostname(ssh, use_dns);
+       if (utmp_size == 0 || strlen(remote) > utmp_size)
+               remote = ssh_remote_ipaddr(ssh);
+       return remote;
+}
+
index 6a2f35e41ffd40a8607882e5f7c9bb0daba34328..f18eaf329d71ad1f74bc13225adc4516bc8b809a 100644 (file)
--- a/session.h
+++ b/session.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: session.h,v 1.31 2013/10/14 21:20:52 djm Exp $ */
+/* $OpenBSD: session.h,v 1.32 2016/03/07 19:02:43 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -81,4 +81,6 @@ void   do_setusercontext(struct passwd *);
 void    child_set_env(char ***envp, u_int *envsizep, const char *name,
                       const char *value);
 
+const char     *session_get_remote_name_or_ip(struct ssh *, u_int, int);
+
 #endif
diff --git a/ssh.c b/ssh.c
index f9ff91f049d599a8e1cb7a5608c704b18693d4c1..a999d5079ce6405d4e63f5b4b7f0ada10f3d0c6e 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh.c,v 1.436 2016/02/15 09:47:49 dtucker Exp $ */
+/* $OpenBSD: ssh.c,v 1.437 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -513,6 +513,7 @@ set_addrinfo_port(struct addrinfo *addrs, int port)
 int
 main(int ac, char **av)
 {
+       struct ssh *ssh = NULL;
        int i, r, opt, exit_status, use_syslog, config_test = 0;
        char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile;
        char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
@@ -1220,6 +1221,8 @@ main(int ac, char **av)
        packet_set_timeout(options.server_alive_interval,
            options.server_alive_count_max);
 
+       ssh = active_state; /* XXX */
+
        if (timeout_ms > 0)
                debug3("timeout: %d ms remain after connect", timeout_ms);
 
@@ -1346,7 +1349,7 @@ main(int ac, char **av)
 
        if (packet_connection_is_on_socket()) {
                verbose("Authenticated to %s ([%s]:%d).", host,
-                   get_remote_ipaddr(), get_remote_port());
+                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
        } else {
                verbose("Authenticated to %s (via proxy).", host);
        }
diff --git a/sshd.c b/sshd.c
index 430569c46081f76c2d0aeaebf9921ebb833852c7..d21aed5156bf298f549d8afefc10646a1943311a 100644 (file)
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshd.c,v 1.465 2016/02/15 09:47:49 dtucker Exp $ */
+/* $OpenBSD: sshd.c,v 1.466 2016/03/07 19:02:43 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -371,7 +371,8 @@ grace_alarm_handler(int sig)
        }
 
        /* Log error and exit. */
-       sigdie("Timeout before authentication for %s", get_remote_ipaddr());
+       sigdie("Timeout before authentication for %s port %d",
+           ssh_remote_ipaddr(active_state), ssh_remote_port(active_state));
 }
 
 /*
@@ -407,7 +408,7 @@ key_regeneration_alarm(int sig)
 }
 
 static void
-sshd_exchange_identification(int sock_in, int sock_out)
+sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out)
 {
        u_int i;
        int mismatch;
@@ -439,7 +440,8 @@ sshd_exchange_identification(int sock_in, int sock_out)
        if (atomicio(vwrite, sock_out, server_version_string,
            strlen(server_version_string))
            != strlen(server_version_string)) {
-               logit("Could not write ident string to %s", get_remote_ipaddr());
+               logit("Could not write ident string to %s port %d",
+                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
                cleanup_exit(255);
        }
 
@@ -447,8 +449,9 @@ sshd_exchange_identification(int sock_in, int sock_out)
        memset(buf, 0, sizeof(buf));
        for (i = 0; i < sizeof(buf) - 1; i++) {
                if (atomicio(read, sock_in, &buf[i], 1) != 1) {
-                       logit("Did not receive identification string from %s",
-                           get_remote_ipaddr());
+                       logit("Did not receive identification string "
+                           "from %s port %d",
+                           ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
                        cleanup_exit(255);
                }
                if (buf[i] == '\r') {
@@ -477,7 +480,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
                (void) atomicio(vwrite, sock_out, s, strlen(s));
                logit("Bad protocol version identification '%.100s' "
                    "from %s port %d", client_version_string,
-                   get_remote_ipaddr(), get_remote_port());
+                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
                close(sock_in);
                close(sock_out);
                cleanup_exit(255);
@@ -485,23 +488,25 @@ sshd_exchange_identification(int sock_in, int sock_out)
        debug("Client protocol version %d.%d; client software version %.100s",
            remote_major, remote_minor, remote_version);
 
-       active_state->compat = compat_datafellows(remote_version);
+       ssh->compat = compat_datafellows(remote_version);
 
-       if ((datafellows & SSH_BUG_PROBE) != 0) {
-               logit("probed from %s with %s.  Don't panic.",
-                   get_remote_ipaddr(), client_version_string);
+       if ((ssh->compat & SSH_BUG_PROBE) != 0) {
+               logit("probed from %s port %d with %s.  Don't panic.",
+                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+                   client_version_string);
                cleanup_exit(255);
        }
-       if ((datafellows & SSH_BUG_SCANNER) != 0) {
-               logit("scanned from %s with %s.  Don't panic.",
-                   get_remote_ipaddr(), client_version_string);
+       if ((ssh->compat & SSH_BUG_SCANNER) != 0) {
+               logit("scanned from %s port %d with %s.  Don't panic.",
+                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+                   client_version_string);
                cleanup_exit(255);
        }
-       if ((datafellows & SSH_BUG_RSASIGMD5) != 0) {
+       if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
                logit("Client version \"%.100s\" uses unsafe RSA signature "
                    "scheme; disabling use of RSA keys", remote_version);
        }
-       if ((datafellows & SSH_BUG_DERIVEKEY) != 0) {
+       if ((ssh->compat & SSH_BUG_DERIVEKEY) != 0) {
                fatal("Client version \"%.100s\" uses unsafe key agreement; "
                    "refusing connection", remote_version);
        }
@@ -546,8 +551,9 @@ sshd_exchange_identification(int sock_in, int sock_out)
                (void) atomicio(vwrite, sock_out, s, strlen(s));
                close(sock_in);
                close(sock_out);
-               logit("Protocol major versions differ for %s: %.200s vs. %.200s",
-                   get_remote_ipaddr(),
+               logit("Protocol major versions differ for %s port %d: "
+                   "%.200s vs. %.200s",
+                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
                    server_version_string, client_version_string);
                cleanup_exit(255);
        }
@@ -1452,6 +1458,47 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
        }
 }
 
+/*
+ * If IP options are supported, make sure there are none (log and
+ * return an error if any are found).  Basically we are worried about
+ * source routing; it can be used to pretend you are somebody
+ * (ip-address) you are not. That itself may be "almost acceptable"
+ * under certain circumstances, but rhosts autentication is useless
+ * if source routing is accepted. Notice also that if we just dropped
+ * source routing here, the other side could use IP spoofing to do
+ * rest of the interaction and could still bypass security.  So we
+ * exit here if we detect any IP options.
+ */
+static void
+check_ip_options(struct ssh *ssh)
+{
+#ifdef IP_OPTIONS
+       int sock_in = ssh_packet_get_connection_in(ssh);
+       struct sockaddr_storage from;
+       socklen_t option_size, i, fromlen = sizeof(from);
+       u_char opts[200];
+       char text[sizeof(opts) * 3 + 1];
+
+       memset(&from, 0, sizeof(from));
+       if (getpeername(sock_in, (struct sockaddr *)&from,
+           &fromlen) < 0)
+               return;
+       if (from.ss_family != AF_INET)
+               return;
+       /* XXX IPv6 options? */
+
+       if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
+           &option_size) >= 0 && option_size != 0) {
+               text[0] = '\0';
+               for (i = 0; i < option_size; i++)
+                       snprintf(text + i*3, sizeof(text) - i*3,
+                           " %2.2x", opts[i]);
+               fatal("Connection from %.100s port %d with IP opts: %.800s",
+                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh), text);
+       }
+       return;
+#endif /* IP_OPTIONS */
+}
 
 /*
  * Main program for the daemon.
@@ -1459,6 +1506,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
 int
 main(int ac, char **av)
 {
+       struct ssh *ssh = NULL;
        extern char *optarg;
        extern int optind;
        int r, opt, i, j, on = 1;
@@ -2118,28 +2166,25 @@ main(int ac, char **av)
         */
        packet_set_connection(sock_in, sock_out);
        packet_set_server();
+       ssh = active_state; /* XXX */
+       check_ip_options(ssh);
 
        /* Set SO_KEEPALIVE if requested. */
        if (options.tcp_keep_alive && packet_connection_is_on_socket() &&
            setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0)
                error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
 
-       if ((remote_port = get_remote_port()) < 0) {
-               debug("get_remote_port failed");
+       if ((remote_port = ssh_remote_port(ssh)) < 0) {
+               debug("ssh_remote_port failed");
                cleanup_exit(255);
        }
 
-       /*
-        * We use get_canonical_hostname with usedns = 0 instead of
-        * get_remote_ipaddr here so IP options will be checked.
-        */
-       (void) get_canonical_hostname(0);
        /*
         * The rest of the code depends on the fact that
-        * get_remote_ipaddr() caches the remote ip, even if
+        * ssh_remote_ipaddr() caches the remote ip, even if
         * the socket goes away.
         */
-       remote_ip = get_remote_ipaddr();
+       remote_ip = ssh_remote_ipaddr(ssh);
 
 #ifdef SSH_AUDIT_EVENTS
        audit_connection_from(remote_ip, remote_port);
@@ -2148,7 +2193,7 @@ main(int ac, char **av)
        /* Log the connection. */
        laddr = get_local_ipaddr(sock_in);
        verbose("Connection from %s port %d on %s port %d",
-           remote_ip, remote_port, laddr,  get_local_port());
+           remote_ip, remote_port, laddr,  ssh_local_port(ssh));
        free(laddr);
 
        /*
@@ -2163,7 +2208,7 @@ main(int ac, char **av)
        if (!debug_flag)
                alarm(options.login_grace_time);
 
-       sshd_exchange_identification(sock_in, sock_out);
+       sshd_exchange_identification(ssh, sock_in, sock_out);
 
        /* In inetd mode, generate ephemeral key only for proto 1 connections */
        if (!compat20 && inetd_flag && sensitive_data.server_key == NULL)
@@ -2299,6 +2344,7 @@ main(int ac, char **av)
 int
 ssh1_session_key(BIGNUM *session_key_int)
 {
+       struct ssh *ssh = active_state; /* XXX */
        int rsafail = 0;
 
        if (BN_cmp(sensitive_data.server_key->rsa->n,
@@ -2307,9 +2353,9 @@ ssh1_session_key(BIGNUM *session_key_int)
                if (BN_num_bits(sensitive_data.server_key->rsa->n) <
                    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) +
                    SSH_KEY_BITS_RESERVED) {
-                       fatal("do_connection: %s: "
+                       fatal("do_connection: %s port %d: "
                            "server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",
-                           get_remote_ipaddr(),
+                           ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
                            BN_num_bits(sensitive_data.server_key->rsa->n),
                            BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
                            SSH_KEY_BITS_RESERVED);
@@ -2325,9 +2371,9 @@ ssh1_session_key(BIGNUM *session_key_int)
                if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <
                    BN_num_bits(sensitive_data.server_key->rsa->n) +
                    SSH_KEY_BITS_RESERVED) {
-                       fatal("do_connection: %s: "
+                       fatal("do_connection: %s port %d: "
                            "host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",
-                           get_remote_ipaddr(),
+                           ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
                            BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),
                            BN_num_bits(sensitive_data.server_key->rsa->n),
                            SSH_KEY_BITS_RESERVED);
@@ -2348,6 +2394,7 @@ ssh1_session_key(BIGNUM *session_key_int)
 static void
 do_ssh1_kex(void)
 {
+       struct ssh *ssh = active_state; /* XXX */
        int i, len;
        int rsafail = 0;
        BIGNUM *session_key_int, *fake_key_int, *real_key_int;
@@ -2465,9 +2512,10 @@ do_ssh1_kex(void)
        (void) BN_mask_bits(session_key_int, sizeof(session_key) * 8);
        len = BN_num_bytes(session_key_int);
        if (len < 0 || (u_int)len > sizeof(session_key)) {
-               error("do_ssh1_kex: bad session key len from %s: "
-                   "session_key_int %d > sizeof(session_key) %lu",
-                   get_remote_ipaddr(), len, (u_long)sizeof(session_key));
+               error("%s: bad session key len from %s port %d: "
+                   "session_key_int %d > sizeof(session_key) %lu", __func__,
+                   ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
+                   len, (u_long)sizeof(session_key));
                rsafail++;
        } else {
                explicit_bzero(session_key, sizeof(session_key));