diff options
author | dtucker@openbsd.org <dtucker@openbsd.org> | 2017-02-01 02:59:09 +0000 |
---|---|---|
committer | Darren Tucker <dtucker@zip.com.au> | 2017-02-03 14:23:24 +1100 |
commit | 858252fb1d451ebb0969cf9749116c8f0ee42753 (patch) | |
tree | 86168774d4d73763e0114ec62d7abeb29fbfba12 | |
parent | 6ba9f893838489add6ec4213c7a997b425e4a9e0 (diff) |
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 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.356 2016/10/18 17:32:54 dtucker Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.357 2017/02/01 02:59:09 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * 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) | |||
3065 | } | 3065 | } |
3066 | packet_check_eom(); | 3066 | packet_check_eom(); |
3067 | c = channel_connect_to_port(host, host_port, | 3067 | c = channel_connect_to_port(host, host_port, |
3068 | "connected socket", originator_string); | 3068 | "connected socket", originator_string, NULL, NULL); |
3069 | free(originator_string); | 3069 | free(originator_string); |
3070 | free(host); | 3070 | free(host); |
3071 | if (c == NULL) { | 3071 | if (c == NULL) { |
@@ -4026,9 +4026,13 @@ channel_connect_ctx_free(struct channel_connect *cctx) | |||
4026 | memset(cctx, 0, sizeof(*cctx)); | 4026 | memset(cctx, 0, sizeof(*cctx)); |
4027 | } | 4027 | } |
4028 | 4028 | ||
4029 | /* Return CONNECTING channel to remote host:port or local socket path */ | 4029 | /* |
4030 | * Return CONNECTING channel to remote host:port or local socket path, | ||
4031 | * passing back the failure reason if appropriate. | ||
4032 | */ | ||
4030 | static Channel * | 4033 | static Channel * |
4031 | connect_to(const char *name, int port, char *ctype, char *rname) | 4034 | connect_to_reason(const char *name, int port, char *ctype, char *rname, |
4035 | int *reason, const char **errmsg) | ||
4032 | { | 4036 | { |
4033 | struct addrinfo hints; | 4037 | struct addrinfo hints; |
4034 | int gaierr; | 4038 | int gaierr; |
@@ -4069,7 +4073,12 @@ connect_to(const char *name, int port, char *ctype, char *rname) | |||
4069 | hints.ai_family = IPv4or6; | 4073 | hints.ai_family = IPv4or6; |
4070 | hints.ai_socktype = SOCK_STREAM; | 4074 | hints.ai_socktype = SOCK_STREAM; |
4071 | snprintf(strport, sizeof strport, "%d", port); | 4075 | snprintf(strport, sizeof strport, "%d", port); |
4072 | if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) { | 4076 | if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) |
4077 | != 0) { | ||
4078 | if (errmsg != NULL) | ||
4079 | *errmsg = ssh_gai_strerror(gaierr); | ||
4080 | if (reason != NULL) | ||
4081 | *reason = SSH2_OPEN_CONNECT_FAILED; | ||
4073 | error("connect_to %.100s: unknown host (%s)", name, | 4082 | error("connect_to %.100s: unknown host (%s)", name, |
4074 | ssh_gai_strerror(gaierr)); | 4083 | ssh_gai_strerror(gaierr)); |
4075 | return NULL; | 4084 | return NULL; |
@@ -4092,6 +4101,13 @@ connect_to(const char *name, int port, char *ctype, char *rname) | |||
4092 | return c; | 4101 | return c; |
4093 | } | 4102 | } |
4094 | 4103 | ||
4104 | /* Return CONNECTING channel to remote host:port or local socket path */ | ||
4105 | static Channel * | ||
4106 | connect_to(const char *name, int port, char *ctype, char *rname) | ||
4107 | { | ||
4108 | return connect_to_reason(name, port, ctype, rname, NULL, NULL); | ||
4109 | } | ||
4110 | |||
4095 | /* | 4111 | /* |
4096 | * returns either the newly connected channel or the downstream channel | 4112 | * returns either the newly connected channel or the downstream channel |
4097 | * that needs to deal with this connection. | 4113 | * that needs to deal with this connection. |
@@ -4136,7 +4152,8 @@ channel_connect_by_listen_path(const char *path, char *ctype, char *rname) | |||
4136 | 4152 | ||
4137 | /* Check if connecting to that port is permitted and connect. */ | 4153 | /* Check if connecting to that port is permitted and connect. */ |
4138 | Channel * | 4154 | Channel * |
4139 | channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname) | 4155 | channel_connect_to_port(const char *host, u_short port, char *ctype, |
4156 | char *rname, int *reason, const char **errmsg) | ||
4140 | { | 4157 | { |
4141 | int i, permit, permit_adm = 1; | 4158 | int i, permit, permit_adm = 1; |
4142 | 4159 | ||
@@ -4161,9 +4178,11 @@ channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname | |||
4161 | if (!permit || !permit_adm) { | 4178 | if (!permit || !permit_adm) { |
4162 | logit("Received request to connect to host %.100s port %d, " | 4179 | logit("Received request to connect to host %.100s port %d, " |
4163 | "but the request was denied.", host, port); | 4180 | "but the request was denied.", host, port); |
4181 | if (reason != NULL) | ||
4182 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; | ||
4164 | return NULL; | 4183 | return NULL; |
4165 | } | 4184 | } |
4166 | return connect_to(host, port, ctype, rname); | 4185 | return connect_to_reason(host, port, ctype, rname, reason, errmsg); |
4167 | } | 4186 | } |
4168 | 4187 | ||
4169 | /* Check if connecting to that path is permitted and connect. */ | 4188 | /* 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 @@ | |||
1 | /* $OpenBSD: channels.h,v 1.120 2016/10/18 17:32:54 dtucker Exp $ */ | 1 | /* $OpenBSD: channels.h,v 1.121 2017/02/01 02:59:09 dtucker Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -275,7 +275,8 @@ void channel_update_permitted_opens(int, int); | |||
275 | void channel_clear_permitted_opens(void); | 275 | void channel_clear_permitted_opens(void); |
276 | void channel_clear_adm_permitted_opens(void); | 276 | void channel_clear_adm_permitted_opens(void); |
277 | void channel_print_adm_permitted_opens(void); | 277 | void channel_print_adm_permitted_opens(void); |
278 | Channel *channel_connect_to_port(const char *, u_short, char *, char *); | 278 | Channel *channel_connect_to_port(const char *, u_short, char *, char *, int *, |
279 | const char **); | ||
279 | Channel *channel_connect_to_path(const char *, char *, char *); | 280 | Channel *channel_connect_to_path(const char *, char *, char *); |
280 | Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); | 281 | Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); |
281 | Channel *channel_connect_by_listen_address(const char *, u_short, | 282 | 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 @@ | |||
1 | /* $OpenBSD: serverloop.c,v 1.190 2017/01/04 05:37:40 djm Exp $ */ | 1 | /* $OpenBSD: serverloop.c,v 1.191 2017/02/01 02:59:09 dtucker Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * 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) | |||
430 | } | 430 | } |
431 | 431 | ||
432 | static Channel * | 432 | static Channel * |
433 | server_request_direct_tcpip(void) | 433 | server_request_direct_tcpip(int *reason, const char **errmsg) |
434 | { | 434 | { |
435 | Channel *c = NULL; | 435 | Channel *c = NULL; |
436 | char *target, *originator; | 436 | char *target, *originator; |
@@ -449,11 +449,13 @@ server_request_direct_tcpip(void) | |||
449 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && | 449 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && |
450 | !no_port_forwarding_flag && !options.disable_forwarding) { | 450 | !no_port_forwarding_flag && !options.disable_forwarding) { |
451 | c = channel_connect_to_port(target, target_port, | 451 | c = channel_connect_to_port(target, target_port, |
452 | "direct-tcpip", "direct-tcpip"); | 452 | "direct-tcpip", "direct-tcpip", reason, errmsg); |
453 | } else { | 453 | } else { |
454 | logit("refused local port forward: " | 454 | logit("refused local port forward: " |
455 | "originator %s port %d, target %s port %d", | 455 | "originator %s port %d, target %s port %d", |
456 | originator, originator_port, target, target_port); | 456 | originator, originator_port, target, target_port); |
457 | if (reason != NULL) | ||
458 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; | ||
457 | } | 459 | } |
458 | 460 | ||
459 | free(originator); | 461 | free(originator); |
@@ -581,7 +583,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
581 | { | 583 | { |
582 | Channel *c = NULL; | 584 | Channel *c = NULL; |
583 | char *ctype; | 585 | char *ctype; |
584 | int rchan; | 586 | const char *errmsg = NULL; |
587 | int rchan, reason = SSH2_OPEN_CONNECT_FAILED; | ||
585 | u_int rmaxpack, rwindow, len; | 588 | u_int rmaxpack, rwindow, len; |
586 | 589 | ||
587 | ctype = packet_get_string(&len); | 590 | ctype = packet_get_string(&len); |
@@ -595,7 +598,7 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
595 | if (strcmp(ctype, "session") == 0) { | 598 | if (strcmp(ctype, "session") == 0) { |
596 | c = server_request_session(); | 599 | c = server_request_session(); |
597 | } else if (strcmp(ctype, "direct-tcpip") == 0) { | 600 | } else if (strcmp(ctype, "direct-tcpip") == 0) { |
598 | c = server_request_direct_tcpip(); | 601 | c = server_request_direct_tcpip(&reason, &errmsg); |
599 | } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { | 602 | } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { |
600 | c = server_request_direct_streamlocal(); | 603 | c = server_request_direct_streamlocal(); |
601 | } else if (strcmp(ctype, "tun@openssh.com") == 0) { | 604 | } else if (strcmp(ctype, "tun@openssh.com") == 0) { |
@@ -618,9 +621,9 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt) | |||
618 | debug("server_input_channel_open: failure %s", ctype); | 621 | debug("server_input_channel_open: failure %s", ctype); |
619 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); | 622 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); |
620 | packet_put_int(rchan); | 623 | packet_put_int(rchan); |
621 | packet_put_int(SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED); | 624 | packet_put_int(reason); |
622 | if (!(datafellows & SSH_BUG_OPENFAILURE)) { | 625 | if (!(datafellows & SSH_BUG_OPENFAILURE)) { |
623 | packet_put_cstring("open failed"); | 626 | packet_put_cstring(errmsg ? errmsg : "open failed"); |
624 | packet_put_cstring(""); | 627 | packet_put_cstring(""); |
625 | } | 628 | } |
626 | packet_send(); | 629 | packet_send(); |