summaryrefslogtreecommitdiff
path: root/channels.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2014-07-02 15:29:40 +1000
committerDamien Miller <djm@mindrot.org>2014-07-02 15:29:40 +1000
commit4b3ed647d5b328cf68e6a8ffbee490d8e0683e82 (patch)
treeab21f41c022d2d8f1f8d2a3814f77d10d4c72e7e /channels.c
parent9e01ff28664921ce9b6500681333e42fb133b4d0 (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@
Diffstat (limited to 'channels.c')
-rw-r--r--channels.c96
1 files changed, 70 insertions, 26 deletions
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;
110typedef struct { 110typedef 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
3043static int
3044open_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 */
3063static int
3064open_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
3249static int
3250port_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 */
3259static int 3303static int
3260connect_next(struct channel_connect *cctx) 3304connect_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
3351Channel * 3395Channel *
3352channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname) 3396channel_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) {