]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream commit
authordtucker@openbsd.org <dtucker@openbsd.org>
Wed, 1 Feb 2017 02:59:09 +0000 (02:59 +0000)
committerDarren Tucker <dtucker@zip.com.au>
Fri, 3 Feb 2017 03:23:24 +0000 (14:23 +1100)
Return true reason for port forwarding failures where
feasible rather than always "administratively prohibited".  bz#2674, ok djm@

Upstream-ID: d901d9887951774e604ca970e1827afaaef9e419

channels.c
channels.h
serverloop.c

index bef8ad6aa2b37668a1b6f10121a37db3eac46988..398da9a89540de38a6bfa00bfcb35f4f0baa3669 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.c,v 1.356 2016/10/18 17:32:54 dtucker Exp $ */
+/* $OpenBSD: channels.c,v 1.357 2017/02/01 02:59:09 dtucker Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -3065,7 +3065,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
        }
        packet_check_eom();
        c = channel_connect_to_port(host, host_port,
-           "connected socket", originator_string);
+           "connected socket", originator_string, NULL, NULL);
        free(originator_string);
        free(host);
        if (c == NULL) {
@@ -4026,9 +4026,13 @@ channel_connect_ctx_free(struct channel_connect *cctx)
        memset(cctx, 0, sizeof(*cctx));
 }
 
-/* Return CONNECTING channel to remote host:port or local socket path */
+/*
+ * Return CONNECTING channel to remote host:port or local socket path,
+ * passing back the failure reason if appropriate.
+ */
 static Channel *
-connect_to(const char *name, int port, char *ctype, char *rname)
+connect_to_reason(const char *name, int port, char *ctype, char *rname,
+     int *reason, const char **errmsg)
 {
        struct addrinfo hints;
        int gaierr;
@@ -4069,7 +4073,12 @@ connect_to(const char *name, int port, char *ctype, char *rname)
                hints.ai_family = IPv4or6;
                hints.ai_socktype = SOCK_STREAM;
                snprintf(strport, sizeof strport, "%d", port);
-               if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
+               if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop))
+                   != 0) {
+                       if (errmsg != NULL)
+                               *errmsg = ssh_gai_strerror(gaierr);
+                       if (reason != NULL)
+                               *reason = SSH2_OPEN_CONNECT_FAILED;
                        error("connect_to %.100s: unknown host (%s)", name,
                            ssh_gai_strerror(gaierr));
                        return NULL;
@@ -4092,6 +4101,13 @@ connect_to(const char *name, int port, char *ctype, char *rname)
        return c;
 }
 
+/* Return CONNECTING channel to remote host:port or local socket path */
+static Channel *
+connect_to(const char *name, int port, char *ctype, char *rname)
+{
+       return connect_to_reason(name, port, ctype, rname, NULL, NULL);
+}
+
 /*
  * returns either the newly connected channel or the downstream channel
  * that needs to deal with this connection.
@@ -4136,7 +4152,8 @@ channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
 
 /* Check if connecting to that port is permitted and connect. */
 Channel *
-channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
+channel_connect_to_port(const char *host, u_short port, char *ctype,
+    char *rname, int *reason, const char **errmsg)
 {
        int i, permit, permit_adm = 1;
 
@@ -4161,9 +4178,11 @@ channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname
        if (!permit || !permit_adm) {
                logit("Received request to connect to host %.100s port %d, "
                    "but the request was denied.", host, port);
+               if (reason != NULL)
+                       *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
                return NULL;
        }
-       return connect_to(host, port, ctype, rname);
+       return connect_to_reason(host, port, ctype, rname, reason, errmsg);
 }
 
 /* Check if connecting to that path is permitted and connect. */
index 09c3c36557df02abd9ce775b4025e3a555864ce5..ce43236d54599ec6b6ddc8366ac4c6750aed4c1b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: channels.h,v 1.120 2016/10/18 17:32:54 dtucker Exp $ */
+/* $OpenBSD: channels.h,v 1.121 2017/02/01 02:59:09 dtucker Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -275,7 +275,8 @@ void         channel_update_permitted_opens(int, int);
 void    channel_clear_permitted_opens(void);
 void    channel_clear_adm_permitted_opens(void);
 void    channel_print_adm_permitted_opens(void);
-Channel        *channel_connect_to_port(const char *, u_short, char *, char *);
+Channel        *channel_connect_to_port(const char *, u_short, char *, char *, int *,
+            const char **);
 Channel *channel_connect_to_path(const char *, char *, char *);
 Channel        *channel_connect_stdio_fwd(const char*, u_short, int, int);
 Channel        *channel_connect_by_listen_address(const char *, u_short,
index bdb944fa3bf25c2ef164477efa2f2b5cae8f4327..2976f55943b40cfcd3dd30085ff8e8c627d45c23 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: serverloop.c,v 1.190 2017/01/04 05:37:40 djm Exp $ */
+/* $OpenBSD: serverloop.c,v 1.191 2017/02/01 02:59:09 dtucker Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -430,7 +430,7 @@ server_input_keep_alive(int type, u_int32_t seq, void *ctxt)
 }
 
 static Channel *
-server_request_direct_tcpip(void)
+server_request_direct_tcpip(int *reason, const char **errmsg)
 {
        Channel *c = NULL;
        char *target, *originator;
@@ -449,11 +449,13 @@ server_request_direct_tcpip(void)
        if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
            !no_port_forwarding_flag && !options.disable_forwarding) {
                c = channel_connect_to_port(target, target_port,
-                   "direct-tcpip", "direct-tcpip");
+                   "direct-tcpip", "direct-tcpip", reason, errmsg);
        } else {
                logit("refused local port forward: "
                    "originator %s port %d, target %s port %d",
                    originator, originator_port, target, target_port);
+               if (reason != NULL)
+                       *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED;
        }
 
        free(originator);
@@ -581,7 +583,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
 {
        Channel *c = NULL;
        char *ctype;
-       int rchan;
+       const char *errmsg = NULL;
+       int rchan, reason = SSH2_OPEN_CONNECT_FAILED;
        u_int rmaxpack, rwindow, len;
 
        ctype = packet_get_string(&len);
@@ -595,7 +598,7 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
        if (strcmp(ctype, "session") == 0) {
                c = server_request_session();
        } else if (strcmp(ctype, "direct-tcpip") == 0) {
-               c = server_request_direct_tcpip();
+               c = server_request_direct_tcpip(&reason, &errmsg);
        } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
                c = server_request_direct_streamlocal();
        } else if (strcmp(ctype, "tun@openssh.com") == 0) {
@@ -618,9 +621,9 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
                debug("server_input_channel_open: failure %s", ctype);
                packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
                packet_put_int(rchan);
-               packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED);
+               packet_put_int(reason);
                if (!(datafellows & SSH_BUG_OPENFAILURE)) {
-                       packet_put_cstring("open failed");
+                       packet_put_cstring(errmsg ? errmsg : "open failed");
                        packet_put_cstring("");
                }
                packet_send();