diff options
author | Damien Miller <djm@mindrot.org> | 2014-07-02 15:29:40 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2014-07-02 15:29:40 +1000 |
commit | 4b3ed647d5b328cf68e6a8ffbee490d8e0683e82 (patch) | |
tree | ab21f41c022d2d8f1f8d2a3814f77d10d4c72e7e | |
parent | 9e01ff28664921ce9b6500681333e42fb133b4d0 (diff) |
- markus@cvs.openbsd.org 2014/06/27 16:41:56
[channels.c channels.h clientloop.c ssh.c]
fix remote fwding with same listen port but different listen address
with gerhard@, ok djm@
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | channels.c | 96 | ||||
-rw-r--r-- | channels.h | 5 | ||||
-rw-r--r-- | clientloop.c | 4 | ||||
-rw-r--r-- | ssh.c | 6 |
5 files changed, 83 insertions, 32 deletions
@@ -58,6 +58,10 @@ | |||
58 | [sshbuf.c] | 58 | [sshbuf.c] |
59 | unblock SIGSEGV before raising it | 59 | unblock SIGSEGV before raising it |
60 | ok djm | 60 | ok djm |
61 | - markus@cvs.openbsd.org 2014/06/27 16:41:56 | ||
62 | [channels.c channels.h clientloop.c ssh.c] | ||
63 | fix remote fwding with same listen port but different listen address | ||
64 | with gerhard@, ok djm@ | ||
61 | 65 | ||
62 | 20140618 | 66 | 20140618 |
63 | - (tim) [openssh/session.c] Work around to get chroot sftp working on UnixWare | 67 | - (tim) [openssh/session.c] Work around to get chroot sftp working on UnixWare |
diff --git a/channels.c b/channels.c index 1020071ff..7d0439e68 100644 --- a/channels.c +++ b/channels.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.c,v 1.332 2014/04/28 03:09:18 djm Exp $ */ | 1 | /* $OpenBSD: channels.c,v 1.333 2014/06/27 16:41:56 markus 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 |
@@ -110,7 +110,8 @@ static int channel_max_fd = 0; | |||
110 | typedef struct { | 110 | typedef struct { |
111 | char *host_to_connect; /* Connect to 'host'. */ | 111 | char *host_to_connect; /* Connect to 'host'. */ |
112 | u_short port_to_connect; /* Connect to 'port'. */ | 112 | u_short port_to_connect; /* Connect to 'port'. */ |
113 | u_short listen_port; /* Remote side should listen port number. */ | 113 | char *listen_host; /* Remote side should listen address. */ |
114 | u_short listen_port; /* Remote side should listen port. */ | ||
114 | } ForwardPermission; | 115 | } ForwardPermission; |
115 | 116 | ||
116 | /* List of all permitted host/port pairs to connect by the user. */ | 117 | /* List of all permitted host/port pairs to connect by the user. */ |
@@ -3032,11 +3033,52 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port, | |||
3032 | idx = num_permitted_opens++; | 3033 | idx = num_permitted_opens++; |
3033 | permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); | 3034 | permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); |
3034 | permitted_opens[idx].port_to_connect = port_to_connect; | 3035 | permitted_opens[idx].port_to_connect = port_to_connect; |
3036 | permitted_opens[idx].listen_host = listen_host ? | ||
3037 | xstrdup(listen_host) : NULL; | ||
3035 | permitted_opens[idx].listen_port = listen_port; | 3038 | permitted_opens[idx].listen_port = listen_port; |
3036 | } | 3039 | } |
3037 | return (idx); | 3040 | return (idx); |
3038 | } | 3041 | } |
3039 | 3042 | ||
3043 | static int | ||
3044 | open_match(ForwardPermission *allowed_open, const char *requestedhost, | ||
3045 | u_short requestedport) | ||
3046 | { | ||
3047 | if (allowed_open->host_to_connect == NULL) | ||
3048 | return 0; | ||
3049 | if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT && | ||
3050 | allowed_open->port_to_connect != requestedport) | ||
3051 | return 0; | ||
3052 | if (strcmp(allowed_open->host_to_connect, requestedhost) != 0) | ||
3053 | return 0; | ||
3054 | return 1; | ||
3055 | } | ||
3056 | |||
3057 | /* | ||
3058 | * Note that in he listen host/port case | ||
3059 | * we don't support FWD_PERMIT_ANY_PORT and | ||
3060 | * need to translate between the configured-host (listen_host) | ||
3061 | * and what we've sent to the remote server (channel_rfwd_bind_host) | ||
3062 | */ | ||
3063 | static int | ||
3064 | open_listen_match(ForwardPermission *allowed_open, const char *requestedhost, | ||
3065 | u_short requestedport, int translate) | ||
3066 | { | ||
3067 | const char *allowed_host; | ||
3068 | |||
3069 | if (allowed_open->host_to_connect == NULL) | ||
3070 | return 0; | ||
3071 | if (allowed_open->listen_port != requestedport) | ||
3072 | return 0; | ||
3073 | allowed_host = translate ? | ||
3074 | channel_rfwd_bind_host(allowed_open->listen_host) : | ||
3075 | allowed_open->listen_host; | ||
3076 | if (allowed_host == NULL || | ||
3077 | strcmp(allowed_host, requestedhost) != 0) | ||
3078 | return 0; | ||
3079 | return 1; | ||
3080 | } | ||
3081 | |||
3040 | /* | 3082 | /* |
3041 | * Request cancellation of remote forwarding of connection host:port from | 3083 | * Request cancellation of remote forwarding of connection host:port from |
3042 | * local side. | 3084 | * local side. |
@@ -3050,8 +3092,7 @@ channel_request_rforward_cancel(const char *host, u_short port) | |||
3050 | return -1; | 3092 | return -1; |
3051 | 3093 | ||
3052 | for (i = 0; i < num_permitted_opens; i++) { | 3094 | for (i = 0; i < num_permitted_opens; i++) { |
3053 | if (permitted_opens[i].host_to_connect != NULL && | 3095 | if (open_listen_match(&permitted_opens[i], host, port, 0)) |
3054 | permitted_opens[i].listen_port == port) | ||
3055 | break; | 3096 | break; |
3056 | } | 3097 | } |
3057 | if (i >= num_permitted_opens) { | 3098 | if (i >= num_permitted_opens) { |
@@ -3065,10 +3106,12 @@ channel_request_rforward_cancel(const char *host, u_short port) | |||
3065 | packet_put_int(port); | 3106 | packet_put_int(port); |
3066 | packet_send(); | 3107 | packet_send(); |
3067 | 3108 | ||
3068 | permitted_opens[i].listen_port = 0; | ||
3069 | permitted_opens[i].port_to_connect = 0; | 3109 | permitted_opens[i].port_to_connect = 0; |
3110 | permitted_opens[i].listen_port = 0; | ||
3070 | free(permitted_opens[i].host_to_connect); | 3111 | free(permitted_opens[i].host_to_connect); |
3071 | permitted_opens[i].host_to_connect = NULL; | 3112 | permitted_opens[i].host_to_connect = NULL; |
3113 | free(permitted_opens[i].listen_host); | ||
3114 | permitted_opens[i].listen_host = NULL; | ||
3072 | 3115 | ||
3073 | return 0; | 3116 | return 0; |
3074 | } | 3117 | } |
@@ -3134,6 +3177,8 @@ channel_add_permitted_opens(char *host, int port) | |||
3134 | num_permitted_opens + 1, sizeof(*permitted_opens)); | 3177 | num_permitted_opens + 1, sizeof(*permitted_opens)); |
3135 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); | 3178 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); |
3136 | permitted_opens[num_permitted_opens].port_to_connect = port; | 3179 | permitted_opens[num_permitted_opens].port_to_connect = port; |
3180 | permitted_opens[num_permitted_opens].listen_host = NULL; | ||
3181 | permitted_opens[num_permitted_opens].listen_port = 0; | ||
3137 | num_permitted_opens++; | 3182 | num_permitted_opens++; |
3138 | 3183 | ||
3139 | all_opens_permitted = 0; | 3184 | all_opens_permitted = 0; |
@@ -3165,6 +3210,8 @@ channel_update_permitted_opens(int idx, int newport) | |||
3165 | permitted_opens[idx].port_to_connect = 0; | 3210 | permitted_opens[idx].port_to_connect = 0; |
3166 | free(permitted_opens[idx].host_to_connect); | 3211 | free(permitted_opens[idx].host_to_connect); |
3167 | permitted_opens[idx].host_to_connect = NULL; | 3212 | permitted_opens[idx].host_to_connect = NULL; |
3213 | free(permitted_opens[idx].listen_host); | ||
3214 | permitted_opens[idx].listen_host = NULL; | ||
3168 | } | 3215 | } |
3169 | } | 3216 | } |
3170 | 3217 | ||
@@ -3178,6 +3225,8 @@ channel_add_adm_permitted_opens(char *host, int port) | |||
3178 | permitted_adm_opens[num_adm_permitted_opens].host_to_connect | 3225 | permitted_adm_opens[num_adm_permitted_opens].host_to_connect |
3179 | = xstrdup(host); | 3226 | = xstrdup(host); |
3180 | permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; | 3227 | permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; |
3228 | permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL; | ||
3229 | permitted_adm_opens[num_adm_permitted_opens].listen_port = 0; | ||
3181 | return ++num_adm_permitted_opens; | 3230 | return ++num_adm_permitted_opens; |
3182 | } | 3231 | } |
3183 | 3232 | ||
@@ -3195,8 +3244,10 @@ channel_clear_permitted_opens(void) | |||
3195 | { | 3244 | { |
3196 | int i; | 3245 | int i; |
3197 | 3246 | ||
3198 | for (i = 0; i < num_permitted_opens; i++) | 3247 | for (i = 0; i < num_permitted_opens; i++) { |
3199 | free(permitted_opens[i].host_to_connect); | 3248 | free(permitted_opens[i].host_to_connect); |
3249 | free(permitted_opens[i].listen_host); | ||
3250 | } | ||
3200 | free(permitted_opens); | 3251 | free(permitted_opens); |
3201 | permitted_opens = NULL; | 3252 | permitted_opens = NULL; |
3202 | num_permitted_opens = 0; | 3253 | num_permitted_opens = 0; |
@@ -3207,8 +3258,10 @@ channel_clear_adm_permitted_opens(void) | |||
3207 | { | 3258 | { |
3208 | int i; | 3259 | int i; |
3209 | 3260 | ||
3210 | for (i = 0; i < num_adm_permitted_opens; i++) | 3261 | for (i = 0; i < num_adm_permitted_opens; i++) { |
3211 | free(permitted_adm_opens[i].host_to_connect); | 3262 | free(permitted_adm_opens[i].host_to_connect); |
3263 | free(permitted_adm_opens[i].listen_host); | ||
3264 | } | ||
3212 | free(permitted_adm_opens); | 3265 | free(permitted_adm_opens); |
3213 | permitted_adm_opens = NULL; | 3266 | permitted_adm_opens = NULL; |
3214 | num_adm_permitted_opens = 0; | 3267 | num_adm_permitted_opens = 0; |
@@ -3246,15 +3299,6 @@ permitopen_port(const char *p) | |||
3246 | return -1; | 3299 | return -1; |
3247 | } | 3300 | } |
3248 | 3301 | ||
3249 | static int | ||
3250 | port_match(u_short allowedport, u_short requestedport) | ||
3251 | { | ||
3252 | if (allowedport == FWD_PERMIT_ANY_PORT || | ||
3253 | allowedport == requestedport) | ||
3254 | return 1; | ||
3255 | return 0; | ||
3256 | } | ||
3257 | |||
3258 | /* Try to start non-blocking connect to next host in cctx list */ | 3302 | /* Try to start non-blocking connect to next host in cctx list */ |
3259 | static int | 3303 | static int |
3260 | connect_next(struct channel_connect *cctx) | 3304 | connect_next(struct channel_connect *cctx) |
@@ -3349,13 +3393,14 @@ connect_to(const char *host, u_short port, char *ctype, char *rname) | |||
3349 | } | 3393 | } |
3350 | 3394 | ||
3351 | Channel * | 3395 | Channel * |
3352 | channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname) | 3396 | channel_connect_by_listen_address(const char *listen_host, |
3397 | u_short listen_port, char *ctype, char *rname) | ||
3353 | { | 3398 | { |
3354 | int i; | 3399 | int i; |
3355 | 3400 | ||
3356 | for (i = 0; i < num_permitted_opens; i++) { | 3401 | for (i = 0; i < num_permitted_opens; i++) { |
3357 | if (permitted_opens[i].host_to_connect != NULL && | 3402 | if (open_listen_match(&permitted_opens[i], listen_host, |
3358 | port_match(permitted_opens[i].listen_port, listen_port)) { | 3403 | listen_port, 1)) { |
3359 | return connect_to( | 3404 | return connect_to( |
3360 | permitted_opens[i].host_to_connect, | 3405 | permitted_opens[i].host_to_connect, |
3361 | permitted_opens[i].port_to_connect, ctype, rname); | 3406 | permitted_opens[i].port_to_connect, ctype, rname); |
@@ -3375,20 +3420,19 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname) | |||
3375 | permit = all_opens_permitted; | 3420 | permit = all_opens_permitted; |
3376 | if (!permit) { | 3421 | if (!permit) { |
3377 | for (i = 0; i < num_permitted_opens; i++) | 3422 | for (i = 0; i < num_permitted_opens; i++) |
3378 | if (permitted_opens[i].host_to_connect != NULL && | 3423 | if (open_match(&permitted_opens[i], host, port)) { |
3379 | port_match(permitted_opens[i].port_to_connect, port) && | ||
3380 | strcmp(permitted_opens[i].host_to_connect, host) == 0) | ||
3381 | permit = 1; | 3424 | permit = 1; |
3425 | break; | ||
3426 | } | ||
3382 | } | 3427 | } |
3383 | 3428 | ||
3384 | if (num_adm_permitted_opens > 0) { | 3429 | if (num_adm_permitted_opens > 0) { |
3385 | permit_adm = 0; | 3430 | permit_adm = 0; |
3386 | for (i = 0; i < num_adm_permitted_opens; i++) | 3431 | for (i = 0; i < num_adm_permitted_opens; i++) |
3387 | if (permitted_adm_opens[i].host_to_connect != NULL && | 3432 | if (open_match(&permitted_adm_opens[i], host, port)) { |
3388 | port_match(permitted_adm_opens[i].port_to_connect, port) && | ||
3389 | strcmp(permitted_adm_opens[i].host_to_connect, host) | ||
3390 | == 0) | ||
3391 | permit_adm = 1; | 3433 | permit_adm = 1; |
3434 | break; | ||
3435 | } | ||
3392 | } | 3436 | } |
3393 | 3437 | ||
3394 | if (!permit || !permit_adm) { | 3438 | if (!permit || !permit_adm) { |
diff --git a/channels.h b/channels.h index 4fab9d7c4..4745b9a7d 100644 --- a/channels.h +++ b/channels.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.h,v 1.113 2013/06/07 15:37:52 dtucker Exp $ */ | 1 | /* $OpenBSD: channels.h,v 1.114 2014/06/27 16:41:56 markus Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -266,7 +266,8 @@ void channel_print_adm_permitted_opens(void); | |||
266 | int channel_input_port_forward_request(int, int); | 266 | int channel_input_port_forward_request(int, int); |
267 | Channel *channel_connect_to(const char *, u_short, char *, char *); | 267 | Channel *channel_connect_to(const char *, u_short, char *, char *); |
268 | Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); | 268 | Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); |
269 | Channel *channel_connect_by_listen_address(u_short, char *, char *); | 269 | Channel *channel_connect_by_listen_address(const char *, u_short, |
270 | char *, char *); | ||
270 | int channel_request_remote_forwarding(const char *, u_short, | 271 | int channel_request_remote_forwarding(const char *, u_short, |
271 | const char *, u_short); | 272 | const char *, u_short); |
272 | int channel_setup_local_fwd_listener(const char *, u_short, | 273 | int channel_setup_local_fwd_listener(const char *, u_short, |
diff --git a/clientloop.c b/clientloop.c index 203151ea8..02510e26d 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.259 2014/04/29 13:10:30 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.260 2014/06/27 16:41:56 markus 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 |
@@ -1849,7 +1849,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) | |||
1849 | "originator %s port %d", listen_address, listen_port, | 1849 | "originator %s port %d", listen_address, listen_port, |
1850 | originator_address, originator_port); | 1850 | originator_address, originator_port); |
1851 | 1851 | ||
1852 | c = channel_connect_by_listen_address(listen_port, | 1852 | c = channel_connect_by_listen_address(listen_address, listen_port, |
1853 | "forwarded-tcpip", originator_address); | 1853 | "forwarded-tcpip", originator_address); |
1854 | 1854 | ||
1855 | free(originator_address); | 1855 | free(originator_address); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.403 2014/06/24 02:19:48 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.404 2014/06/27 16:41:56 markus 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 |
@@ -1279,8 +1279,10 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
1279 | Forward *rfwd = (Forward *)ctxt; | 1279 | Forward *rfwd = (Forward *)ctxt; |
1280 | 1280 | ||
1281 | /* XXX verbose() on failure? */ | 1281 | /* XXX verbose() on failure? */ |
1282 | debug("remote forward %s for: listen %d, connect %s:%d", | 1282 | debug("remote forward %s for: listen %s%s%d, connect %s:%d", |
1283 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", | 1283 | type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", |
1284 | rfwd->listen_host == NULL ? "" : rfwd->listen_host, | ||
1285 | rfwd->listen_host == NULL ? "" : ":", | ||
1284 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); | 1286 | rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); |
1285 | if (rfwd->listen_port == 0) { | 1287 | if (rfwd->listen_port == 0) { |
1286 | if (type == SSH2_MSG_REQUEST_SUCCESS) { | 1288 | if (type == SSH2_MSG_REQUEST_SUCCESS) { |