diff options
author | dtucker@openbsd.org <dtucker@openbsd.org> | 2017-02-01 03:59:09 +0100 |
---|---|---|
committer | Darren Tucker <dtucker@zip.com.au> | 2017-02-03 04:23:24 +0100 |
commit | 858252fb1d451ebb0969cf9749116c8f0ee42753 (patch) | |
tree | 86168774d4d73763e0114ec62d7abeb29fbfba12 | |
parent | upstream commit (diff) | |
download | openssh-858252fb1d451ebb0969cf9749116c8f0ee42753.tar.xz openssh-858252fb1d451ebb0969cf9749116c8f0ee42753.zip |
upstream commit
Return true reason for port forwarding failures where
feasible rather than always "administratively prohibited". bz#2674, ok djm@
Upstream-ID: d901d9887951774e604ca970e1827afaaef9e419
-rw-r--r-- | channels.c | 33 | ||||
-rw-r--r-- | channels.h | 5 | ||||
-rw-r--r-- | serverloop.c | 17 |
3 files changed, 39 insertions, 16 deletions
diff --git a/channels.c b/channels.c index bef8ad6aa..398da9a89 100644 --- a/channels.c +++ b/channels.c @@ -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. */ diff --git a/channels.h b/channels.h index 09c3c3655..ce43236d5 100644 --- a/channels.h +++ b/channels.h @@ -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, diff --git a/serverloop.c b/serverloop.c index bdb944fa3..2976f5594 100644 --- a/serverloop.c +++ b/serverloop.c @@ -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(); |