diff options
author | djm@openbsd.org <djm@openbsd.org> | 2017-09-12 06:32:07 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2017-09-12 17:37:02 +1000 |
commit | dbee4119b502e3f8b6cd3282c69c537fd01d8e16 (patch) | |
tree | b8a3263a79e0920e8d08f188654f1ccb7c254406 | |
parent | abd59663df37a42152e37980113ccaa405b9a282 (diff) |
upstream commit
refactor channels.c
Move static state to a "struct ssh_channels" that is allocated at
runtime and tracked as a member of struct ssh.
Explicitly pass "struct ssh" to all channels functions.
Replace use of the legacy packet APIs in channels.c.
Rework sshd_config PermitOpen handling: previously the configuration
parser would call directly into the channels layer. After the refactor
this is not possible, as the channels structures are allocated at
connection time and aren't available when the configuration is parsed.
The server config parser now tracks PermitOpen itself and explicitly
configures the channels code later.
ok markus@
Upstream-ID: 11828f161656b965cc306576422613614bea2d8f
-rw-r--r-- | auth-options.c | 11 | ||||
-rw-r--r-- | auth.c | 3 | ||||
-rw-r--r-- | channels.c | 3011 | ||||
-rw-r--r-- | channels.h | 180 | ||||
-rw-r--r-- | clientloop.c | 191 | ||||
-rw-r--r-- | clientloop.h | 31 | ||||
-rw-r--r-- | monitor.c | 5 | ||||
-rw-r--r-- | monitor_wrap.c | 4 | ||||
-rw-r--r-- | mux.c | 193 | ||||
-rw-r--r-- | nchan.c | 114 | ||||
-rw-r--r-- | packet.c | 68 | ||||
-rw-r--r-- | packet.h | 8 | ||||
-rw-r--r-- | servconf.c | 87 | ||||
-rw-r--r-- | servconf.h | 14 | ||||
-rw-r--r-- | serverloop.c | 105 | ||||
-rw-r--r-- | serverloop.h | 6 | ||||
-rw-r--r-- | session.c | 223 | ||||
-rw-r--r-- | session.h | 16 | ||||
-rw-r--r-- | ssh.c | 88 | ||||
-rw-r--r-- | sshbuf.h | 3 | ||||
-rw-r--r-- | sshconnect.c | 38 | ||||
-rw-r--r-- | sshconnect.h | 8 | ||||
-rw-r--r-- | sshd.c | 19 | ||||
-rw-r--r-- | ssherr.c | 4 | ||||
-rw-r--r-- | ssherr.h | 3 |
25 files changed, 2441 insertions, 1992 deletions
diff --git a/auth-options.c b/auth-options.c index 0a191dbba..bed00eef0 100644 --- a/auth-options.c +++ b/auth-options.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth-options.c,v 1.73 2017/05/31 10:54:00 markus Exp $ */ | 1 | /* $OpenBSD: auth-options.c,v 1.74 2017/09/12 06:32:07 djm 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 |
@@ -61,9 +61,13 @@ char *authorized_principals = NULL; | |||
61 | 61 | ||
62 | extern ServerOptions options; | 62 | extern ServerOptions options; |
63 | 63 | ||
64 | /* XXX refactor to be stateless */ | ||
65 | |||
64 | void | 66 | void |
65 | auth_clear_options(void) | 67 | auth_clear_options(void) |
66 | { | 68 | { |
69 | struct ssh *ssh = active_state; /* XXX */ | ||
70 | |||
67 | no_agent_forwarding_flag = 0; | 71 | no_agent_forwarding_flag = 0; |
68 | no_port_forwarding_flag = 0; | 72 | no_port_forwarding_flag = 0; |
69 | no_pty_flag = 0; | 73 | no_pty_flag = 0; |
@@ -81,7 +85,7 @@ auth_clear_options(void) | |||
81 | free(authorized_principals); | 85 | free(authorized_principals); |
82 | authorized_principals = NULL; | 86 | authorized_principals = NULL; |
83 | forced_tun_device = -1; | 87 | forced_tun_device = -1; |
84 | channel_clear_permitted_opens(); | 88 | channel_clear_permitted_opens(ssh); |
85 | } | 89 | } |
86 | 90 | ||
87 | /* | 91 | /* |
@@ -117,6 +121,7 @@ match_flag(const char *opt, int allow_negate, char **optsp, const char *msg) | |||
117 | /* | 121 | /* |
118 | * return 1 if access is granted, 0 if not. | 122 | * return 1 if access is granted, 0 if not. |
119 | * side effect: sets key option flags | 123 | * side effect: sets key option flags |
124 | * XXX remove side effects; fill structure instead. | ||
120 | */ | 125 | */ |
121 | int | 126 | int |
122 | auth_parse_options(struct passwd *pw, char *opts, const char *file, | 127 | auth_parse_options(struct passwd *pw, char *opts, const char *file, |
@@ -380,7 +385,7 @@ auth_parse_options(struct passwd *pw, char *opts, const char *file, | |||
380 | goto bad_option; | 385 | goto bad_option; |
381 | } | 386 | } |
382 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) | 387 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0) |
383 | channel_add_permitted_opens(host, port); | 388 | channel_add_permitted_opens(ssh, host, port); |
384 | free(patterns); | 389 | free(patterns); |
385 | goto next_option; | 390 | goto next_option; |
386 | } | 391 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: auth.c,v 1.123 2017/08/18 05:36:45 djm Exp $ */ | 1 | /* $OpenBSD: auth.c,v 1.124 2017/09/12 06:32:07 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -567,6 +567,7 @@ getpwnamallow(const char *user) | |||
567 | ci->user = user; | 567 | ci->user = user; |
568 | parse_server_match_config(&options, ci); | 568 | parse_server_match_config(&options, ci); |
569 | log_change_level(options.log_level); | 569 | log_change_level(options.log_level); |
570 | process_permitopen(ssh, &options); | ||
570 | 571 | ||
571 | #if defined(_AIX) && defined(HAVE_SETAUTHDB) | 572 | #if defined(_AIX) && defined(HAVE_SETAUTHDB) |
572 | aix_setauthdb(user); | 573 | aix_setauthdb(user); |
diff --git a/channels.c b/channels.c index d9e81b5fa..935625c74 100644 --- a/channels.c +++ b/channels.c | |||
@@ -55,26 +55,27 @@ | |||
55 | 55 | ||
56 | #include <errno.h> | 56 | #include <errno.h> |
57 | #include <fcntl.h> | 57 | #include <fcntl.h> |
58 | #include <limits.h> | ||
58 | #include <netdb.h> | 59 | #include <netdb.h> |
60 | #include <stdarg.h> | ||
59 | #ifdef HAVE_STDINT_H | 61 | #ifdef HAVE_STDINT_H |
60 | #include <stdint.h> | 62 | #include <stdint.h> |
61 | #endif | 63 | #endif |
62 | #include <stdio.h> | 64 | #include <stdio.h> |
63 | #include <stdlib.h> | 65 | #include <stdlib.h> |
64 | #include <string.h> | 66 | #include <string.h> |
65 | #include <termios.h> | 67 | #include <termios.h> |
66 | #include <unistd.h> | 68 | #include <unistd.h> |
67 | #include <stdarg.h> | ||
68 | 69 | ||
69 | #include "openbsd-compat/sys-queue.h" | 70 | #include "openbsd-compat/sys-queue.h" |
70 | #include "xmalloc.h" | 71 | #include "xmalloc.h" |
71 | #include "ssh.h" | 72 | #include "ssh.h" |
72 | #include "ssh2.h" | 73 | #include "ssh2.h" |
73 | #include "ssherr.h" | 74 | #include "ssherr.h" |
75 | #include "sshbuf.h" | ||
74 | #include "packet.h" | 76 | #include "packet.h" |
75 | #include "log.h" | 77 | #include "log.h" |
76 | #include "misc.h" | 78 | #include "misc.h" |
77 | #include "buffer.h" | ||
78 | #include "channels.h" | 79 | #include "channels.h" |
79 | #include "compat.h" | 80 | #include "compat.h" |
80 | #include "canohost.h" | 81 | #include "canohost.h" |
@@ -82,28 +83,19 @@ | |||
82 | #include "authfd.h" | 83 | #include "authfd.h" |
83 | #include "pathnames.h" | 84 | #include "pathnames.h" |
84 | 85 | ||
85 | /* -- channel core */ | 86 | /* -- agent forwarding */ |
86 | 87 | #define NUM_SOCKS 10 | |
87 | /* | ||
88 | * Pointer to an array containing all allocated channels. The array is | ||
89 | * dynamically extended as needed. | ||
90 | */ | ||
91 | static Channel **channels = NULL; | ||
92 | |||
93 | /* | ||
94 | * Size of the channel array. All slots of the array must always be | ||
95 | * initialized (at least the type field); unused slots set to NULL | ||
96 | */ | ||
97 | static u_int channels_alloc = 0; | ||
98 | 88 | ||
99 | /* | 89 | /* -- tcp forwarding */ |
100 | * Maximum file descriptor value used in any of the channels. This is | 90 | /* special-case port number meaning allow any port */ |
101 | * updated in channel_new. | 91 | #define FWD_PERMIT_ANY_PORT 0 |
102 | */ | ||
103 | static int channel_max_fd = 0; | ||
104 | 92 | ||
93 | /* special-case wildcard meaning allow any host */ | ||
94 | #define FWD_PERMIT_ANY_HOST "*" | ||
105 | 95 | ||
106 | /* -- tcp forwarding */ | 96 | /* -- X11 forwarding */ |
97 | /* Maximum number of fake X11 displays to try. */ | ||
98 | #define MAX_DISPLAYS 1000 | ||
107 | 99 | ||
108 | /* | 100 | /* |
109 | * Data structure for storing which hosts are permitted for forward requests. | 101 | * Data structure for storing which hosts are permitted for forward requests. |
@@ -123,100 +115,150 @@ typedef struct { | |||
123 | Channel *downstream; /* Downstream mux*/ | 115 | Channel *downstream; /* Downstream mux*/ |
124 | } ForwardPermission; | 116 | } ForwardPermission; |
125 | 117 | ||
126 | /* List of all permitted host/port pairs to connect by the user. */ | 118 | typedef void chan_fn(struct ssh *, Channel *c, |
127 | static ForwardPermission *permitted_opens = NULL; | 119 | fd_set *readset, fd_set *writeset); |
128 | 120 | ||
129 | /* List of all permitted host/port pairs to connect by the admin. */ | 121 | /* Master structure for channels state */ |
130 | static ForwardPermission *permitted_adm_opens = NULL; | 122 | struct ssh_channels { |
131 | 123 | /* | |
132 | /* Number of permitted host/port pairs in the array permitted by the user. */ | 124 | * Pointer to an array containing all allocated channels. The array |
133 | static int num_permitted_opens = 0; | 125 | * is dynamically extended as needed. |
126 | */ | ||
127 | Channel **channels; | ||
134 | 128 | ||
135 | /* Number of permitted host/port pair in the array permitted by the admin. */ | 129 | /* |
136 | static int num_adm_permitted_opens = 0; | 130 | * Size of the channel array. All slots of the array must always be |
131 | * initialized (at least the type field); unused slots set to NULL | ||
132 | */ | ||
133 | u_int channels_alloc; | ||
137 | 134 | ||
138 | /* special-case port number meaning allow any port */ | 135 | /* |
139 | #define FWD_PERMIT_ANY_PORT 0 | 136 | * Maximum file descriptor value used in any of the channels. This is |
137 | * updated in channel_new. | ||
138 | */ | ||
139 | int channel_max_fd; | ||
140 | 140 | ||
141 | /* special-case wildcard meaning allow any host */ | 141 | /* |
142 | #define FWD_PERMIT_ANY_HOST "*" | 142 | * 'channel_pre*' are called just before select() to add any bits |
143 | * relevant to channels in the select bitmasks. | ||
144 | * | ||
145 | * 'channel_post*': perform any appropriate operations for | ||
146 | * channels which have events pending. | ||
147 | */ | ||
148 | chan_fn **channel_pre; | ||
149 | chan_fn **channel_post; | ||
143 | 150 | ||
144 | /* | 151 | /* -- tcp forwarding */ |
145 | * If this is true, all opens are permitted. This is the case on the server | ||
146 | * on which we have to trust the client anyway, and the user could do | ||
147 | * anything after logging in anyway. | ||
148 | */ | ||
149 | static int all_opens_permitted = 0; | ||
150 | 152 | ||
153 | /* List of all permitted host/port pairs to connect by the user. */ | ||
154 | ForwardPermission *permitted_opens; | ||
151 | 155 | ||
152 | /* -- X11 forwarding */ | 156 | /* List of all permitted host/port pairs to connect by the admin. */ |
157 | ForwardPermission *permitted_adm_opens; | ||
153 | 158 | ||
154 | /* Maximum number of fake X11 displays to try. */ | 159 | /* |
155 | #define MAX_DISPLAYS 1000 | 160 | * Number of permitted host/port pairs in the array permitted by |
161 | * the user. | ||
162 | */ | ||
163 | u_int num_permitted_opens; | ||
156 | 164 | ||
157 | /* Saved X11 local (client) display. */ | 165 | /* |
158 | static char *x11_saved_display = NULL; | 166 | * Number of permitted host/port pair in the array permitted by |
167 | * the admin. | ||
168 | */ | ||
169 | u_int num_adm_permitted_opens; | ||
159 | 170 | ||
160 | /* Saved X11 authentication protocol name. */ | 171 | /* |
161 | static char *x11_saved_proto = NULL; | 172 | * If this is true, all opens are permitted. This is the case on |
173 | * the server on which we have to trust the client anyway, and the | ||
174 | * user could do anything after logging in anyway. | ||
175 | */ | ||
176 | int all_opens_permitted; | ||
162 | 177 | ||
163 | /* Saved X11 authentication data. This is the real data. */ | 178 | /* -- X11 forwarding */ |
164 | static char *x11_saved_data = NULL; | ||
165 | static u_int x11_saved_data_len = 0; | ||
166 | 179 | ||
167 | /* Deadline after which all X11 connections are refused */ | 180 | /* Saved X11 local (client) display. */ |
168 | static u_int x11_refuse_time; | 181 | char *x11_saved_display; |
169 | 182 | ||
170 | /* | 183 | /* Saved X11 authentication protocol name. */ |
171 | * Fake X11 authentication data. This is what the server will be sending us; | 184 | char *x11_saved_proto; |
172 | * we should replace any occurrences of this by the real data. | ||
173 | */ | ||
174 | static u_char *x11_fake_data = NULL; | ||
175 | static u_int x11_fake_data_len; | ||
176 | 185 | ||
186 | /* Saved X11 authentication data. This is the real data. */ | ||
187 | char *x11_saved_data; | ||
188 | u_int x11_saved_data_len; | ||
177 | 189 | ||
178 | /* -- agent forwarding */ | 190 | /* Deadline after which all X11 connections are refused */ |
191 | u_int x11_refuse_time; | ||
179 | 192 | ||
180 | #define NUM_SOCKS 10 | 193 | /* |
194 | * Fake X11 authentication data. This is what the server will be | ||
195 | * sending us; we should replace any occurrences of this by the | ||
196 | * real data. | ||
197 | */ | ||
198 | u_char *x11_fake_data; | ||
199 | u_int x11_fake_data_len; | ||
181 | 200 | ||
182 | /* AF_UNSPEC or AF_INET or AF_INET6 */ | 201 | /* AF_UNSPEC or AF_INET or AF_INET6 */ |
183 | static int IPv4or6 = AF_UNSPEC; | 202 | int IPv4or6; |
203 | }; | ||
184 | 204 | ||
185 | /* helper */ | 205 | /* helper */ |
186 | static void port_open_helper(Channel *c, char *rtype); | 206 | static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype); |
187 | static const char *channel_rfwd_bind_host(const char *listen_host); | 207 | static const char *channel_rfwd_bind_host(const char *listen_host); |
188 | 208 | ||
189 | /* non-blocking connect helpers */ | 209 | /* non-blocking connect helpers */ |
190 | static int connect_next(struct channel_connect *); | 210 | static int connect_next(struct channel_connect *); |
191 | static void channel_connect_ctx_free(struct channel_connect *); | 211 | static void channel_connect_ctx_free(struct channel_connect *); |
192 | 212 | ||
213 | /* Setup helper */ | ||
214 | static void channel_handler_init(struct ssh_channels *sc); | ||
215 | |||
193 | /* -- channel core */ | 216 | /* -- channel core */ |
194 | 217 | ||
218 | void | ||
219 | channel_init_channels(struct ssh *ssh) | ||
220 | { | ||
221 | struct ssh_channels *sc; | ||
222 | |||
223 | if ((sc = calloc(1, sizeof(*sc))) == NULL || | ||
224 | (sc->channel_pre = calloc(SSH_CHANNEL_MAX_TYPE, | ||
225 | sizeof(*sc->channel_pre))) == NULL || | ||
226 | (sc->channel_post = calloc(SSH_CHANNEL_MAX_TYPE, | ||
227 | sizeof(*sc->channel_post))) == NULL) | ||
228 | fatal("%s: allocation failed", __func__); | ||
229 | sc->channels_alloc = 10; | ||
230 | sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels)); | ||
231 | sc->IPv4or6 = AF_UNSPEC; | ||
232 | channel_handler_init(sc); | ||
233 | |||
234 | ssh->chanctxt = sc; | ||
235 | } | ||
236 | |||
195 | Channel * | 237 | Channel * |
196 | channel_by_id(int id) | 238 | channel_by_id(struct ssh *ssh, int id) |
197 | { | 239 | { |
198 | Channel *c; | 240 | Channel *c; |
199 | 241 | ||
200 | if (id < 0 || (u_int)id >= channels_alloc) { | 242 | if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) { |
201 | logit("channel_by_id: %d: bad id", id); | 243 | logit("%s: %d: bad id", __func__, id); |
202 | return NULL; | 244 | return NULL; |
203 | } | 245 | } |
204 | c = channels[id]; | 246 | c = ssh->chanctxt->channels[id]; |
205 | if (c == NULL) { | 247 | if (c == NULL) { |
206 | logit("channel_by_id: %d: bad id: channel free", id); | 248 | logit("%s: %d: bad id: channel free", __func__, id); |
207 | return NULL; | 249 | return NULL; |
208 | } | 250 | } |
209 | return c; | 251 | return c; |
210 | } | 252 | } |
211 | 253 | ||
212 | Channel * | 254 | Channel * |
213 | channel_by_remote_id(int remote_id) | 255 | channel_by_remote_id(struct ssh *ssh, int remote_id) |
214 | { | 256 | { |
215 | Channel *c; | 257 | Channel *c; |
216 | u_int i; | 258 | u_int i; |
217 | 259 | ||
218 | for (i = 0; i < channels_alloc; i++) { | 260 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
219 | c = channels[i]; | 261 | c = ssh->chanctxt->channels[i]; |
220 | if (c != NULL && c->remote_id == remote_id) | 262 | if (c != NULL && c->remote_id == remote_id) |
221 | return c; | 263 | return c; |
222 | } | 264 | } |
@@ -228,12 +270,12 @@ channel_by_remote_id(int remote_id) | |||
228 | * Private channels, like listening sockets, may not receive messages. | 270 | * Private channels, like listening sockets, may not receive messages. |
229 | */ | 271 | */ |
230 | Channel * | 272 | Channel * |
231 | channel_lookup(int id) | 273 | channel_lookup(struct ssh *ssh, int id) |
232 | { | 274 | { |
233 | Channel *c; | 275 | Channel *c; |
234 | 276 | ||
235 | if ((c = channel_by_id(id)) == NULL) | 277 | if ((c = channel_by_id(ssh, id)) == NULL) |
236 | return (NULL); | 278 | return NULL; |
237 | 279 | ||
238 | switch (c->type) { | 280 | switch (c->type) { |
239 | case SSH_CHANNEL_X11_OPEN: | 281 | case SSH_CHANNEL_X11_OPEN: |
@@ -244,10 +286,10 @@ channel_lookup(int id) | |||
244 | case SSH_CHANNEL_OPEN: | 286 | case SSH_CHANNEL_OPEN: |
245 | case SSH_CHANNEL_ABANDONED: | 287 | case SSH_CHANNEL_ABANDONED: |
246 | case SSH_CHANNEL_MUX_PROXY: | 288 | case SSH_CHANNEL_MUX_PROXY: |
247 | return (c); | 289 | return c; |
248 | } | 290 | } |
249 | logit("Non-public channel %d, type %d.", id, c->type); | 291 | logit("Non-public channel %d, type %d.", id, c->type); |
250 | return (NULL); | 292 | return NULL; |
251 | } | 293 | } |
252 | 294 | ||
253 | /* | 295 | /* |
@@ -255,13 +297,15 @@ channel_lookup(int id) | |||
255 | * when the channel consumer/producer is ready, e.g. shell exec'd | 297 | * when the channel consumer/producer is ready, e.g. shell exec'd |
256 | */ | 298 | */ |
257 | static void | 299 | static void |
258 | channel_register_fds(Channel *c, int rfd, int wfd, int efd, | 300 | channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, |
259 | int extusage, int nonblock, int is_tty) | 301 | int extusage, int nonblock, int is_tty) |
260 | { | 302 | { |
303 | struct ssh_channels *sc = ssh->chanctxt; | ||
304 | |||
261 | /* Update the maximum file descriptor value. */ | 305 | /* Update the maximum file descriptor value. */ |
262 | channel_max_fd = MAXIMUM(channel_max_fd, rfd); | 306 | sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd); |
263 | channel_max_fd = MAXIMUM(channel_max_fd, wfd); | 307 | sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, wfd); |
264 | channel_max_fd = MAXIMUM(channel_max_fd, efd); | 308 | sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, efd); |
265 | 309 | ||
266 | if (rfd != -1) | 310 | if (rfd != -1) |
267 | fcntl(rfd, F_SETFD, FD_CLOEXEC); | 311 | fcntl(rfd, F_SETFD, FD_CLOEXEC); |
@@ -299,190 +343,221 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd, | |||
299 | * remote_name to be freed. | 343 | * remote_name to be freed. |
300 | */ | 344 | */ |
301 | Channel * | 345 | Channel * |
302 | channel_new(char *ctype, int type, int rfd, int wfd, int efd, | 346 | channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, |
303 | u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock) | 347 | u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock) |
304 | { | 348 | { |
305 | int found; | 349 | struct ssh_channels *sc = ssh->chanctxt; |
306 | u_int i; | 350 | u_int i, found; |
307 | Channel *c; | 351 | Channel *c; |
308 | 352 | ||
309 | /* Do initial allocation if this is the first call. */ | ||
310 | if (channels_alloc == 0) { | ||
311 | channels_alloc = 10; | ||
312 | channels = xcalloc(channels_alloc, sizeof(Channel *)); | ||
313 | for (i = 0; i < channels_alloc; i++) | ||
314 | channels[i] = NULL; | ||
315 | } | ||
316 | /* Try to find a free slot where to put the new channel. */ | 353 | /* Try to find a free slot where to put the new channel. */ |
317 | for (found = -1, i = 0; i < channels_alloc; i++) | 354 | for (i = 0; i < sc->channels_alloc; i++) { |
318 | if (channels[i] == NULL) { | 355 | if (sc->channels[i] == NULL) { |
319 | /* Found a free slot. */ | 356 | /* Found a free slot. */ |
320 | found = (int)i; | 357 | found = i; |
321 | break; | 358 | break; |
322 | } | 359 | } |
323 | if (found < 0) { | 360 | } |
324 | /* There are no free slots. Take last+1 slot and expand the array. */ | 361 | if (i >= sc->channels_alloc) { |
325 | found = channels_alloc; | 362 | /* |
326 | if (channels_alloc > 10000) | 363 | * There are no free slots. Take last+1 slot and expand |
327 | fatal("channel_new: internal error: channels_alloc %d " | 364 | * the array. |
328 | "too big.", channels_alloc); | 365 | */ |
329 | channels = xreallocarray(channels, channels_alloc + 10, | 366 | found = sc->channels_alloc; |
330 | sizeof(Channel *)); | 367 | if (sc->channels_alloc > CHANNELS_MAX_CHANNELS) |
331 | channels_alloc += 10; | 368 | fatal("%s: internal error: channels_alloc %d too big", |
332 | debug2("channel: expanding %d", channels_alloc); | 369 | __func__, sc->channels_alloc); |
333 | for (i = found; i < channels_alloc; i++) | 370 | sc->channels = xrecallocarray(sc->channels, sc->channels_alloc, |
334 | channels[i] = NULL; | 371 | sc->channels_alloc + 10, sizeof(*sc->channels)); |
372 | sc->channels_alloc += 10; | ||
373 | debug2("channel: expanding %d", sc->channels_alloc); | ||
335 | } | 374 | } |
336 | /* Initialize and return new channel. */ | 375 | /* Initialize and return new channel. */ |
337 | c = channels[found] = xcalloc(1, sizeof(Channel)); | 376 | c = sc->channels[found] = xcalloc(1, sizeof(Channel)); |
338 | buffer_init(&c->input); | 377 | if ((c->input = sshbuf_new()) == NULL || |
339 | buffer_init(&c->output); | 378 | (c->output = sshbuf_new()) == NULL || |
340 | buffer_init(&c->extended); | 379 | (c->extended = sshbuf_new()) == NULL) |
341 | c->path = NULL; | 380 | fatal("%s: sshbuf_new failed", __func__); |
342 | c->listening_addr = NULL; | ||
343 | c->listening_port = 0; | ||
344 | c->ostate = CHAN_OUTPUT_OPEN; | 381 | c->ostate = CHAN_OUTPUT_OPEN; |
345 | c->istate = CHAN_INPUT_OPEN; | 382 | c->istate = CHAN_INPUT_OPEN; |
346 | c->flags = 0; | 383 | channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0); |
347 | channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0); | ||
348 | c->notbefore = 0; | ||
349 | c->self = found; | 384 | c->self = found; |
350 | c->type = type; | 385 | c->type = type; |
351 | c->ctype = ctype; | 386 | c->ctype = ctype; |
352 | c->local_window = window; | 387 | c->local_window = window; |
353 | c->local_window_max = window; | 388 | c->local_window_max = window; |
354 | c->local_consumed = 0; | ||
355 | c->local_maxpacket = maxpack; | 389 | c->local_maxpacket = maxpack; |
356 | c->remote_id = -1; | 390 | c->remote_id = -1; |
357 | c->remote_name = xstrdup(remote_name); | 391 | c->remote_name = xstrdup(remote_name); |
358 | c->remote_window = 0; | ||
359 | c->remote_maxpacket = 0; | ||
360 | c->force_drain = 0; | ||
361 | c->single_connection = 0; | ||
362 | c->detach_user = NULL; | ||
363 | c->detach_close = 0; | ||
364 | c->open_confirm = NULL; | ||
365 | c->open_confirm_ctx = NULL; | ||
366 | c->input_filter = NULL; | ||
367 | c->output_filter = NULL; | ||
368 | c->filter_ctx = NULL; | ||
369 | c->filter_cleanup = NULL; | ||
370 | c->ctl_chan = -1; | 392 | c->ctl_chan = -1; |
371 | c->mux_rcb = NULL; | ||
372 | c->mux_ctx = NULL; | ||
373 | c->mux_pause = 0; | ||
374 | c->delayed = 1; /* prevent call to channel_post handler */ | 393 | c->delayed = 1; /* prevent call to channel_post handler */ |
375 | TAILQ_INIT(&c->status_confirms); | 394 | TAILQ_INIT(&c->status_confirms); |
376 | debug("channel %d: new [%s]", found, remote_name); | 395 | debug("channel %d: new [%s]", found, remote_name); |
377 | return c; | 396 | return c; |
378 | } | 397 | } |
379 | 398 | ||
380 | static int | 399 | static void |
381 | channel_find_maxfd(void) | 400 | channel_find_maxfd(struct ssh_channels *sc) |
382 | { | 401 | { |
383 | u_int i; | 402 | u_int i; |
384 | int max = 0; | 403 | int max = 0; |
385 | Channel *c; | 404 | Channel *c; |
386 | 405 | ||
387 | for (i = 0; i < channels_alloc; i++) { | 406 | for (i = 0; i < sc->channels_alloc; i++) { |
388 | c = channels[i]; | 407 | c = sc->channels[i]; |
389 | if (c != NULL) { | 408 | if (c != NULL) { |
390 | max = MAXIMUM(max, c->rfd); | 409 | max = MAXIMUM(max, c->rfd); |
391 | max = MAXIMUM(max, c->wfd); | 410 | max = MAXIMUM(max, c->wfd); |
392 | max = MAXIMUM(max, c->efd); | 411 | max = MAXIMUM(max, c->efd); |
393 | } | 412 | } |
394 | } | 413 | } |
395 | return max; | 414 | sc->channel_max_fd = max; |
396 | } | 415 | } |
397 | 416 | ||
398 | int | 417 | int |
399 | channel_close_fd(int *fdp) | 418 | channel_close_fd(struct ssh *ssh, int *fdp) |
400 | { | 419 | { |
420 | struct ssh_channels *sc = ssh->chanctxt; | ||
401 | int ret = 0, fd = *fdp; | 421 | int ret = 0, fd = *fdp; |
402 | 422 | ||
403 | if (fd != -1) { | 423 | if (fd != -1) { |
404 | ret = close(fd); | 424 | ret = close(fd); |
405 | *fdp = -1; | 425 | *fdp = -1; |
406 | if (fd == channel_max_fd) | 426 | if (fd == sc->channel_max_fd) |
407 | channel_max_fd = channel_find_maxfd(); | 427 | channel_find_maxfd(sc); |
408 | } | 428 | } |
409 | return ret; | 429 | return ret; |
410 | } | 430 | } |
411 | 431 | ||
412 | /* Close all channel fd/socket. */ | 432 | /* Close all channel fd/socket. */ |
413 | static void | 433 | static void |
414 | channel_close_fds(Channel *c) | 434 | channel_close_fds(struct ssh *ssh, Channel *c) |
435 | { | ||
436 | channel_close_fd(ssh, &c->sock); | ||
437 | channel_close_fd(ssh, &c->rfd); | ||
438 | channel_close_fd(ssh, &c->wfd); | ||
439 | channel_close_fd(ssh, &c->efd); | ||
440 | } | ||
441 | |||
442 | static void | ||
443 | fwd_perm_clear(ForwardPermission *fp) | ||
444 | { | ||
445 | free(fp->host_to_connect); | ||
446 | free(fp->listen_host); | ||
447 | free(fp->listen_path); | ||
448 | bzero(fp, sizeof(*fp)); | ||
449 | } | ||
450 | |||
451 | enum { FWDPERM_USER, FWDPERM_ADMIN }; | ||
452 | |||
453 | static int | ||
454 | fwd_perm_list_add(struct ssh *ssh, int which, | ||
455 | const char *host_to_connect, int port_to_connect, | ||
456 | const char *listen_host, const char *listen_path, int listen_port, | ||
457 | Channel *downstream) | ||
458 | { | ||
459 | ForwardPermission **fpl; | ||
460 | u_int n, *nfpl; | ||
461 | |||
462 | switch (which) { | ||
463 | case FWDPERM_USER: | ||
464 | fpl = &ssh->chanctxt->permitted_opens; | ||
465 | nfpl = &ssh->chanctxt->num_permitted_opens; | ||
466 | break; | ||
467 | case FWDPERM_ADMIN: | ||
468 | fpl = &ssh->chanctxt->permitted_adm_opens; | ||
469 | nfpl = &ssh->chanctxt->num_adm_permitted_opens; | ||
470 | break; | ||
471 | default: | ||
472 | fatal("%s: invalid list %d", __func__, which); | ||
473 | } | ||
474 | |||
475 | if (*nfpl >= INT_MAX) | ||
476 | fatal("%s: overflow", __func__); | ||
477 | |||
478 | *fpl = xrecallocarray(*fpl, *nfpl, *nfpl + 1, sizeof(**fpl)); | ||
479 | n = (*nfpl)++; | ||
480 | #define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s)) | ||
481 | (*fpl)[n].host_to_connect = MAYBE_DUP(host_to_connect); | ||
482 | (*fpl)[n].port_to_connect = port_to_connect; | ||
483 | (*fpl)[n].listen_host = MAYBE_DUP(listen_host); | ||
484 | (*fpl)[n].listen_path = MAYBE_DUP(listen_path); | ||
485 | (*fpl)[n].listen_port = listen_port; | ||
486 | (*fpl)[n].downstream = downstream; | ||
487 | #undef MAYBE_DUP | ||
488 | return (int)n; | ||
489 | } | ||
490 | |||
491 | static void | ||
492 | mux_remove_remote_forwardings(struct ssh *ssh, Channel *c) | ||
415 | { | 493 | { |
416 | channel_close_fd(&c->sock); | 494 | struct ssh_channels *sc = ssh->chanctxt; |
417 | channel_close_fd(&c->rfd); | 495 | ForwardPermission *fp; |
418 | channel_close_fd(&c->wfd); | 496 | int r; |
419 | channel_close_fd(&c->efd); | 497 | u_int i; |
498 | |||
499 | for (i = 0; i < sc->num_permitted_opens; i++) { | ||
500 | fp = &sc->permitted_opens[i]; | ||
501 | if (fp->downstream != c) | ||
502 | continue; | ||
503 | |||
504 | /* cancel on the server, since mux client is gone */ | ||
505 | debug("channel %d: cleanup remote forward for %s:%u", | ||
506 | c->self, fp->listen_host, fp->listen_port); | ||
507 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || | ||
508 | (r = sshpkt_put_cstring(ssh, | ||
509 | "cancel-tcpip-forward")) != 0 || | ||
510 | (r = sshpkt_put_u8(ssh, 0)) != 0 || | ||
511 | (r = sshpkt_put_cstring(ssh, | ||
512 | channel_rfwd_bind_host(fp->listen_host))) != 0 || | ||
513 | (r = sshpkt_put_u32(ssh, fp->listen_port)) != 0 || | ||
514 | (r = sshpkt_send(ssh)) != 0) { | ||
515 | fatal("%s: channel %i: %s", __func__, | ||
516 | c->self, ssh_err(r)); | ||
517 | } | ||
518 | fwd_perm_clear(fp); /* unregister */ | ||
519 | } | ||
420 | } | 520 | } |
421 | 521 | ||
422 | /* Free the channel and close its fd/socket. */ | 522 | /* Free the channel and close its fd/socket. */ |
423 | void | 523 | void |
424 | channel_free(Channel *c) | 524 | channel_free(struct ssh *ssh, Channel *c) |
425 | { | 525 | { |
526 | struct ssh_channels *sc = ssh->chanctxt; | ||
426 | char *s; | 527 | char *s; |
427 | u_int i, n; | 528 | u_int i, n; |
428 | Channel *other; | 529 | Channel *other; |
429 | struct channel_confirm *cc; | 530 | struct channel_confirm *cc; |
430 | 531 | ||
431 | for (n = 0, i = 0; i < channels_alloc; i++) { | 532 | for (n = 0, i = 0; i < sc->channels_alloc; i++) { |
432 | if ((other = channels[i]) != NULL) { | 533 | if ((other = sc->channels[i]) == NULL) |
433 | n++; | 534 | continue; |
434 | 535 | n++; | |
435 | /* detach from mux client and prepare for closing */ | 536 | /* detach from mux client and prepare for closing */ |
436 | if (c->type == SSH_CHANNEL_MUX_CLIENT && | 537 | if (c->type == SSH_CHANNEL_MUX_CLIENT && |
437 | other->type == SSH_CHANNEL_MUX_PROXY && | 538 | other->type == SSH_CHANNEL_MUX_PROXY && |
438 | other->mux_ctx == c) { | 539 | other->mux_ctx == c) { |
439 | other->mux_ctx = NULL; | 540 | other->mux_ctx = NULL; |
440 | other->type = SSH_CHANNEL_OPEN; | 541 | other->type = SSH_CHANNEL_OPEN; |
441 | other->istate = CHAN_INPUT_CLOSED; | 542 | other->istate = CHAN_INPUT_CLOSED; |
442 | other->ostate = CHAN_OUTPUT_CLOSED; | 543 | other->ostate = CHAN_OUTPUT_CLOSED; |
443 | } | ||
444 | } | 544 | } |
445 | } | 545 | } |
446 | debug("channel %d: free: %s, nchannels %u", c->self, | 546 | debug("channel %d: free: %s, nchannels %u", c->self, |
447 | c->remote_name ? c->remote_name : "???", n); | 547 | c->remote_name ? c->remote_name : "???", n); |
448 | 548 | ||
449 | /* XXX more MUX cleanup: remove remote forwardings */ | 549 | if (c->type == SSH_CHANNEL_MUX_CLIENT) |
450 | if (c->type == SSH_CHANNEL_MUX_CLIENT) { | 550 | mux_remove_remote_forwardings(ssh, c); |
451 | for (i = 0; i < (u_int)num_permitted_opens; i++) { | ||
452 | if (permitted_opens[i].downstream != c) | ||
453 | continue; | ||
454 | /* cancel on the server, since mux client is gone */ | ||
455 | debug("channel %d: cleanup remote forward for %s:%u", | ||
456 | c->self, | ||
457 | permitted_opens[i].listen_host, | ||
458 | permitted_opens[i].listen_port); | ||
459 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | ||
460 | packet_put_cstring("cancel-tcpip-forward"); | ||
461 | packet_put_char(0); | ||
462 | packet_put_cstring(channel_rfwd_bind_host( | ||
463 | permitted_opens[i].listen_host)); | ||
464 | packet_put_int(permitted_opens[i].listen_port); | ||
465 | packet_send(); | ||
466 | /* unregister */ | ||
467 | permitted_opens[i].listen_port = 0; | ||
468 | permitted_opens[i].port_to_connect = 0; | ||
469 | free(permitted_opens[i].host_to_connect); | ||
470 | permitted_opens[i].host_to_connect = NULL; | ||
471 | free(permitted_opens[i].listen_host); | ||
472 | permitted_opens[i].listen_host = NULL; | ||
473 | permitted_opens[i].listen_path = NULL; | ||
474 | permitted_opens[i].downstream = NULL; | ||
475 | } | ||
476 | } | ||
477 | 551 | ||
478 | s = channel_open_message(); | 552 | s = channel_open_message(ssh); |
479 | debug3("channel %d: status: %s", c->self, s); | 553 | debug3("channel %d: status: %s", c->self, s); |
480 | free(s); | 554 | free(s); |
481 | 555 | ||
482 | channel_close_fds(c); | 556 | channel_close_fds(ssh, c); |
483 | buffer_free(&c->input); | 557 | sshbuf_free(c->input); |
484 | buffer_free(&c->output); | 558 | sshbuf_free(c->output); |
485 | buffer_free(&c->extended); | 559 | sshbuf_free(c->extended); |
560 | c->input = c->output = c->extended = NULL; | ||
486 | free(c->remote_name); | 561 | free(c->remote_name); |
487 | c->remote_name = NULL; | 562 | c->remote_name = NULL; |
488 | free(c->path); | 563 | free(c->path); |
@@ -491,25 +566,26 @@ channel_free(Channel *c) | |||
491 | c->listening_addr = NULL; | 566 | c->listening_addr = NULL; |
492 | while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { | 567 | while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) { |
493 | if (cc->abandon_cb != NULL) | 568 | if (cc->abandon_cb != NULL) |
494 | cc->abandon_cb(c, cc->ctx); | 569 | cc->abandon_cb(ssh, c, cc->ctx); |
495 | TAILQ_REMOVE(&c->status_confirms, cc, entry); | 570 | TAILQ_REMOVE(&c->status_confirms, cc, entry); |
496 | explicit_bzero(cc, sizeof(*cc)); | 571 | explicit_bzero(cc, sizeof(*cc)); |
497 | free(cc); | 572 | free(cc); |
498 | } | 573 | } |
499 | if (c->filter_cleanup != NULL && c->filter_ctx != NULL) | 574 | if (c->filter_cleanup != NULL && c->filter_ctx != NULL) |
500 | c->filter_cleanup(c->self, c->filter_ctx); | 575 | c->filter_cleanup(ssh, c->self, c->filter_ctx); |
501 | channels[c->self] = NULL; | 576 | sc->channels[c->self] = NULL; |
577 | bzero(c, sizeof(*c)); | ||
502 | free(c); | 578 | free(c); |
503 | } | 579 | } |
504 | 580 | ||
505 | void | 581 | void |
506 | channel_free_all(void) | 582 | channel_free_all(struct ssh *ssh) |
507 | { | 583 | { |
508 | u_int i; | 584 | u_int i; |
509 | 585 | ||
510 | for (i = 0; i < channels_alloc; i++) | 586 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) |
511 | if (channels[i] != NULL) | 587 | if (ssh->chanctxt->channels[i] != NULL) |
512 | channel_free(channels[i]); | 588 | channel_free(ssh, ssh->chanctxt->channels[i]); |
513 | } | 589 | } |
514 | 590 | ||
515 | /* | 591 | /* |
@@ -517,26 +593,26 @@ channel_free_all(void) | |||
517 | * descriptors after a fork. | 593 | * descriptors after a fork. |
518 | */ | 594 | */ |
519 | void | 595 | void |
520 | channel_close_all(void) | 596 | channel_close_all(struct ssh *ssh) |
521 | { | 597 | { |
522 | u_int i; | 598 | u_int i; |
523 | 599 | ||
524 | for (i = 0; i < channels_alloc; i++) | 600 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) |
525 | if (channels[i] != NULL) | 601 | if (ssh->chanctxt->channels[i] != NULL) |
526 | channel_close_fds(channels[i]); | 602 | channel_close_fds(ssh, ssh->chanctxt->channels[i]); |
527 | } | 603 | } |
528 | 604 | ||
529 | /* | 605 | /* |
530 | * Stop listening to channels. | 606 | * Stop listening to channels. |
531 | */ | 607 | */ |
532 | void | 608 | void |
533 | channel_stop_listening(void) | 609 | channel_stop_listening(struct ssh *ssh) |
534 | { | 610 | { |
535 | u_int i; | 611 | u_int i; |
536 | Channel *c; | 612 | Channel *c; |
537 | 613 | ||
538 | for (i = 0; i < channels_alloc; i++) { | 614 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
539 | c = channels[i]; | 615 | c = ssh->chanctxt->channels[i]; |
540 | if (c != NULL) { | 616 | if (c != NULL) { |
541 | switch (c->type) { | 617 | switch (c->type) { |
542 | case SSH_CHANNEL_AUTH_SOCKET: | 618 | case SSH_CHANNEL_AUTH_SOCKET: |
@@ -545,8 +621,8 @@ channel_stop_listening(void) | |||
545 | case SSH_CHANNEL_X11_LISTENER: | 621 | case SSH_CHANNEL_X11_LISTENER: |
546 | case SSH_CHANNEL_UNIX_LISTENER: | 622 | case SSH_CHANNEL_UNIX_LISTENER: |
547 | case SSH_CHANNEL_RUNIX_LISTENER: | 623 | case SSH_CHANNEL_RUNIX_LISTENER: |
548 | channel_close_fd(&c->sock); | 624 | channel_close_fd(ssh, &c->sock); |
549 | channel_free(c); | 625 | channel_free(ssh, c); |
550 | break; | 626 | break; |
551 | } | 627 | } |
552 | } | 628 | } |
@@ -558,20 +634,20 @@ channel_stop_listening(void) | |||
558 | * more channel is overfull. | 634 | * more channel is overfull. |
559 | */ | 635 | */ |
560 | int | 636 | int |
561 | channel_not_very_much_buffered_data(void) | 637 | channel_not_very_much_buffered_data(struct ssh *ssh) |
562 | { | 638 | { |
563 | u_int i; | 639 | u_int i; |
640 | u_int maxsize = ssh_packet_get_maxsize(ssh); | ||
564 | Channel *c; | 641 | Channel *c; |
565 | 642 | ||
566 | for (i = 0; i < channels_alloc; i++) { | 643 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
567 | c = channels[i]; | 644 | c = ssh->chanctxt->channels[i]; |
568 | if (c != NULL && c->type == SSH_CHANNEL_OPEN) { | 645 | if (c == NULL || c->type != SSH_CHANNEL_OPEN) |
569 | if (buffer_len(&c->output) > packet_get_maxsize()) { | 646 | continue; |
570 | debug2("channel %d: big output buffer %u > %u", | 647 | if (sshbuf_len(c->output) > maxsize) { |
571 | c->self, buffer_len(&c->output), | 648 | debug2("channel %d: big output buffer %zu > %u", |
572 | packet_get_maxsize()); | 649 | c->self, sshbuf_len(c->output), maxsize); |
573 | return 0; | 650 | return 0; |
574 | } | ||
575 | } | 651 | } |
576 | } | 652 | } |
577 | return 1; | 653 | return 1; |
@@ -579,13 +655,13 @@ channel_not_very_much_buffered_data(void) | |||
579 | 655 | ||
580 | /* Returns true if any channel is still open. */ | 656 | /* Returns true if any channel is still open. */ |
581 | int | 657 | int |
582 | channel_still_open(void) | 658 | channel_still_open(struct ssh *ssh) |
583 | { | 659 | { |
584 | u_int i; | 660 | u_int i; |
585 | Channel *c; | 661 | Channel *c; |
586 | 662 | ||
587 | for (i = 0; i < channels_alloc; i++) { | 663 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
588 | c = channels[i]; | 664 | c = ssh->chanctxt->channels[i]; |
589 | if (c == NULL) | 665 | if (c == NULL) |
590 | continue; | 666 | continue; |
591 | switch (c->type) { | 667 | switch (c->type) { |
@@ -620,13 +696,13 @@ channel_still_open(void) | |||
620 | 696 | ||
621 | /* Returns the id of an open channel suitable for keepaliving */ | 697 | /* Returns the id of an open channel suitable for keepaliving */ |
622 | int | 698 | int |
623 | channel_find_open(void) | 699 | channel_find_open(struct ssh *ssh) |
624 | { | 700 | { |
625 | u_int i; | 701 | u_int i; |
626 | Channel *c; | 702 | Channel *c; |
627 | 703 | ||
628 | for (i = 0; i < channels_alloc; i++) { | 704 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
629 | c = channels[i]; | 705 | c = ssh->chanctxt->channels[i]; |
630 | if (c == NULL || c->remote_id < 0) | 706 | if (c == NULL || c->remote_id < 0) |
631 | continue; | 707 | continue; |
632 | switch (c->type) { | 708 | switch (c->type) { |
@@ -664,18 +740,21 @@ channel_find_open(void) | |||
664 | * newlines. | 740 | * newlines. |
665 | */ | 741 | */ |
666 | char * | 742 | char * |
667 | channel_open_message(void) | 743 | channel_open_message(struct ssh *ssh) |
668 | { | 744 | { |
669 | Buffer buffer; | 745 | struct sshbuf *buf; |
670 | Channel *c; | 746 | Channel *c; |
671 | char buf[1024], *cp; | ||
672 | u_int i; | 747 | u_int i; |
673 | 748 | int r; | |
674 | buffer_init(&buffer); | 749 | char *ret; |
675 | snprintf(buf, sizeof buf, "The following connections are open:\r\n"); | 750 | |
676 | buffer_append(&buffer, buf, strlen(buf)); | 751 | if ((buf = sshbuf_new()) == NULL) |
677 | for (i = 0; i < channels_alloc; i++) { | 752 | fatal("%s: sshbuf_new", __func__); |
678 | c = channels[i]; | 753 | if ((r = sshbuf_putf(buf, |
754 | "The following connections are open:\r\n")) != 0) | ||
755 | fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); | ||
756 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { | ||
757 | c = ssh->chanctxt->channels[i]; | ||
679 | if (c == NULL) | 758 | if (c == NULL) |
680 | continue; | 759 | continue; |
681 | switch (c->type) { | 760 | switch (c->type) { |
@@ -698,69 +777,85 @@ channel_open_message(void) | |||
698 | case SSH_CHANNEL_X11_OPEN: | 777 | case SSH_CHANNEL_X11_OPEN: |
699 | case SSH_CHANNEL_MUX_PROXY: | 778 | case SSH_CHANNEL_MUX_PROXY: |
700 | case SSH_CHANNEL_MUX_CLIENT: | 779 | case SSH_CHANNEL_MUX_CLIENT: |
701 | snprintf(buf, sizeof buf, | 780 | if ((r = sshbuf_putf(buf, " #%d %.300s " |
702 | " #%d %.300s (t%d r%d i%u/%d o%u/%d fd %d/%d cc %d)\r\n", | 781 | "(t%d r%d i%u/%zu o%u/%zu fd %d/%d cc %d)\r\n", |
703 | c->self, c->remote_name, | 782 | c->self, c->remote_name, |
704 | c->type, c->remote_id, | 783 | c->type, c->remote_id, |
705 | c->istate, buffer_len(&c->input), | 784 | c->istate, sshbuf_len(c->input), |
706 | c->ostate, buffer_len(&c->output), | 785 | c->ostate, sshbuf_len(c->output), |
707 | c->rfd, c->wfd, c->ctl_chan); | 786 | c->rfd, c->wfd, c->ctl_chan)) != 0) |
708 | buffer_append(&buffer, buf, strlen(buf)); | 787 | fatal("%s: sshbuf_putf: %s", |
788 | __func__, ssh_err(r)); | ||
709 | continue; | 789 | continue; |
710 | default: | 790 | default: |
711 | fatal("channel_open_message: bad channel type %d", c->type); | 791 | fatal("%s: bad channel type %d", __func__, c->type); |
712 | /* NOTREACHED */ | 792 | /* NOTREACHED */ |
713 | } | 793 | } |
714 | } | 794 | } |
715 | buffer_append(&buffer, "\0", 1); | 795 | if ((ret = sshbuf_dup_string(buf)) == NULL) |
716 | cp = xstrdup((char *)buffer_ptr(&buffer)); | 796 | fatal("%s: sshbuf_dup_string", __func__); |
717 | buffer_free(&buffer); | 797 | sshbuf_free(buf); |
718 | return cp; | 798 | return ret; |
799 | } | ||
800 | |||
801 | static void | ||
802 | open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type) | ||
803 | { | ||
804 | int r; | ||
805 | |||
806 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 || | ||
807 | (r = sshpkt_put_cstring(ssh, type)) != 0 || | ||
808 | (r = sshpkt_put_u32(ssh, c->self)) != 0 || | ||
809 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || | ||
810 | (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) { | ||
811 | fatal("%s: channel %i: open: %s", where, c->self, ssh_err(r)); | ||
812 | } | ||
719 | } | 813 | } |
720 | 814 | ||
721 | void | 815 | void |
722 | channel_send_open(int id) | 816 | channel_send_open(struct ssh *ssh, int id) |
723 | { | 817 | { |
724 | Channel *c = channel_lookup(id); | 818 | Channel *c = channel_lookup(ssh, id); |
819 | int r; | ||
725 | 820 | ||
726 | if (c == NULL) { | 821 | if (c == NULL) { |
727 | logit("channel_send_open: %d: bad id", id); | 822 | logit("channel_send_open: %d: bad id", id); |
728 | return; | 823 | return; |
729 | } | 824 | } |
730 | debug2("channel %d: send open", id); | 825 | debug2("channel %d: send open", id); |
731 | packet_start(SSH2_MSG_CHANNEL_OPEN); | 826 | open_preamble(ssh, __func__, c, c->ctype); |
732 | packet_put_cstring(c->ctype); | 827 | if ((r = sshpkt_send(ssh)) != 0) |
733 | packet_put_int(c->self); | 828 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); |
734 | packet_put_int(c->local_window); | ||
735 | packet_put_int(c->local_maxpacket); | ||
736 | packet_send(); | ||
737 | } | 829 | } |
738 | 830 | ||
739 | void | 831 | void |
740 | channel_request_start(int id, char *service, int wantconfirm) | 832 | channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm) |
741 | { | 833 | { |
742 | Channel *c = channel_lookup(id); | 834 | Channel *c = channel_lookup(ssh, id); |
835 | int r; | ||
743 | 836 | ||
744 | if (c == NULL) { | 837 | if (c == NULL) { |
745 | logit("channel_request_start: %d: unknown channel id", id); | 838 | logit("%s: %d: unknown channel id", __func__, id); |
746 | return; | 839 | return; |
747 | } | 840 | } |
748 | debug2("channel %d: request %s confirm %d", id, service, wantconfirm); | 841 | debug2("channel %d: request %s confirm %d", id, service, wantconfirm); |
749 | packet_start(SSH2_MSG_CHANNEL_REQUEST); | 842 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || |
750 | packet_put_int(c->remote_id); | 843 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
751 | packet_put_cstring(service); | 844 | (r = sshpkt_put_cstring(ssh, service)) != 0 || |
752 | packet_put_char(wantconfirm); | 845 | (r = sshpkt_put_u8(ssh, wantconfirm)) != 0) { |
846 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | ||
847 | } | ||
753 | } | 848 | } |
754 | 849 | ||
755 | void | 850 | void |
756 | channel_register_status_confirm(int id, channel_confirm_cb *cb, | 851 | channel_register_status_confirm(struct ssh *ssh, int id, |
757 | channel_confirm_abandon_cb *abandon_cb, void *ctx) | 852 | channel_confirm_cb *cb, channel_confirm_abandon_cb *abandon_cb, void *ctx) |
758 | { | 853 | { |
759 | struct channel_confirm *cc; | 854 | struct channel_confirm *cc; |
760 | Channel *c; | 855 | Channel *c; |
761 | 856 | ||
762 | if ((c = channel_lookup(id)) == NULL) | 857 | if ((c = channel_lookup(ssh, id)) == NULL) |
763 | fatal("channel_register_expect: %d: bad id", id); | 858 | fatal("%s: %d: bad id", __func__, id); |
764 | 859 | ||
765 | cc = xcalloc(1, sizeof(*cc)); | 860 | cc = xcalloc(1, sizeof(*cc)); |
766 | cc->cb = cb; | 861 | cc->cb = cb; |
@@ -770,12 +865,13 @@ channel_register_status_confirm(int id, channel_confirm_cb *cb, | |||
770 | } | 865 | } |
771 | 866 | ||
772 | void | 867 | void |
773 | channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx) | 868 | channel_register_open_confirm(struct ssh *ssh, int id, |
869 | channel_open_fn *fn, void *ctx) | ||
774 | { | 870 | { |
775 | Channel *c = channel_lookup(id); | 871 | Channel *c = channel_lookup(ssh, id); |
776 | 872 | ||
777 | if (c == NULL) { | 873 | if (c == NULL) { |
778 | logit("channel_register_open_confirm: %d: bad id", id); | 874 | logit("%s: %d: bad id", __func__, id); |
779 | return; | 875 | return; |
780 | } | 876 | } |
781 | c->open_confirm = fn; | 877 | c->open_confirm = fn; |
@@ -783,12 +879,13 @@ channel_register_open_confirm(int id, channel_open_fn *fn, void *ctx) | |||
783 | } | 879 | } |
784 | 880 | ||
785 | void | 881 | void |
786 | channel_register_cleanup(int id, channel_callback_fn *fn, int do_close) | 882 | channel_register_cleanup(struct ssh *ssh, int id, |
883 | channel_callback_fn *fn, int do_close) | ||
787 | { | 884 | { |
788 | Channel *c = channel_by_id(id); | 885 | Channel *c = channel_by_id(ssh, id); |
789 | 886 | ||
790 | if (c == NULL) { | 887 | if (c == NULL) { |
791 | logit("channel_register_cleanup: %d: bad id", id); | 888 | logit("%s: %d: bad id", __func__, id); |
792 | return; | 889 | return; |
793 | } | 890 | } |
794 | c->detach_user = fn; | 891 | c->detach_user = fn; |
@@ -796,12 +893,12 @@ channel_register_cleanup(int id, channel_callback_fn *fn, int do_close) | |||
796 | } | 893 | } |
797 | 894 | ||
798 | void | 895 | void |
799 | channel_cancel_cleanup(int id) | 896 | channel_cancel_cleanup(struct ssh *ssh, int id) |
800 | { | 897 | { |
801 | Channel *c = channel_by_id(id); | 898 | Channel *c = channel_by_id(ssh, id); |
802 | 899 | ||
803 | if (c == NULL) { | 900 | if (c == NULL) { |
804 | logit("channel_cancel_cleanup: %d: bad id", id); | 901 | logit("%s: %d: bad id", __func__, id); |
805 | return; | 902 | return; |
806 | } | 903 | } |
807 | c->detach_user = NULL; | 904 | c->detach_user = NULL; |
@@ -809,13 +906,13 @@ channel_cancel_cleanup(int id) | |||
809 | } | 906 | } |
810 | 907 | ||
811 | void | 908 | void |
812 | channel_register_filter(int id, channel_infilter_fn *ifn, | 909 | channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn, |
813 | channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx) | 910 | channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx) |
814 | { | 911 | { |
815 | Channel *c = channel_lookup(id); | 912 | Channel *c = channel_lookup(ssh, id); |
816 | 913 | ||
817 | if (c == NULL) { | 914 | if (c == NULL) { |
818 | logit("channel_register_filter: %d: bad id", id); | 915 | logit("%s: %d: bad id", __func__, id); |
819 | return; | 916 | return; |
820 | } | 917 | } |
821 | c->input_filter = ifn; | 918 | c->input_filter = ifn; |
@@ -825,79 +922,72 @@ channel_register_filter(int id, channel_infilter_fn *ifn, | |||
825 | } | 922 | } |
826 | 923 | ||
827 | void | 924 | void |
828 | channel_set_fds(int id, int rfd, int wfd, int efd, | 925 | channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd, |
829 | int extusage, int nonblock, int is_tty, u_int window_max) | 926 | int extusage, int nonblock, int is_tty, u_int window_max) |
830 | { | 927 | { |
831 | Channel *c = channel_lookup(id); | 928 | Channel *c = channel_lookup(ssh, id); |
929 | int r; | ||
832 | 930 | ||
833 | if (c == NULL || c->type != SSH_CHANNEL_LARVAL) | 931 | if (c == NULL || c->type != SSH_CHANNEL_LARVAL) |
834 | fatal("channel_activate for non-larval channel %d.", id); | 932 | fatal("channel_activate for non-larval channel %d.", id); |
835 | channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty); | 933 | channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); |
836 | c->type = SSH_CHANNEL_OPEN; | 934 | c->type = SSH_CHANNEL_OPEN; |
837 | c->local_window = c->local_window_max = window_max; | 935 | c->local_window = c->local_window_max = window_max; |
838 | packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); | ||
839 | packet_put_int(c->remote_id); | ||
840 | packet_put_int(c->local_window); | ||
841 | packet_send(); | ||
842 | } | ||
843 | 936 | ||
844 | /* | 937 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || |
845 | * 'channel_pre*' are called just before select() to add any bits relevant to | 938 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
846 | * channels in the select bitmasks. | 939 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || |
847 | */ | 940 | (r = sshpkt_send(ssh)) != 0) |
848 | /* | 941 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); |
849 | * 'channel_post*': perform any appropriate operations for channels which | 942 | } |
850 | * have events pending. | ||
851 | */ | ||
852 | typedef void chan_fn(Channel *c, fd_set *readset, fd_set *writeset); | ||
853 | chan_fn *channel_pre[SSH_CHANNEL_MAX_TYPE]; | ||
854 | chan_fn *channel_post[SSH_CHANNEL_MAX_TYPE]; | ||
855 | 943 | ||
856 | /* ARGSUSED */ | ||
857 | static void | 944 | static void |
858 | channel_pre_listener(Channel *c, fd_set *readset, fd_set *writeset) | 945 | channel_pre_listener(struct ssh *ssh, Channel *c, |
946 | fd_set *readset, fd_set *writeset) | ||
859 | { | 947 | { |
860 | FD_SET(c->sock, readset); | 948 | FD_SET(c->sock, readset); |
861 | } | 949 | } |
862 | 950 | ||
863 | /* ARGSUSED */ | ||
864 | static void | 951 | static void |
865 | channel_pre_connecting(Channel *c, fd_set *readset, fd_set *writeset) | 952 | channel_pre_connecting(struct ssh *ssh, Channel *c, |
953 | fd_set *readset, fd_set *writeset) | ||
866 | { | 954 | { |
867 | debug3("channel %d: waiting for connection", c->self); | 955 | debug3("channel %d: waiting for connection", c->self); |
868 | FD_SET(c->sock, writeset); | 956 | FD_SET(c->sock, writeset); |
869 | } | 957 | } |
870 | 958 | ||
871 | static void | 959 | static void |
872 | channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) | 960 | channel_pre_open(struct ssh *ssh, Channel *c, |
961 | fd_set *readset, fd_set *writeset) | ||
873 | { | 962 | { |
874 | if (c->istate == CHAN_INPUT_OPEN && | 963 | if (c->istate == CHAN_INPUT_OPEN && |
875 | c->remote_window > 0 && | 964 | c->remote_window > 0 && |
876 | buffer_len(&c->input) < c->remote_window && | 965 | sshbuf_len(c->input) < c->remote_window && |
877 | buffer_check_alloc(&c->input, CHAN_RBUF)) | 966 | sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) |
878 | FD_SET(c->rfd, readset); | 967 | FD_SET(c->rfd, readset); |
879 | if (c->ostate == CHAN_OUTPUT_OPEN || | 968 | if (c->ostate == CHAN_OUTPUT_OPEN || |
880 | c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { | 969 | c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
881 | if (buffer_len(&c->output) > 0) { | 970 | if (sshbuf_len(c->output) > 0) { |
882 | FD_SET(c->wfd, writeset); | 971 | FD_SET(c->wfd, writeset); |
883 | } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { | 972 | } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
884 | if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) | 973 | if (CHANNEL_EFD_OUTPUT_ACTIVE(c)) |
885 | debug2("channel %d: obuf_empty delayed efd %d/(%d)", | 974 | debug2("channel %d: " |
886 | c->self, c->efd, buffer_len(&c->extended)); | 975 | "obuf_empty delayed efd %d/(%zu)", c->self, |
976 | c->efd, sshbuf_len(c->extended)); | ||
887 | else | 977 | else |
888 | chan_obuf_empty(c); | 978 | chan_obuf_empty(ssh, c); |
889 | } | 979 | } |
890 | } | 980 | } |
891 | /** XXX check close conditions, too */ | 981 | /** XXX check close conditions, too */ |
892 | if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED && | 982 | if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED && |
893 | c->ostate == CHAN_OUTPUT_CLOSED)) { | 983 | c->ostate == CHAN_OUTPUT_CLOSED)) { |
894 | if (c->extended_usage == CHAN_EXTENDED_WRITE && | 984 | if (c->extended_usage == CHAN_EXTENDED_WRITE && |
895 | buffer_len(&c->extended) > 0) | 985 | sshbuf_len(c->extended) > 0) |
896 | FD_SET(c->efd, writeset); | 986 | FD_SET(c->efd, writeset); |
897 | else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) && | 987 | else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) && |
898 | (c->extended_usage == CHAN_EXTENDED_READ || | 988 | (c->extended_usage == CHAN_EXTENDED_READ || |
899 | c->extended_usage == CHAN_EXTENDED_IGNORE) && | 989 | c->extended_usage == CHAN_EXTENDED_IGNORE) && |
900 | buffer_len(&c->extended) < c->remote_window) | 990 | sshbuf_len(c->extended) < c->remote_window) |
901 | FD_SET(c->efd, readset); | 991 | FD_SET(c->efd, readset); |
902 | } | 992 | } |
903 | /* XXX: What about efd? races? */ | 993 | /* XXX: What about efd? races? */ |
@@ -913,24 +1003,26 @@ channel_pre_open(Channel *c, fd_set *readset, fd_set *writeset) | |||
913 | * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok | 1003 | * Returns: 0 = need more data, -1 = wrong cookie, 1 = ok |
914 | */ | 1004 | */ |
915 | static int | 1005 | static int |
916 | x11_open_helper(Buffer *b) | 1006 | x11_open_helper(struct ssh *ssh, struct sshbuf *b) |
917 | { | 1007 | { |
1008 | struct ssh_channels *sc = ssh->chanctxt; | ||
918 | u_char *ucp; | 1009 | u_char *ucp; |
919 | u_int proto_len, data_len; | 1010 | u_int proto_len, data_len; |
920 | 1011 | ||
921 | /* Is this being called after the refusal deadline? */ | 1012 | /* Is this being called after the refusal deadline? */ |
922 | if (x11_refuse_time != 0 && (u_int)monotime() >= x11_refuse_time) { | 1013 | if (sc->x11_refuse_time != 0 && |
1014 | (u_int)monotime() >= sc->x11_refuse_time) { | ||
923 | verbose("Rejected X11 connection after ForwardX11Timeout " | 1015 | verbose("Rejected X11 connection after ForwardX11Timeout " |
924 | "expired"); | 1016 | "expired"); |
925 | return -1; | 1017 | return -1; |
926 | } | 1018 | } |
927 | 1019 | ||
928 | /* Check if the fixed size part of the packet is in buffer. */ | 1020 | /* Check if the fixed size part of the packet is in buffer. */ |
929 | if (buffer_len(b) < 12) | 1021 | if (sshbuf_len(b) < 12) |
930 | return 0; | 1022 | return 0; |
931 | 1023 | ||
932 | /* Parse the lengths of variable-length fields. */ | 1024 | /* Parse the lengths of variable-length fields. */ |
933 | ucp = buffer_ptr(b); | 1025 | ucp = sshbuf_mutable_ptr(b); |
934 | if (ucp[0] == 0x42) { /* Byte order MSB first. */ | 1026 | if (ucp[0] == 0x42) { /* Byte order MSB first. */ |
935 | proto_len = 256 * ucp[6] + ucp[7]; | 1027 | proto_len = 256 * ucp[6] + ucp[7]; |
936 | data_len = 256 * ucp[8] + ucp[9]; | 1028 | data_len = 256 * ucp[8] + ucp[9]; |
@@ -944,27 +1036,27 @@ x11_open_helper(Buffer *b) | |||
944 | } | 1036 | } |
945 | 1037 | ||
946 | /* Check if the whole packet is in buffer. */ | 1038 | /* Check if the whole packet is in buffer. */ |
947 | if (buffer_len(b) < | 1039 | if (sshbuf_len(b) < |
948 | 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) | 1040 | 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3)) |
949 | return 0; | 1041 | return 0; |
950 | 1042 | ||
951 | /* Check if authentication protocol matches. */ | 1043 | /* Check if authentication protocol matches. */ |
952 | if (proto_len != strlen(x11_saved_proto) || | 1044 | if (proto_len != strlen(sc->x11_saved_proto) || |
953 | memcmp(ucp + 12, x11_saved_proto, proto_len) != 0) { | 1045 | memcmp(ucp + 12, sc->x11_saved_proto, proto_len) != 0) { |
954 | debug2("X11 connection uses different authentication protocol."); | 1046 | debug2("X11 connection uses different authentication protocol."); |
955 | return -1; | 1047 | return -1; |
956 | } | 1048 | } |
957 | /* Check if authentication data matches our fake data. */ | 1049 | /* Check if authentication data matches our fake data. */ |
958 | if (data_len != x11_fake_data_len || | 1050 | if (data_len != sc->x11_fake_data_len || |
959 | timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3), | 1051 | timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3), |
960 | x11_fake_data, x11_fake_data_len) != 0) { | 1052 | sc->x11_fake_data, sc->x11_fake_data_len) != 0) { |
961 | debug2("X11 auth data does not match fake data."); | 1053 | debug2("X11 auth data does not match fake data."); |
962 | return -1; | 1054 | return -1; |
963 | } | 1055 | } |
964 | /* Check fake data length */ | 1056 | /* Check fake data length */ |
965 | if (x11_fake_data_len != x11_saved_data_len) { | 1057 | if (sc->x11_fake_data_len != sc->x11_saved_data_len) { |
966 | error("X11 fake_data_len %d != saved_data_len %d", | 1058 | error("X11 fake_data_len %d != saved_data_len %d", |
967 | x11_fake_data_len, x11_saved_data_len); | 1059 | sc->x11_fake_data_len, sc->x11_saved_data_len); |
968 | return -1; | 1060 | return -1; |
969 | } | 1061 | } |
970 | /* | 1062 | /* |
@@ -973,60 +1065,64 @@ x11_open_helper(Buffer *b) | |||
973 | * data. | 1065 | * data. |
974 | */ | 1066 | */ |
975 | memcpy(ucp + 12 + ((proto_len + 3) & ~3), | 1067 | memcpy(ucp + 12 + ((proto_len + 3) & ~3), |
976 | x11_saved_data, x11_saved_data_len); | 1068 | sc->x11_saved_data, sc->x11_saved_data_len); |
977 | return 1; | 1069 | return 1; |
978 | } | 1070 | } |
979 | 1071 | ||
980 | static void | 1072 | static void |
981 | channel_pre_x11_open(Channel *c, fd_set *readset, fd_set *writeset) | 1073 | channel_pre_x11_open(struct ssh *ssh, Channel *c, |
1074 | fd_set *readset, fd_set *writeset) | ||
982 | { | 1075 | { |
983 | int ret = x11_open_helper(&c->output); | 1076 | int ret = x11_open_helper(ssh, c->output); |
984 | 1077 | ||
985 | /* c->force_drain = 1; */ | 1078 | /* c->force_drain = 1; */ |
986 | 1079 | ||
987 | if (ret == 1) { | 1080 | if (ret == 1) { |
988 | c->type = SSH_CHANNEL_OPEN; | 1081 | c->type = SSH_CHANNEL_OPEN; |
989 | channel_pre_open(c, readset, writeset); | 1082 | channel_pre_open(ssh, c, readset, writeset); |
990 | } else if (ret == -1) { | 1083 | } else if (ret == -1) { |
991 | logit("X11 connection rejected because of wrong authentication."); | 1084 | logit("X11 connection rejected because of wrong authentication."); |
992 | debug2("X11 rejected %d i%d/o%d", c->self, c->istate, c->ostate); | 1085 | debug2("X11 rejected %d i%d/o%d", |
993 | chan_read_failed(c); | 1086 | c->self, c->istate, c->ostate); |
994 | buffer_clear(&c->input); | 1087 | chan_read_failed(ssh, c); |
995 | chan_ibuf_empty(c); | 1088 | sshbuf_reset(c->input); |
996 | buffer_clear(&c->output); | 1089 | chan_ibuf_empty(ssh, c); |
997 | chan_write_failed(c); | 1090 | sshbuf_reset(c->output); |
1091 | chan_write_failed(ssh, c); | ||
998 | debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); | 1092 | debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); |
999 | } | 1093 | } |
1000 | } | 1094 | } |
1001 | 1095 | ||
1002 | static void | 1096 | static void |
1003 | channel_pre_mux_client(Channel *c, fd_set *readset, fd_set *writeset) | 1097 | channel_pre_mux_client(struct ssh *ssh, |
1098 | Channel *c, fd_set *readset, fd_set *writeset) | ||
1004 | { | 1099 | { |
1005 | if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && | 1100 | if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause && |
1006 | buffer_check_alloc(&c->input, CHAN_RBUF)) | 1101 | sshbuf_check_reserve(c->input, CHAN_RBUF) == 0) |
1007 | FD_SET(c->rfd, readset); | 1102 | FD_SET(c->rfd, readset); |
1008 | if (c->istate == CHAN_INPUT_WAIT_DRAIN) { | 1103 | if (c->istate == CHAN_INPUT_WAIT_DRAIN) { |
1009 | /* clear buffer immediately (discard any partial packet) */ | 1104 | /* clear buffer immediately (discard any partial packet) */ |
1010 | buffer_clear(&c->input); | 1105 | sshbuf_reset(c->input); |
1011 | chan_ibuf_empty(c); | 1106 | chan_ibuf_empty(ssh, c); |
1012 | /* Start output drain. XXX just kill chan? */ | 1107 | /* Start output drain. XXX just kill chan? */ |
1013 | chan_rcvd_oclose(c); | 1108 | chan_rcvd_oclose(ssh, c); |
1014 | } | 1109 | } |
1015 | if (c->ostate == CHAN_OUTPUT_OPEN || | 1110 | if (c->ostate == CHAN_OUTPUT_OPEN || |
1016 | c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { | 1111 | c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { |
1017 | if (buffer_len(&c->output) > 0) | 1112 | if (sshbuf_len(c->output) > 0) |
1018 | FD_SET(c->wfd, writeset); | 1113 | FD_SET(c->wfd, writeset); |
1019 | else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) | 1114 | else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) |
1020 | chan_obuf_empty(c); | 1115 | chan_obuf_empty(ssh, c); |
1021 | } | 1116 | } |
1022 | } | 1117 | } |
1023 | 1118 | ||
1024 | /* try to decode a socks4 header */ | 1119 | /* try to decode a socks4 header */ |
1025 | /* ARGSUSED */ | ||
1026 | static int | 1120 | static int |
1027 | channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) | 1121 | channel_decode_socks4(struct ssh *ssh, Channel *c, |
1122 | fd_set *readset, fd_set *writeset) | ||
1028 | { | 1123 | { |
1029 | char *p, *host; | 1124 | const u_char *p; |
1125 | char *host; | ||
1030 | u_int len, have, i, found, need; | 1126 | u_int len, have, i, found, need; |
1031 | char username[256]; | 1127 | char username[256]; |
1032 | struct { | 1128 | struct { |
@@ -1035,14 +1131,15 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) | |||
1035 | u_int16_t dest_port; | 1131 | u_int16_t dest_port; |
1036 | struct in_addr dest_addr; | 1132 | struct in_addr dest_addr; |
1037 | } s4_req, s4_rsp; | 1133 | } s4_req, s4_rsp; |
1134 | int r; | ||
1038 | 1135 | ||
1039 | debug2("channel %d: decode socks4", c->self); | 1136 | debug2("channel %d: decode socks4", c->self); |
1040 | 1137 | ||
1041 | have = buffer_len(&c->input); | 1138 | have = sshbuf_len(c->input); |
1042 | len = sizeof(s4_req); | 1139 | len = sizeof(s4_req); |
1043 | if (have < len) | 1140 | if (have < len) |
1044 | return 0; | 1141 | return 0; |
1045 | p = (char *)buffer_ptr(&c->input); | 1142 | p = sshbuf_ptr(c->input); |
1046 | 1143 | ||
1047 | need = 1; | 1144 | need = 1; |
1048 | /* SOCKS4A uses an invalid IP address 0.0.0.x */ | 1145 | /* SOCKS4A uses an invalid IP address 0.0.0.x */ |
@@ -1067,12 +1164,15 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) | |||
1067 | } | 1164 | } |
1068 | if (found < need) | 1165 | if (found < need) |
1069 | return 0; | 1166 | return 0; |
1070 | buffer_get(&c->input, (char *)&s4_req.version, 1); | 1167 | if ((r = sshbuf_get(c->input, &s4_req.version, 1)) != 0 || |
1071 | buffer_get(&c->input, (char *)&s4_req.command, 1); | 1168 | (r = sshbuf_get(c->input, &s4_req.command, 1)) != 0 || |
1072 | buffer_get(&c->input, (char *)&s4_req.dest_port, 2); | 1169 | (r = sshbuf_get(c->input, &s4_req.dest_port, 2)) != 0 || |
1073 | buffer_get(&c->input, (char *)&s4_req.dest_addr, 4); | 1170 | (r = sshbuf_get(c->input, &s4_req.dest_addr, 4)) != 0) { |
1074 | have = buffer_len(&c->input); | 1171 | debug("channels %d: decode socks4: %s", c->self, ssh_err(r)); |
1075 | p = (char *)buffer_ptr(&c->input); | 1172 | return -1; |
1173 | } | ||
1174 | have = sshbuf_len(c->input); | ||
1175 | p = sshbuf_ptr(c->input); | ||
1076 | if (memchr(p, '\0', have) == NULL) { | 1176 | if (memchr(p, '\0', have) == NULL) { |
1077 | error("channel %d: decode socks4: user not nul terminated", | 1177 | error("channel %d: decode socks4: user not nul terminated", |
1078 | c->self); | 1178 | c->self); |
@@ -1080,21 +1180,20 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) | |||
1080 | } | 1180 | } |
1081 | len = strlen(p); | 1181 | len = strlen(p); |
1082 | debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); | 1182 | debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); |
1083 | len++; /* trailing '\0' */ | 1183 | len++; /* trailing '\0' */ |
1084 | if (len > have) | ||
1085 | fatal("channel %d: decode socks4: len %d > have %d", | ||
1086 | c->self, len, have); | ||
1087 | strlcpy(username, p, sizeof(username)); | 1184 | strlcpy(username, p, sizeof(username)); |
1088 | buffer_consume(&c->input, len); | 1185 | if ((r = sshbuf_consume(c->input, len)) != 0) { |
1089 | 1186 | fatal("%s: channel %d: consume: %s", __func__, | |
1187 | c->self, ssh_err(r)); | ||
1188 | } | ||
1090 | free(c->path); | 1189 | free(c->path); |
1091 | c->path = NULL; | 1190 | c->path = NULL; |
1092 | if (need == 1) { /* SOCKS4: one string */ | 1191 | if (need == 1) { /* SOCKS4: one string */ |
1093 | host = inet_ntoa(s4_req.dest_addr); | 1192 | host = inet_ntoa(s4_req.dest_addr); |
1094 | c->path = xstrdup(host); | 1193 | c->path = xstrdup(host); |
1095 | } else { /* SOCKS4A: two strings */ | 1194 | } else { /* SOCKS4A: two strings */ |
1096 | have = buffer_len(&c->input); | 1195 | have = sshbuf_len(c->input); |
1097 | p = (char *)buffer_ptr(&c->input); | 1196 | p = sshbuf_ptr(c->input); |
1098 | if (memchr(p, '\0', have) == NULL) { | 1197 | if (memchr(p, '\0', have) == NULL) { |
1099 | error("channel %d: decode socks4a: host not nul " | 1198 | error("channel %d: decode socks4a: host not nul " |
1100 | "terminated", c->self); | 1199 | "terminated", c->self); |
@@ -1110,7 +1209,10 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) | |||
1110 | return -1; | 1209 | return -1; |
1111 | } | 1210 | } |
1112 | c->path = xstrdup(p); | 1211 | c->path = xstrdup(p); |
1113 | buffer_consume(&c->input, len); | 1212 | if ((r = sshbuf_consume(c->input, len)) != 0) { |
1213 | fatal("%s: channel %d: consume: %s", __func__, | ||
1214 | c->self, ssh_err(r)); | ||
1215 | } | ||
1114 | } | 1216 | } |
1115 | c->host_port = ntohs(s4_req.dest_port); | 1217 | c->host_port = ntohs(s4_req.dest_port); |
1116 | 1218 | ||
@@ -1126,7 +1228,10 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) | |||
1126 | s4_rsp.command = 90; /* cd: req granted */ | 1228 | s4_rsp.command = 90; /* cd: req granted */ |
1127 | s4_rsp.dest_port = 0; /* ignored */ | 1229 | s4_rsp.dest_port = 0; /* ignored */ |
1128 | s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */ | 1230 | s4_rsp.dest_addr.s_addr = INADDR_ANY; /* ignored */ |
1129 | buffer_append(&c->output, &s4_rsp, sizeof(s4_rsp)); | 1231 | if ((r = sshbuf_put(c->output, &s4_rsp, sizeof(s4_rsp))) != 0) { |
1232 | fatal("%s: channel %d: append reply: %s", __func__, | ||
1233 | c->self, ssh_err(r)); | ||
1234 | } | ||
1130 | return 1; | 1235 | return 1; |
1131 | } | 1236 | } |
1132 | 1237 | ||
@@ -1139,10 +1244,11 @@ channel_decode_socks4(Channel *c, fd_set *readset, fd_set *writeset) | |||
1139 | #define SSH_SOCKS5_CONNECT 0x01 | 1244 | #define SSH_SOCKS5_CONNECT 0x01 |
1140 | #define SSH_SOCKS5_SUCCESS 0x00 | 1245 | #define SSH_SOCKS5_SUCCESS 0x00 |
1141 | 1246 | ||
1142 | /* ARGSUSED */ | ||
1143 | static int | 1247 | static int |
1144 | channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) | 1248 | channel_decode_socks5(struct ssh *ssh, Channel *c, |
1249 | fd_set *readset, fd_set *writeset) | ||
1145 | { | 1250 | { |
1251 | /* XXX use get/put_u8 instead of trusting struct padding */ | ||
1146 | struct { | 1252 | struct { |
1147 | u_int8_t version; | 1253 | u_int8_t version; |
1148 | u_int8_t command; | 1254 | u_int8_t command; |
@@ -1151,14 +1257,15 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) | |||
1151 | } s5_req, s5_rsp; | 1257 | } s5_req, s5_rsp; |
1152 | u_int16_t dest_port; | 1258 | u_int16_t dest_port; |
1153 | char dest_addr[255+1], ntop[INET6_ADDRSTRLEN]; | 1259 | char dest_addr[255+1], ntop[INET6_ADDRSTRLEN]; |
1154 | u_char *p; | 1260 | const u_char *p; |
1155 | u_int have, need, i, found, nmethods, addrlen, af; | 1261 | u_int have, need, i, found, nmethods, addrlen, af; |
1262 | int r; | ||
1156 | 1263 | ||
1157 | debug2("channel %d: decode socks5", c->self); | 1264 | debug2("channel %d: decode socks5", c->self); |
1158 | p = buffer_ptr(&c->input); | 1265 | p = sshbuf_ptr(c->input); |
1159 | if (p[0] != 0x05) | 1266 | if (p[0] != 0x05) |
1160 | return -1; | 1267 | return -1; |
1161 | have = buffer_len(&c->input); | 1268 | have = sshbuf_len(c->input); |
1162 | if (!(c->flags & SSH_SOCKS5_AUTHDONE)) { | 1269 | if (!(c->flags & SSH_SOCKS5_AUTHDONE)) { |
1163 | /* format: ver | nmethods | methods */ | 1270 | /* format: ver | nmethods | methods */ |
1164 | if (have < 2) | 1271 | if (have < 2) |
@@ -1178,9 +1285,16 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) | |||
1178 | c->self); | 1285 | c->self); |
1179 | return -1; | 1286 | return -1; |
1180 | } | 1287 | } |
1181 | buffer_consume(&c->input, nmethods + 2); | 1288 | if ((r = sshbuf_consume(c->input, nmethods + 2)) != 0) { |
1182 | buffer_put_char(&c->output, 0x05); /* version */ | 1289 | fatal("%s: channel %d: consume: %s", __func__, |
1183 | buffer_put_char(&c->output, SSH_SOCKS5_NOAUTH); /* method */ | 1290 | c->self, ssh_err(r)); |
1291 | } | ||
1292 | /* version, method */ | ||
1293 | if ((r = sshbuf_put_u8(c->output, 0x05)) != 0 || | ||
1294 | (r = sshbuf_put_u8(c->output, SSH_SOCKS5_NOAUTH)) != 0) { | ||
1295 | fatal("%s: channel %d: append reply: %s", __func__, | ||
1296 | c->self, ssh_err(r)); | ||
1297 | } | ||
1184 | FD_SET(c->sock, writeset); | 1298 | FD_SET(c->sock, writeset); |
1185 | c->flags |= SSH_SOCKS5_AUTHDONE; | 1299 | c->flags |= SSH_SOCKS5_AUTHDONE; |
1186 | debug2("channel %d: socks5 auth done", c->self); | 1300 | debug2("channel %d: socks5 auth done", c->self); |
@@ -1218,11 +1332,22 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) | |||
1218 | need++; | 1332 | need++; |
1219 | if (have < need) | 1333 | if (have < need) |
1220 | return 0; | 1334 | return 0; |
1221 | buffer_consume(&c->input, sizeof(s5_req)); | 1335 | if ((r = sshbuf_consume(c->input, sizeof(s5_req))) != 0) { |
1222 | if (s5_req.atyp == SSH_SOCKS5_DOMAIN) | 1336 | fatal("%s: channel %d: consume: %s", __func__, |
1223 | buffer_consume(&c->input, 1); /* host string length */ | 1337 | c->self, ssh_err(r)); |
1224 | buffer_get(&c->input, &dest_addr, addrlen); | 1338 | } |
1225 | buffer_get(&c->input, (char *)&dest_port, 2); | 1339 | if (s5_req.atyp == SSH_SOCKS5_DOMAIN) { |
1340 | /* host string length */ | ||
1341 | if ((r = sshbuf_consume(c->input, 1)) != 0) { | ||
1342 | fatal("%s: channel %d: consume: %s", __func__, | ||
1343 | c->self, ssh_err(r)); | ||
1344 | } | ||
1345 | } | ||
1346 | if ((r = sshbuf_get(c->input, &dest_addr, addrlen)) != 0 || | ||
1347 | (r = sshbuf_get(c->input, &dest_port, 2)) != 0) { | ||
1348 | debug("channel %d: parse addr/port: %s", c->self, ssh_err(r)); | ||
1349 | return -1; | ||
1350 | } | ||
1226 | dest_addr[addrlen] = '\0'; | 1351 | dest_addr[addrlen] = '\0'; |
1227 | free(c->path); | 1352 | free(c->path); |
1228 | c->path = NULL; | 1353 | c->path = NULL; |
@@ -1249,22 +1374,23 @@ channel_decode_socks5(Channel *c, fd_set *readset, fd_set *writeset) | |||
1249 | s5_rsp.atyp = SSH_SOCKS5_IPV4; | 1374 | s5_rsp.atyp = SSH_SOCKS5_IPV4; |
1250 | dest_port = 0; /* ignored */ | 1375 | dest_port = 0; /* ignored */ |
1251 | 1376 | ||
1252 | buffer_append(&c->output, &s5_rsp, sizeof(s5_rsp)); | 1377 | if ((r = sshbuf_put(c->output, &s5_rsp, sizeof(s5_rsp))) != 0 || |
1253 | buffer_put_int(&c->output, ntohl(INADDR_ANY)); /* bind address */ | 1378 | (r = sshbuf_put_u32(c->output, ntohl(INADDR_ANY))) != 0 || |
1254 | buffer_append(&c->output, &dest_port, sizeof(dest_port)); | 1379 | (r = sshbuf_put(c->output, &dest_port, sizeof(dest_port))) != 0) |
1380 | fatal("%s: channel %d: append reply: %s", __func__, | ||
1381 | c->self, ssh_err(r)); | ||
1255 | return 1; | 1382 | return 1; |
1256 | } | 1383 | } |
1257 | 1384 | ||
1258 | Channel * | 1385 | Channel * |
1259 | channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect, | 1386 | channel_connect_stdio_fwd(struct ssh *ssh, |
1260 | int in, int out) | 1387 | const char *host_to_connect, u_short port_to_connect, int in, int out) |
1261 | { | 1388 | { |
1262 | Channel *c; | 1389 | Channel *c; |
1263 | 1390 | ||
1264 | debug("channel_connect_stdio_fwd %s:%d", host_to_connect, | 1391 | debug("%s %s:%d", __func__, host_to_connect, port_to_connect); |
1265 | port_to_connect); | ||
1266 | 1392 | ||
1267 | c = channel_new("stdio-forward", SSH_CHANNEL_OPENING, in, out, | 1393 | c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out, |
1268 | -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | 1394 | -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
1269 | 0, "stdio-forward", /*nonblock*/0); | 1395 | 0, "stdio-forward", /*nonblock*/0); |
1270 | 1396 | ||
@@ -1273,23 +1399,24 @@ channel_connect_stdio_fwd(const char *host_to_connect, u_short port_to_connect, | |||
1273 | c->listening_port = 0; | 1399 | c->listening_port = 0; |
1274 | c->force_drain = 1; | 1400 | c->force_drain = 1; |
1275 | 1401 | ||
1276 | channel_register_fds(c, in, out, -1, 0, 1, 0); | 1402 | channel_register_fds(ssh, c, in, out, -1, 0, 1, 0); |
1277 | port_open_helper(c, "direct-tcpip"); | 1403 | port_open_helper(ssh, c, "direct-tcpip"); |
1278 | 1404 | ||
1279 | return c; | 1405 | return c; |
1280 | } | 1406 | } |
1281 | 1407 | ||
1282 | /* dynamic port forwarding */ | 1408 | /* dynamic port forwarding */ |
1283 | static void | 1409 | static void |
1284 | channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) | 1410 | channel_pre_dynamic(struct ssh *ssh, Channel *c, |
1411 | fd_set *readset, fd_set *writeset) | ||
1285 | { | 1412 | { |
1286 | u_char *p; | 1413 | const u_char *p; |
1287 | u_int have; | 1414 | u_int have; |
1288 | int ret; | 1415 | int ret; |
1289 | 1416 | ||
1290 | have = buffer_len(&c->input); | 1417 | have = sshbuf_len(c->input); |
1291 | debug2("channel %d: pre_dynamic: have %d", c->self, have); | 1418 | debug2("channel %d: pre_dynamic: have %d", c->self, have); |
1292 | /* buffer_dump(&c->input); */ | 1419 | /* sshbuf_dump(c->input, stderr); */ |
1293 | /* check if the fixed size part of the packet is in buffer. */ | 1420 | /* check if the fixed size part of the packet is in buffer. */ |
1294 | if (have < 3) { | 1421 | if (have < 3) { |
1295 | /* need more */ | 1422 | /* need more */ |
@@ -1297,20 +1424,21 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) | |||
1297 | return; | 1424 | return; |
1298 | } | 1425 | } |
1299 | /* try to guess the protocol */ | 1426 | /* try to guess the protocol */ |
1300 | p = buffer_ptr(&c->input); | 1427 | p = sshbuf_ptr(c->input); |
1428 | /* XXX sshbuf_peek_u8? */ | ||
1301 | switch (p[0]) { | 1429 | switch (p[0]) { |
1302 | case 0x04: | 1430 | case 0x04: |
1303 | ret = channel_decode_socks4(c, readset, writeset); | 1431 | ret = channel_decode_socks4(ssh, c, readset, writeset); |
1304 | break; | 1432 | break; |
1305 | case 0x05: | 1433 | case 0x05: |
1306 | ret = channel_decode_socks5(c, readset, writeset); | 1434 | ret = channel_decode_socks5(ssh, c, readset, writeset); |
1307 | break; | 1435 | break; |
1308 | default: | 1436 | default: |
1309 | ret = -1; | 1437 | ret = -1; |
1310 | break; | 1438 | break; |
1311 | } | 1439 | } |
1312 | if (ret < 0) { | 1440 | if (ret < 0) { |
1313 | chan_mark_dead(c); | 1441 | chan_mark_dead(ssh, c); |
1314 | } else if (ret == 0) { | 1442 | } else if (ret == 0) { |
1315 | debug2("channel %d: pre_dynamic: need more", c->self); | 1443 | debug2("channel %d: pre_dynamic: need more", c->self); |
1316 | /* need more */ | 1444 | /* need more */ |
@@ -1318,75 +1446,75 @@ channel_pre_dynamic(Channel *c, fd_set *readset, fd_set *writeset) | |||
1318 | } else { | 1446 | } else { |
1319 | /* switch to the next state */ | 1447 | /* switch to the next state */ |
1320 | c->type = SSH_CHANNEL_OPENING; | 1448 | c->type = SSH_CHANNEL_OPENING; |
1321 | port_open_helper(c, "direct-tcpip"); | 1449 | port_open_helper(ssh, c, "direct-tcpip"); |
1322 | } | 1450 | } |
1323 | } | 1451 | } |
1324 | 1452 | ||
1325 | /* This is our fake X11 server socket. */ | 1453 | /* This is our fake X11 server socket. */ |
1326 | /* ARGSUSED */ | ||
1327 | static void | 1454 | static void |
1328 | channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset) | 1455 | channel_post_x11_listener(struct ssh *ssh, Channel *c, |
1456 | fd_set *readset, fd_set *writeset) | ||
1329 | { | 1457 | { |
1330 | Channel *nc; | 1458 | Channel *nc; |
1331 | struct sockaddr_storage addr; | 1459 | struct sockaddr_storage addr; |
1332 | int newsock, oerrno; | 1460 | int r, newsock, oerrno, remote_port; |
1333 | socklen_t addrlen; | 1461 | socklen_t addrlen; |
1334 | char buf[16384], *remote_ipaddr; | 1462 | char buf[16384], *remote_ipaddr; |
1335 | int remote_port; | 1463 | |
1336 | 1464 | if (!FD_ISSET(c->sock, readset)) | |
1337 | if (FD_ISSET(c->sock, readset)) { | 1465 | return; |
1338 | debug("X11 connection requested."); | 1466 | |
1339 | addrlen = sizeof(addr); | 1467 | debug("X11 connection requested."); |
1340 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | 1468 | addrlen = sizeof(addr); |
1341 | if (c->single_connection) { | 1469 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); |
1342 | oerrno = errno; | 1470 | if (c->single_connection) { |
1343 | debug2("single_connection: closing X11 listener."); | 1471 | oerrno = errno; |
1344 | channel_close_fd(&c->sock); | 1472 | debug2("single_connection: closing X11 listener."); |
1345 | chan_mark_dead(c); | 1473 | channel_close_fd(ssh, &c->sock); |
1346 | errno = oerrno; | 1474 | chan_mark_dead(ssh, c); |
1347 | } | 1475 | errno = oerrno; |
1348 | if (newsock < 0) { | 1476 | } |
1349 | if (errno != EINTR && errno != EWOULDBLOCK && | 1477 | if (newsock < 0) { |
1350 | errno != ECONNABORTED) | 1478 | if (errno != EINTR && errno != EWOULDBLOCK && |
1351 | error("accept: %.100s", strerror(errno)); | 1479 | errno != ECONNABORTED) |
1352 | if (errno == EMFILE || errno == ENFILE) | 1480 | error("accept: %.100s", strerror(errno)); |
1353 | c->notbefore = monotime() + 1; | 1481 | if (errno == EMFILE || errno == ENFILE) |
1354 | return; | 1482 | c->notbefore = monotime() + 1; |
1355 | } | 1483 | return; |
1356 | set_nodelay(newsock); | ||
1357 | remote_ipaddr = get_peer_ipaddr(newsock); | ||
1358 | remote_port = get_peer_port(newsock); | ||
1359 | snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", | ||
1360 | remote_ipaddr, remote_port); | ||
1361 | |||
1362 | nc = channel_new("accepted x11 socket", | ||
1363 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | ||
1364 | c->local_window_max, c->local_maxpacket, 0, buf, 1); | ||
1365 | packet_start(SSH2_MSG_CHANNEL_OPEN); | ||
1366 | packet_put_cstring("x11"); | ||
1367 | packet_put_int(nc->self); | ||
1368 | packet_put_int(nc->local_window_max); | ||
1369 | packet_put_int(nc->local_maxpacket); | ||
1370 | /* originator ipaddr and port */ | ||
1371 | packet_put_cstring(remote_ipaddr); | ||
1372 | if (datafellows & SSH_BUG_X11FWD) { | ||
1373 | debug2("ssh2 x11 bug compat mode"); | ||
1374 | } else { | ||
1375 | packet_put_int(remote_port); | ||
1376 | } | ||
1377 | packet_send(); | ||
1378 | free(remote_ipaddr); | ||
1379 | } | 1484 | } |
1485 | set_nodelay(newsock); | ||
1486 | remote_ipaddr = get_peer_ipaddr(newsock); | ||
1487 | remote_port = get_peer_port(newsock); | ||
1488 | snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", | ||
1489 | remote_ipaddr, remote_port); | ||
1490 | |||
1491 | nc = channel_new(ssh, "accepted x11 socket", | ||
1492 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | ||
1493 | c->local_window_max, c->local_maxpacket, 0, buf, 1); | ||
1494 | open_preamble(ssh, __func__, nc, "x11"); | ||
1495 | if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0) { | ||
1496 | fatal("%s: channel %i: reply %s", __func__, | ||
1497 | c->self, ssh_err(r)); | ||
1498 | } | ||
1499 | if ((datafellows & SSH_BUG_X11FWD) != 0) | ||
1500 | debug2("channel %d: ssh2 x11 bug compat mode", nc->self); | ||
1501 | else if ((r = sshpkt_put_u32(ssh, remote_port)) != 0) { | ||
1502 | fatal("%s: channel %i: reply %s", __func__, | ||
1503 | c->self, ssh_err(r)); | ||
1504 | } | ||
1505 | if ((r = sshpkt_send(ssh)) != 0) | ||
1506 | fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); | ||
1507 | free(remote_ipaddr); | ||
1380 | } | 1508 | } |
1381 | 1509 | ||
1382 | static void | 1510 | static void |
1383 | port_open_helper(Channel *c, char *rtype) | 1511 | port_open_helper(struct ssh *ssh, Channel *c, char *rtype) |
1384 | { | 1512 | { |
1385 | char buf[1024]; | ||
1386 | char *local_ipaddr = get_local_ipaddr(c->sock); | 1513 | char *local_ipaddr = get_local_ipaddr(c->sock); |
1387 | int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock); | 1514 | int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock); |
1388 | char *remote_ipaddr = get_peer_ipaddr(c->sock); | 1515 | char *remote_ipaddr = get_peer_ipaddr(c->sock); |
1389 | int remote_port = get_peer_port(c->sock); | 1516 | int remote_port = get_peer_port(c->sock); |
1517 | int r; | ||
1390 | 1518 | ||
1391 | if (remote_port == -1) { | 1519 | if (remote_port == -1) { |
1392 | /* Fake addr/port to appease peers that validate it (Tectia) */ | 1520 | /* Fake addr/port to appease peers that validate it (Tectia) */ |
@@ -1395,44 +1523,57 @@ port_open_helper(Channel *c, char *rtype) | |||
1395 | remote_port = 65535; | 1523 | remote_port = 65535; |
1396 | } | 1524 | } |
1397 | 1525 | ||
1398 | snprintf(buf, sizeof buf, | 1526 | free(c->remote_name); |
1527 | xasprintf(&c->remote_name, | ||
1399 | "%s: listening port %d for %.100s port %d, " | 1528 | "%s: listening port %d for %.100s port %d, " |
1400 | "connect from %.200s port %d to %.100s port %d", | 1529 | "connect from %.200s port %d to %.100s port %d", |
1401 | rtype, c->listening_port, c->path, c->host_port, | 1530 | rtype, c->listening_port, c->path, c->host_port, |
1402 | remote_ipaddr, remote_port, local_ipaddr, local_port); | 1531 | remote_ipaddr, remote_port, local_ipaddr, local_port); |
1403 | 1532 | ||
1404 | free(c->remote_name); | 1533 | open_preamble(ssh, __func__, c, rtype); |
1405 | c->remote_name = xstrdup(buf); | ||
1406 | |||
1407 | packet_start(SSH2_MSG_CHANNEL_OPEN); | ||
1408 | packet_put_cstring(rtype); | ||
1409 | packet_put_int(c->self); | ||
1410 | packet_put_int(c->local_window_max); | ||
1411 | packet_put_int(c->local_maxpacket); | ||
1412 | if (strcmp(rtype, "direct-tcpip") == 0) { | 1534 | if (strcmp(rtype, "direct-tcpip") == 0) { |
1413 | /* target host, port */ | 1535 | /* target host, port */ |
1414 | packet_put_cstring(c->path); | 1536 | if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || |
1415 | packet_put_int(c->host_port); | 1537 | (r = sshpkt_put_u32(ssh, c->host_port)) != 0) { |
1538 | fatal("%s: channel %i: reply %s", __func__, | ||
1539 | c->self, ssh_err(r)); | ||
1540 | } | ||
1416 | } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { | 1541 | } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { |
1417 | /* target path */ | 1542 | /* target path */ |
1418 | packet_put_cstring(c->path); | 1543 | if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) { |
1544 | fatal("%s: channel %i: reply %s", __func__, | ||
1545 | c->self, ssh_err(r)); | ||
1546 | } | ||
1419 | } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { | 1547 | } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { |
1420 | /* listen path */ | 1548 | /* listen path */ |
1421 | packet_put_cstring(c->path); | 1549 | if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) { |
1550 | fatal("%s: channel %i: reply %s", __func__, | ||
1551 | c->self, ssh_err(r)); | ||
1552 | } | ||
1422 | } else { | 1553 | } else { |
1423 | /* listen address, port */ | 1554 | /* listen address, port */ |
1424 | packet_put_cstring(c->path); | 1555 | if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 || |
1425 | packet_put_int(local_port); | 1556 | (r = sshpkt_put_u32(ssh, local_port)) != 0) { |
1557 | fatal("%s: channel %i: reply %s", __func__, | ||
1558 | c->self, ssh_err(r)); | ||
1559 | } | ||
1426 | } | 1560 | } |
1427 | if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { | 1561 | if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { |
1428 | /* reserved for future owner/mode info */ | 1562 | /* reserved for future owner/mode info */ |
1429 | packet_put_cstring(""); | 1563 | if ((r = sshpkt_put_cstring(ssh, "")) != 0) { |
1564 | fatal("%s: channel %i: reply %s", __func__, | ||
1565 | c->self, ssh_err(r)); | ||
1566 | } | ||
1430 | } else { | 1567 | } else { |
1431 | /* originator host and port */ | 1568 | /* originator host and port */ |
1432 | packet_put_cstring(remote_ipaddr); | 1569 | if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 || |
1433 | packet_put_int((u_int)remote_port); | 1570 | (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) { |
1571 | fatal("%s: channel %i: reply %s", __func__, | ||
1572 | c->self, ssh_err(r)); | ||
1573 | } | ||
1434 | } | 1574 | } |
1435 | packet_send(); | 1575 | if ((r = sshpkt_send(ssh)) != 0) |
1576 | fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); | ||
1436 | free(remote_ipaddr); | 1577 | free(remote_ipaddr); |
1437 | free(local_ipaddr); | 1578 | free(local_ipaddr); |
1438 | } | 1579 | } |
@@ -1451,17 +1592,17 @@ channel_set_reuseaddr(int fd) | |||
1451 | } | 1592 | } |
1452 | 1593 | ||
1453 | void | 1594 | void |
1454 | channel_set_x11_refuse_time(u_int refuse_time) | 1595 | channel_set_x11_refuse_time(struct ssh *ssh, u_int refuse_time) |
1455 | { | 1596 | { |
1456 | x11_refuse_time = refuse_time; | 1597 | ssh->chanctxt->x11_refuse_time = refuse_time; |
1457 | } | 1598 | } |
1458 | 1599 | ||
1459 | /* | 1600 | /* |
1460 | * This socket is listening for connections to a forwarded TCP/IP port. | 1601 | * This socket is listening for connections to a forwarded TCP/IP port. |
1461 | */ | 1602 | */ |
1462 | /* ARGSUSED */ | ||
1463 | static void | 1603 | static void |
1464 | channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) | 1604 | channel_post_port_listener(struct ssh *ssh, Channel *c, |
1605 | fd_set *readset, fd_set *writeset) | ||
1465 | { | 1606 | { |
1466 | Channel *nc; | 1607 | Channel *nc; |
1467 | struct sockaddr_storage addr; | 1608 | struct sockaddr_storage addr; |
@@ -1469,336 +1610,387 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1469 | socklen_t addrlen; | 1610 | socklen_t addrlen; |
1470 | char *rtype; | 1611 | char *rtype; |
1471 | 1612 | ||
1472 | if (FD_ISSET(c->sock, readset)) { | 1613 | if (!FD_ISSET(c->sock, readset)) |
1473 | debug("Connection to port %d forwarding " | 1614 | return; |
1474 | "to %.100s port %d requested.", | ||
1475 | c->listening_port, c->path, c->host_port); | ||
1476 | |||
1477 | if (c->type == SSH_CHANNEL_RPORT_LISTENER) { | ||
1478 | nextstate = SSH_CHANNEL_OPENING; | ||
1479 | rtype = "forwarded-tcpip"; | ||
1480 | } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { | ||
1481 | nextstate = SSH_CHANNEL_OPENING; | ||
1482 | rtype = "forwarded-streamlocal@openssh.com"; | ||
1483 | } else if (c->host_port == PORT_STREAMLOCAL) { | ||
1484 | nextstate = SSH_CHANNEL_OPENING; | ||
1485 | rtype = "direct-streamlocal@openssh.com"; | ||
1486 | } else if (c->host_port == 0) { | ||
1487 | nextstate = SSH_CHANNEL_DYNAMIC; | ||
1488 | rtype = "dynamic-tcpip"; | ||
1489 | } else { | ||
1490 | nextstate = SSH_CHANNEL_OPENING; | ||
1491 | rtype = "direct-tcpip"; | ||
1492 | } | ||
1493 | 1615 | ||
1494 | addrlen = sizeof(addr); | 1616 | debug("Connection to port %d forwarding to %.100s port %d requested.", |
1495 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | 1617 | c->listening_port, c->path, c->host_port); |
1496 | if (newsock < 0) { | 1618 | |
1497 | if (errno != EINTR && errno != EWOULDBLOCK && | 1619 | if (c->type == SSH_CHANNEL_RPORT_LISTENER) { |
1498 | errno != ECONNABORTED) | 1620 | nextstate = SSH_CHANNEL_OPENING; |
1499 | error("accept: %.100s", strerror(errno)); | 1621 | rtype = "forwarded-tcpip"; |
1500 | if (errno == EMFILE || errno == ENFILE) | 1622 | } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { |
1501 | c->notbefore = monotime() + 1; | 1623 | nextstate = SSH_CHANNEL_OPENING; |
1502 | return; | 1624 | rtype = "forwarded-streamlocal@openssh.com"; |
1503 | } | 1625 | } else if (c->host_port == PORT_STREAMLOCAL) { |
1504 | if (c->host_port != PORT_STREAMLOCAL) | 1626 | nextstate = SSH_CHANNEL_OPENING; |
1505 | set_nodelay(newsock); | 1627 | rtype = "direct-streamlocal@openssh.com"; |
1506 | nc = channel_new(rtype, nextstate, newsock, newsock, -1, | 1628 | } else if (c->host_port == 0) { |
1507 | c->local_window_max, c->local_maxpacket, 0, rtype, 1); | 1629 | nextstate = SSH_CHANNEL_DYNAMIC; |
1508 | nc->listening_port = c->listening_port; | 1630 | rtype = "dynamic-tcpip"; |
1509 | nc->host_port = c->host_port; | 1631 | } else { |
1510 | if (c->path != NULL) | 1632 | nextstate = SSH_CHANNEL_OPENING; |
1511 | nc->path = xstrdup(c->path); | 1633 | rtype = "direct-tcpip"; |
1512 | 1634 | } | |
1513 | if (nextstate != SSH_CHANNEL_DYNAMIC) | 1635 | |
1514 | port_open_helper(nc, rtype); | 1636 | addrlen = sizeof(addr); |
1637 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | ||
1638 | if (newsock < 0) { | ||
1639 | if (errno != EINTR && errno != EWOULDBLOCK && | ||
1640 | errno != ECONNABORTED) | ||
1641 | error("accept: %.100s", strerror(errno)); | ||
1642 | if (errno == EMFILE || errno == ENFILE) | ||
1643 | c->notbefore = monotime() + 1; | ||
1644 | return; | ||
1515 | } | 1645 | } |
1646 | if (c->host_port != PORT_STREAMLOCAL) | ||
1647 | set_nodelay(newsock); | ||
1648 | nc = channel_new(ssh, rtype, nextstate, newsock, newsock, -1, | ||
1649 | c->local_window_max, c->local_maxpacket, 0, rtype, 1); | ||
1650 | nc->listening_port = c->listening_port; | ||
1651 | nc->host_port = c->host_port; | ||
1652 | if (c->path != NULL) | ||
1653 | nc->path = xstrdup(c->path); | ||
1654 | |||
1655 | if (nextstate != SSH_CHANNEL_DYNAMIC) | ||
1656 | port_open_helper(ssh, nc, rtype); | ||
1516 | } | 1657 | } |
1517 | 1658 | ||
1518 | /* | 1659 | /* |
1519 | * This is the authentication agent socket listening for connections from | 1660 | * This is the authentication agent socket listening for connections from |
1520 | * clients. | 1661 | * clients. |
1521 | */ | 1662 | */ |
1522 | /* ARGSUSED */ | ||
1523 | static void | 1663 | static void |
1524 | channel_post_auth_listener(Channel *c, fd_set *readset, fd_set *writeset) | 1664 | channel_post_auth_listener(struct ssh *ssh, Channel *c, |
1665 | fd_set *readset, fd_set *writeset) | ||
1525 | { | 1666 | { |
1526 | Channel *nc; | 1667 | Channel *nc; |
1527 | int newsock; | 1668 | int r, newsock; |
1528 | struct sockaddr_storage addr; | 1669 | struct sockaddr_storage addr; |
1529 | socklen_t addrlen; | 1670 | socklen_t addrlen; |
1530 | 1671 | ||
1531 | if (FD_ISSET(c->sock, readset)) { | 1672 | if (!FD_ISSET(c->sock, readset)) |
1532 | addrlen = sizeof(addr); | 1673 | return; |
1533 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | 1674 | |
1534 | if (newsock < 0) { | 1675 | addrlen = sizeof(addr); |
1535 | error("accept from auth socket: %.100s", | 1676 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); |
1536 | strerror(errno)); | 1677 | if (newsock < 0) { |
1537 | if (errno == EMFILE || errno == ENFILE) | 1678 | error("accept from auth socket: %.100s", strerror(errno)); |
1538 | c->notbefore = monotime() + 1; | 1679 | if (errno == EMFILE || errno == ENFILE) |
1539 | return; | 1680 | c->notbefore = monotime() + 1; |
1540 | } | 1681 | return; |
1541 | nc = channel_new("accepted auth socket", | ||
1542 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | ||
1543 | c->local_window_max, c->local_maxpacket, | ||
1544 | 0, "accepted auth socket", 1); | ||
1545 | packet_start(SSH2_MSG_CHANNEL_OPEN); | ||
1546 | packet_put_cstring("auth-agent@openssh.com"); | ||
1547 | packet_put_int(nc->self); | ||
1548 | packet_put_int(c->local_window_max); | ||
1549 | packet_put_int(c->local_maxpacket); | ||
1550 | packet_send(); | ||
1551 | } | 1682 | } |
1683 | nc = channel_new(ssh, "accepted auth socket", | ||
1684 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | ||
1685 | c->local_window_max, c->local_maxpacket, | ||
1686 | 0, "accepted auth socket", 1); | ||
1687 | open_preamble(ssh, __func__, nc, "auth-agent@openssh.com"); | ||
1688 | if ((r = sshpkt_send(ssh)) != 0) | ||
1689 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | ||
1552 | } | 1690 | } |
1553 | 1691 | ||
1554 | /* ARGSUSED */ | ||
1555 | static void | 1692 | static void |
1556 | channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset) | 1693 | channel_post_connecting(struct ssh *ssh, Channel *c, |
1694 | fd_set *readset, fd_set *writeset) | ||
1557 | { | 1695 | { |
1558 | int err = 0, sock; | 1696 | int err = 0, sock, r; |
1559 | socklen_t sz = sizeof(err); | 1697 | socklen_t sz = sizeof(err); |
1560 | 1698 | ||
1561 | if (FD_ISSET(c->sock, writeset)) { | 1699 | if (!FD_ISSET(c->sock, writeset)) |
1562 | if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { | 1700 | return; |
1563 | err = errno; | 1701 | |
1564 | error("getsockopt SO_ERROR failed"); | 1702 | if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) { |
1703 | err = errno; | ||
1704 | error("getsockopt SO_ERROR failed"); | ||
1705 | } | ||
1706 | if (err == 0) { | ||
1707 | debug("channel %d: connected to %s port %d", | ||
1708 | c->self, c->connect_ctx.host, c->connect_ctx.port); | ||
1709 | channel_connect_ctx_free(&c->connect_ctx); | ||
1710 | c->type = SSH_CHANNEL_OPEN; | ||
1711 | if ((r = sshpkt_start(ssh, | ||
1712 | SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 || | ||
1713 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || | ||
1714 | (r = sshpkt_put_u32(ssh, c->self)) != 0 || | ||
1715 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 || | ||
1716 | (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) { | ||
1717 | fatal("%s: channel %i: confirm: %s", __func__, | ||
1718 | c->self, ssh_err(r)); | ||
1565 | } | 1719 | } |
1566 | if (err == 0) { | 1720 | } else { |
1567 | debug("channel %d: connected to %s port %d", | 1721 | debug("channel %d: connection failed: %s", |
1568 | c->self, c->connect_ctx.host, c->connect_ctx.port); | 1722 | c->self, strerror(err)); |
1569 | channel_connect_ctx_free(&c->connect_ctx); | 1723 | /* Try next address, if any */ |
1570 | c->type = SSH_CHANNEL_OPEN; | 1724 | if ((sock = connect_next(&c->connect_ctx)) > 0) { |
1571 | packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION); | 1725 | close(c->sock); |
1572 | packet_put_int(c->remote_id); | 1726 | c->sock = c->rfd = c->wfd = sock; |
1573 | packet_put_int(c->self); | 1727 | channel_find_maxfd(ssh->chanctxt); |
1574 | packet_put_int(c->local_window); | 1728 | return; |
1575 | packet_put_int(c->local_maxpacket); | 1729 | } |
1576 | } else { | 1730 | /* Exhausted all addresses */ |
1577 | debug("channel %d: connection failed: %s", | 1731 | error("connect_to %.100s port %d: failed.", |
1578 | c->self, strerror(err)); | 1732 | c->connect_ctx.host, c->connect_ctx.port); |
1579 | /* Try next address, if any */ | 1733 | channel_connect_ctx_free(&c->connect_ctx); |
1580 | if ((sock = connect_next(&c->connect_ctx)) > 0) { | 1734 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 || |
1581 | close(c->sock); | 1735 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
1582 | c->sock = c->rfd = c->wfd = sock; | 1736 | (r = sshpkt_put_u32(ssh, SSH2_OPEN_CONNECT_FAILED)) != 0) { |
1583 | channel_max_fd = channel_find_maxfd(); | 1737 | fatal("%s: channel %i: failure: %s", __func__, |
1584 | return; | 1738 | c->self, ssh_err(r)); |
1585 | } | 1739 | } |
1586 | /* Exhausted all addresses */ | 1740 | if ((datafellows & SSH_BUG_OPENFAILURE) == 0 && |
1587 | error("connect_to %.100s port %d: failed.", | 1741 | ((r = sshpkt_put_cstring(ssh, strerror(err))) != 0 || |
1588 | c->connect_ctx.host, c->connect_ctx.port); | 1742 | (r = sshpkt_put_cstring(ssh, "")) != 0)) { |
1589 | channel_connect_ctx_free(&c->connect_ctx); | 1743 | fatal("%s: channel %i: failure: %s", __func__, |
1590 | packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE); | 1744 | c->self, ssh_err(r)); |
1591 | packet_put_int(c->remote_id); | ||
1592 | packet_put_int(SSH2_OPEN_CONNECT_FAILED); | ||
1593 | if (!(datafellows & SSH_BUG_OPENFAILURE)) { | ||
1594 | packet_put_cstring(strerror(err)); | ||
1595 | packet_put_cstring(""); | ||
1596 | } | ||
1597 | chan_mark_dead(c); | ||
1598 | } | 1745 | } |
1599 | packet_send(); | 1746 | chan_mark_dead(ssh, c); |
1600 | } | 1747 | } |
1748 | if ((r = sshpkt_send(ssh)) != 0) | ||
1749 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | ||
1601 | } | 1750 | } |
1602 | 1751 | ||
1603 | /* ARGSUSED */ | ||
1604 | static int | 1752 | static int |
1605 | channel_handle_rfd(Channel *c, fd_set *readset, fd_set *writeset) | 1753 | channel_handle_rfd(struct ssh *ssh, Channel *c, |
1754 | fd_set *readset, fd_set *writeset) | ||
1606 | { | 1755 | { |
1607 | char buf[CHAN_RBUF]; | 1756 | char buf[CHAN_RBUF]; |
1608 | int len, force; | 1757 | ssize_t len; |
1758 | int r, force; | ||
1609 | 1759 | ||
1610 | force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED; | 1760 | force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED; |
1611 | if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) { | 1761 | |
1612 | errno = 0; | 1762 | if (c->rfd == -1 || (!force && !FD_ISSET(c->rfd, readset))) |
1613 | len = read(c->rfd, buf, sizeof(buf)); | 1763 | return 1; |
1614 | if (len < 0 && (errno == EINTR || | 1764 | |
1615 | ((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) | 1765 | errno = 0; |
1616 | return 1; | 1766 | len = read(c->rfd, buf, sizeof(buf)); |
1767 | if (len < 0 && (errno == EINTR || | ||
1768 | ((errno == EAGAIN || errno == EWOULDBLOCK) && !force))) | ||
1769 | return 1; | ||
1617 | #ifndef PTY_ZEROREAD | 1770 | #ifndef PTY_ZEROREAD |
1618 | if (len <= 0) { | 1771 | if (len <= 0) { |
1619 | #else | 1772 | #else |
1620 | if ((!c->isatty && len <= 0) || | 1773 | if ((!c->isatty && len <= 0) || |
1621 | (c->isatty && (len < 0 || (len == 0 && errno != 0)))) { | 1774 | (c->isatty && (len < 0 || (len == 0 && errno != 0)))) { |
1622 | #endif | 1775 | #endif |
1623 | debug2("channel %d: read<=0 rfd %d len %d", | 1776 | debug2("channel %d: read<=0 rfd %d len %zd", |
1624 | c->self, c->rfd, len); | 1777 | c->self, c->rfd, len); |
1625 | if (c->type != SSH_CHANNEL_OPEN) { | 1778 | if (c->type != SSH_CHANNEL_OPEN) { |
1626 | debug2("channel %d: not open", c->self); | 1779 | debug2("channel %d: not open", c->self); |
1627 | chan_mark_dead(c); | 1780 | chan_mark_dead(ssh, c); |
1628 | return -1; | ||
1629 | } else { | ||
1630 | chan_read_failed(c); | ||
1631 | } | ||
1632 | return -1; | 1781 | return -1; |
1633 | } | ||
1634 | if (c->input_filter != NULL) { | ||
1635 | if (c->input_filter(c, buf, len) == -1) { | ||
1636 | debug2("channel %d: filter stops", c->self); | ||
1637 | chan_read_failed(c); | ||
1638 | } | ||
1639 | } else if (c->datagram) { | ||
1640 | buffer_put_string(&c->input, buf, len); | ||
1641 | } else { | 1782 | } else { |
1642 | buffer_append(&c->input, buf, len); | 1783 | chan_read_failed(ssh, c); |
1643 | } | 1784 | } |
1785 | return -1; | ||
1786 | } | ||
1787 | if (c->input_filter != NULL) { | ||
1788 | if (c->input_filter(ssh, c, buf, len) == -1) { | ||
1789 | debug2("channel %d: filter stops", c->self); | ||
1790 | chan_read_failed(ssh, c); | ||
1791 | } | ||
1792 | } else if (c->datagram) { | ||
1793 | if ((r = sshbuf_put_string(c->input, buf, len)) != 0) | ||
1794 | fatal("%s: channel %d: put datagram: %s", __func__, | ||
1795 | c->self, ssh_err(r)); | ||
1796 | } else if ((r = sshbuf_put(c->input, buf, len)) != 0) { | ||
1797 | fatal("%s: channel %d: put data: %s", __func__, | ||
1798 | c->self, ssh_err(r)); | ||
1644 | } | 1799 | } |
1645 | return 1; | 1800 | return 1; |
1646 | } | 1801 | } |
1647 | 1802 | ||
1648 | /* ARGSUSED */ | ||
1649 | static int | 1803 | static int |
1650 | channel_handle_wfd(Channel *c, fd_set *readset, fd_set *writeset) | 1804 | channel_handle_wfd(struct ssh *ssh, Channel *c, |
1805 | fd_set *readset, fd_set *writeset) | ||
1651 | { | 1806 | { |
1652 | struct termios tio; | 1807 | struct termios tio; |
1653 | u_char *data = NULL, *buf; | 1808 | u_char *data = NULL, *buf; /* XXX const; need filter API change */ |
1654 | u_int dlen, olen = 0; | 1809 | size_t dlen, olen = 0; |
1655 | int len; | 1810 | int r, len; |
1811 | |||
1812 | if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) || | ||
1813 | sshbuf_len(c->output) == 0) | ||
1814 | return 1; | ||
1656 | 1815 | ||
1657 | /* Send buffered output data to the socket. */ | 1816 | /* Send buffered output data to the socket. */ |
1658 | if (c->wfd != -1 && | 1817 | olen = sshbuf_len(c->output); |
1659 | FD_ISSET(c->wfd, writeset) && | 1818 | if (c->output_filter != NULL) { |
1660 | buffer_len(&c->output) > 0) { | 1819 | if ((buf = c->output_filter(ssh, c, &data, &dlen)) == NULL) { |
1661 | olen = buffer_len(&c->output); | 1820 | debug2("channel %d: filter stops", c->self); |
1662 | if (c->output_filter != NULL) { | 1821 | if (c->type != SSH_CHANNEL_OPEN) |
1663 | if ((buf = c->output_filter(c, &data, &dlen)) == NULL) { | 1822 | chan_mark_dead(ssh, c); |
1664 | debug2("channel %d: filter stops", c->self); | 1823 | else |
1665 | if (c->type != SSH_CHANNEL_OPEN) | 1824 | chan_write_failed(ssh, c); |
1666 | chan_mark_dead(c); | 1825 | return -1; |
1667 | else | ||
1668 | chan_write_failed(c); | ||
1669 | return -1; | ||
1670 | } | ||
1671 | } else if (c->datagram) { | ||
1672 | buf = data = buffer_get_string(&c->output, &dlen); | ||
1673 | } else { | ||
1674 | buf = data = buffer_ptr(&c->output); | ||
1675 | dlen = buffer_len(&c->output); | ||
1676 | } | 1826 | } |
1827 | } else if (c->datagram) { | ||
1828 | if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0) | ||
1829 | fatal("%s: channel %d: get datagram: %s", __func__, | ||
1830 | c->self, ssh_err(r)); | ||
1831 | } else { | ||
1832 | buf = data = sshbuf_mutable_ptr(c->output); | ||
1833 | dlen = sshbuf_len(c->output); | ||
1834 | } | ||
1835 | |||
1836 | if (c->datagram) { | ||
1837 | /* ignore truncated writes, datagrams might get lost */ | ||
1838 | len = write(c->wfd, data, dlen); | ||
1839 | free(data); | ||
1840 | if (len < 0 && (errno == EINTR || errno == EAGAIN || | ||
1841 | errno == EWOULDBLOCK)) | ||
1842 | return 1; | ||
1843 | if (len <= 0) | ||
1844 | goto write_fail; | ||
1845 | goto out; | ||
1846 | } | ||
1677 | 1847 | ||
1678 | if (c->datagram) { | ||
1679 | /* ignore truncated writes, datagrams might get lost */ | ||
1680 | len = write(c->wfd, buf, dlen); | ||
1681 | free(data); | ||
1682 | if (len < 0 && (errno == EINTR || errno == EAGAIN || | ||
1683 | errno == EWOULDBLOCK)) | ||
1684 | return 1; | ||
1685 | if (len <= 0) { | ||
1686 | if (c->type != SSH_CHANNEL_OPEN) | ||
1687 | chan_mark_dead(c); | ||
1688 | else | ||
1689 | chan_write_failed(c); | ||
1690 | return -1; | ||
1691 | } | ||
1692 | goto out; | ||
1693 | } | ||
1694 | #ifdef _AIX | 1848 | #ifdef _AIX |
1695 | /* XXX: Later AIX versions can't push as much data to tty */ | 1849 | /* XXX: Later AIX versions can't push as much data to tty */ |
1696 | if (c->wfd_isatty) | 1850 | if (c->wfd_isatty) |
1697 | dlen = MIN(dlen, 8*1024); | 1851 | dlen = MIN(dlen, 8*1024); |
1698 | #endif | 1852 | #endif |
1699 | 1853 | ||
1700 | len = write(c->wfd, buf, dlen); | 1854 | len = write(c->wfd, buf, dlen); |
1701 | if (len < 0 && | 1855 | if (len < 0 && |
1702 | (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) | 1856 | (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) |
1703 | return 1; | 1857 | return 1; |
1704 | if (len <= 0) { | 1858 | if (len <= 0) { |
1705 | if (c->type != SSH_CHANNEL_OPEN) { | 1859 | write_fail: |
1706 | debug2("channel %d: not open", c->self); | 1860 | if (c->type != SSH_CHANNEL_OPEN) { |
1707 | chan_mark_dead(c); | 1861 | debug2("channel %d: not open", c->self); |
1708 | return -1; | 1862 | chan_mark_dead(ssh, c); |
1709 | } else { | ||
1710 | chan_write_failed(c); | ||
1711 | } | ||
1712 | return -1; | 1863 | return -1; |
1864 | } else { | ||
1865 | chan_write_failed(ssh, c); | ||
1713 | } | 1866 | } |
1867 | return -1; | ||
1868 | } | ||
1714 | #ifndef BROKEN_TCGETATTR_ICANON | 1869 | #ifndef BROKEN_TCGETATTR_ICANON |
1715 | if (c->isatty && dlen >= 1 && buf[0] != '\r') { | 1870 | if (c->isatty && dlen >= 1 && buf[0] != '\r') { |
1716 | if (tcgetattr(c->wfd, &tio) == 0 && | 1871 | if (tcgetattr(c->wfd, &tio) == 0 && |
1717 | !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { | 1872 | !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { |
1718 | /* | 1873 | /* |
1719 | * Simulate echo to reduce the impact of | 1874 | * Simulate echo to reduce the impact of |
1720 | * traffic analysis. We need to match the | 1875 | * traffic analysis. We need to match the |
1721 | * size of a SSH2_MSG_CHANNEL_DATA message | 1876 | * size of a SSH2_MSG_CHANNEL_DATA message |
1722 | * (4 byte channel id + buf) | 1877 | * (4 byte channel id + buf) |
1723 | */ | 1878 | */ |
1724 | packet_send_ignore(4 + len); | 1879 | if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 || |
1725 | packet_send(); | 1880 | (r = sshpkt_send(ssh)) != 0) |
1726 | } | 1881 | fatal("%s: channel %d: ignore: %s", |
1882 | __func__, c->self, ssh_err(r)); | ||
1727 | } | 1883 | } |
1728 | #endif | 1884 | } |
1729 | buffer_consume(&c->output, len); | 1885 | #endif /* BROKEN_TCGETATTR_ICANON */ |
1886 | if ((r = sshbuf_consume(c->output, len)) != 0) { | ||
1887 | fatal("%s: channel %d: consume: %s", | ||
1888 | __func__, c->self, ssh_err(r)); | ||
1730 | } | 1889 | } |
1731 | out: | 1890 | out: |
1732 | if (olen > 0) | 1891 | c->local_consumed += olen - sshbuf_len(c->output); |
1733 | c->local_consumed += olen - buffer_len(&c->output); | 1892 | |
1893 | return 1; | ||
1894 | } | ||
1895 | |||
1896 | static int | ||
1897 | channel_handle_efd_write(struct ssh *ssh, Channel *c, | ||
1898 | fd_set *readset, fd_set *writeset) | ||
1899 | { | ||
1900 | int r; | ||
1901 | ssize_t len; | ||
1902 | |||
1903 | if (!FD_ISSET(c->efd, writeset) || sshbuf_len(c->extended) == 0) | ||
1904 | return 1; | ||
1905 | |||
1906 | len = write(c->efd, sshbuf_ptr(c->extended), | ||
1907 | sshbuf_len(c->extended)); | ||
1908 | debug2("channel %d: written %zd to efd %d", c->self, len, c->efd); | ||
1909 | if (len < 0 && (errno == EINTR || errno == EAGAIN || | ||
1910 | errno == EWOULDBLOCK)) | ||
1911 | return 1; | ||
1912 | if (len <= 0) { | ||
1913 | debug2("channel %d: closing write-efd %d", c->self, c->efd); | ||
1914 | channel_close_fd(ssh, &c->efd); | ||
1915 | } else { | ||
1916 | if ((r = sshbuf_consume(c->extended, len)) != 0) { | ||
1917 | fatal("%s: channel %d: consume: %s", | ||
1918 | __func__, c->self, ssh_err(r)); | ||
1919 | } | ||
1920 | c->local_consumed += len; | ||
1921 | } | ||
1734 | return 1; | 1922 | return 1; |
1735 | } | 1923 | } |
1736 | 1924 | ||
1737 | static int | 1925 | static int |
1738 | channel_handle_efd(Channel *c, fd_set *readset, fd_set *writeset) | 1926 | channel_handle_efd_read(struct ssh *ssh, Channel *c, |
1927 | fd_set *readset, fd_set *writeset) | ||
1739 | { | 1928 | { |
1740 | char buf[CHAN_RBUF]; | 1929 | char buf[CHAN_RBUF]; |
1741 | int len; | 1930 | int r; |
1931 | ssize_t len; | ||
1742 | 1932 | ||
1743 | /** XXX handle drain efd, too */ | 1933 | if (!c->detach_close && !FD_ISSET(c->efd, readset)) |
1744 | if (c->efd != -1) { | 1934 | return 1; |
1745 | if (c->extended_usage == CHAN_EXTENDED_WRITE && | 1935 | |
1746 | FD_ISSET(c->efd, writeset) && | 1936 | len = read(c->efd, buf, sizeof(buf)); |
1747 | buffer_len(&c->extended) > 0) { | 1937 | debug2("channel %d: read %zd from efd %d", c->self, len, c->efd); |
1748 | len = write(c->efd, buffer_ptr(&c->extended), | 1938 | if (len < 0 && (errno == EINTR || ((errno == EAGAIN || |
1749 | buffer_len(&c->extended)); | 1939 | errno == EWOULDBLOCK) && !c->detach_close))) |
1750 | debug2("channel %d: written %d to efd %d", | 1940 | return 1; |
1751 | c->self, len, c->efd); | 1941 | if (len <= 0) { |
1752 | if (len < 0 && (errno == EINTR || errno == EAGAIN || | 1942 | debug2("channel %d: closing read-efd %d", |
1753 | errno == EWOULDBLOCK)) | 1943 | c->self, c->efd); |
1754 | return 1; | 1944 | channel_close_fd(ssh, &c->efd); |
1755 | if (len <= 0) { | 1945 | } else { |
1756 | debug2("channel %d: closing write-efd %d", | 1946 | if (c->extended_usage == CHAN_EXTENDED_IGNORE) { |
1757 | c->self, c->efd); | 1947 | debug3("channel %d: discard efd", |
1758 | channel_close_fd(&c->efd); | 1948 | c->self); |
1759 | } else { | 1949 | } else if ((r = sshbuf_put(c->extended, buf, len)) != 0) { |
1760 | buffer_consume(&c->extended, len); | 1950 | fatal("%s: channel %d: append: %s", |
1761 | c->local_consumed += len; | 1951 | __func__, c->self, ssh_err(r)); |
1762 | } | ||
1763 | } else if (c->efd != -1 && | ||
1764 | (c->extended_usage == CHAN_EXTENDED_READ || | ||
1765 | c->extended_usage == CHAN_EXTENDED_IGNORE) && | ||
1766 | (c->detach_close || FD_ISSET(c->efd, readset))) { | ||
1767 | len = read(c->efd, buf, sizeof(buf)); | ||
1768 | debug2("channel %d: read %d from efd %d", | ||
1769 | c->self, len, c->efd); | ||
1770 | if (len < 0 && (errno == EINTR || ((errno == EAGAIN || | ||
1771 | errno == EWOULDBLOCK) && !c->detach_close))) | ||
1772 | return 1; | ||
1773 | if (len <= 0) { | ||
1774 | debug2("channel %d: closing read-efd %d", | ||
1775 | c->self, c->efd); | ||
1776 | channel_close_fd(&c->efd); | ||
1777 | } else { | ||
1778 | if (c->extended_usage == CHAN_EXTENDED_IGNORE) { | ||
1779 | debug3("channel %d: discard efd", | ||
1780 | c->self); | ||
1781 | } else | ||
1782 | buffer_append(&c->extended, buf, len); | ||
1783 | } | ||
1784 | } | 1952 | } |
1785 | } | 1953 | } |
1786 | return 1; | 1954 | return 1; |
1787 | } | 1955 | } |
1788 | 1956 | ||
1789 | static int | 1957 | static int |
1790 | channel_check_window(Channel *c) | 1958 | channel_handle_efd(struct ssh *ssh, Channel *c, |
1959 | fd_set *readset, fd_set *writeset) | ||
1960 | { | ||
1961 | if (c->efd == -1) | ||
1962 | return 1; | ||
1963 | |||
1964 | /** XXX handle drain efd, too */ | ||
1965 | |||
1966 | if (c->extended_usage == CHAN_EXTENDED_WRITE) | ||
1967 | return channel_handle_efd_write(ssh, c, readset, writeset); | ||
1968 | else if (c->extended_usage == CHAN_EXTENDED_READ || | ||
1969 | c->extended_usage == CHAN_EXTENDED_IGNORE) | ||
1970 | return channel_handle_efd_read(ssh, c, readset, writeset); | ||
1971 | |||
1972 | return 1; | ||
1973 | } | ||
1974 | |||
1975 | static int | ||
1976 | channel_check_window(struct ssh *ssh, Channel *c) | ||
1791 | { | 1977 | { |
1978 | int r; | ||
1979 | |||
1792 | if (c->type == SSH_CHANNEL_OPEN && | 1980 | if (c->type == SSH_CHANNEL_OPEN && |
1793 | !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && | 1981 | !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) && |
1794 | ((c->local_window_max - c->local_window > | 1982 | ((c->local_window_max - c->local_window > |
1795 | c->local_maxpacket*3) || | 1983 | c->local_maxpacket*3) || |
1796 | c->local_window < c->local_window_max/2) && | 1984 | c->local_window < c->local_window_max/2) && |
1797 | c->local_consumed > 0) { | 1985 | c->local_consumed > 0) { |
1798 | packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST); | 1986 | if ((r = sshpkt_start(ssh, |
1799 | packet_put_int(c->remote_id); | 1987 | SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 || |
1800 | packet_put_int(c->local_consumed); | 1988 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
1801 | packet_send(); | 1989 | (r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 || |
1990 | (r = sshpkt_send(ssh)) != 0) { | ||
1991 | fatal("%s: channel %i: %s", __func__, | ||
1992 | c->self, ssh_err(r)); | ||
1993 | } | ||
1802 | debug2("channel %d: window %d sent adjust %d", | 1994 | debug2("channel %d: window %d sent adjust %d", |
1803 | c->self, c->local_window, | 1995 | c->self, c->local_window, |
1804 | c->local_consumed); | 1996 | c->local_consumed); |
@@ -1809,85 +2001,112 @@ channel_check_window(Channel *c) | |||
1809 | } | 2001 | } |
1810 | 2002 | ||
1811 | static void | 2003 | static void |
1812 | channel_post_open(Channel *c, fd_set *readset, fd_set *writeset) | 2004 | channel_post_open(struct ssh *ssh, Channel *c, |
2005 | fd_set *readset, fd_set *writeset) | ||
1813 | { | 2006 | { |
1814 | channel_handle_rfd(c, readset, writeset); | 2007 | channel_handle_rfd(ssh, c, readset, writeset); |
1815 | channel_handle_wfd(c, readset, writeset); | 2008 | channel_handle_wfd(ssh, c, readset, writeset); |
1816 | channel_handle_efd(c, readset, writeset); | 2009 | channel_handle_efd(ssh, c, readset, writeset); |
1817 | channel_check_window(c); | 2010 | channel_check_window(ssh, c); |
1818 | } | 2011 | } |
1819 | 2012 | ||
1820 | static u_int | 2013 | static u_int |
1821 | read_mux(Channel *c, u_int need) | 2014 | read_mux(struct ssh *ssh, Channel *c, u_int need) |
1822 | { | 2015 | { |
1823 | char buf[CHAN_RBUF]; | 2016 | char buf[CHAN_RBUF]; |
1824 | int len; | 2017 | ssize_t len; |
1825 | u_int rlen; | 2018 | u_int rlen; |
2019 | int r; | ||
1826 | 2020 | ||
1827 | if (buffer_len(&c->input) < need) { | 2021 | if (sshbuf_len(c->input) < need) { |
1828 | rlen = need - buffer_len(&c->input); | 2022 | rlen = need - sshbuf_len(c->input); |
1829 | len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF)); | 2023 | len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF)); |
1830 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) | 2024 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
1831 | return buffer_len(&c->input); | 2025 | return sshbuf_len(c->input); |
1832 | if (len <= 0) { | 2026 | if (len <= 0) { |
1833 | debug2("channel %d: ctl read<=0 rfd %d len %d", | 2027 | debug2("channel %d: ctl read<=0 rfd %d len %zd", |
1834 | c->self, c->rfd, len); | 2028 | c->self, c->rfd, len); |
1835 | chan_read_failed(c); | 2029 | chan_read_failed(ssh, c); |
1836 | return 0; | 2030 | return 0; |
1837 | } else | 2031 | } else if ((r = sshbuf_put(c->input, buf, len)) != 0) { |
1838 | buffer_append(&c->input, buf, len); | 2032 | fatal("%s: channel %d: append: %s", |
2033 | __func__, c->self, ssh_err(r)); | ||
2034 | } | ||
1839 | } | 2035 | } |
1840 | return buffer_len(&c->input); | 2036 | return sshbuf_len(c->input); |
1841 | } | 2037 | } |
1842 | 2038 | ||
1843 | static void | 2039 | static void |
1844 | channel_post_mux_client(Channel *c, fd_set *readset, fd_set *writeset) | 2040 | channel_post_mux_client_read(struct ssh *ssh, Channel *c, |
2041 | fd_set *readset, fd_set *writeset) | ||
1845 | { | 2042 | { |
1846 | u_int need; | 2043 | u_int need; |
1847 | ssize_t len; | ||
1848 | 2044 | ||
1849 | if (c->rfd != -1 && !c->mux_pause && FD_ISSET(c->rfd, readset) && | 2045 | if (c->rfd == -1 || !FD_ISSET(c->rfd, readset)) |
1850 | (c->istate == CHAN_INPUT_OPEN || | 2046 | return; |
1851 | c->istate == CHAN_INPUT_WAIT_DRAIN)) { | 2047 | if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN) |
1852 | /* | 2048 | return; |
1853 | * Don't not read past the precise end of packets to | 2049 | if (c->mux_pause) |
1854 | * avoid disrupting fd passing. | 2050 | return; |
1855 | */ | 2051 | |
1856 | if (read_mux(c, 4) < 4) /* read header */ | 2052 | /* |
1857 | return; | 2053 | * Don't not read past the precise end of packets to |
1858 | need = get_u32(buffer_ptr(&c->input)); | 2054 | * avoid disrupting fd passing. |
2055 | */ | ||
2056 | if (read_mux(ssh, c, 4) < 4) /* read header */ | ||
2057 | return; | ||
2058 | /* XXX sshbuf_peek_u32 */ | ||
2059 | need = PEEK_U32(sshbuf_ptr(c->input)); | ||
1859 | #define CHANNEL_MUX_MAX_PACKET (256 * 1024) | 2060 | #define CHANNEL_MUX_MAX_PACKET (256 * 1024) |
1860 | if (need > CHANNEL_MUX_MAX_PACKET) { | 2061 | if (need > CHANNEL_MUX_MAX_PACKET) { |
1861 | debug2("channel %d: packet too big %u > %u", | 2062 | debug2("channel %d: packet too big %u > %u", |
1862 | c->self, CHANNEL_MUX_MAX_PACKET, need); | 2063 | c->self, CHANNEL_MUX_MAX_PACKET, need); |
1863 | chan_rcvd_oclose(c); | 2064 | chan_rcvd_oclose(ssh, c); |
1864 | return; | 2065 | return; |
1865 | } | ||
1866 | if (read_mux(c, need + 4) < need + 4) /* read body */ | ||
1867 | return; | ||
1868 | if (c->mux_rcb(c) != 0) { | ||
1869 | debug("channel %d: mux_rcb failed", c->self); | ||
1870 | chan_mark_dead(c); | ||
1871 | return; | ||
1872 | } | ||
1873 | } | 2066 | } |
2067 | if (read_mux(ssh, c, need + 4) < need + 4) /* read body */ | ||
2068 | return; | ||
2069 | if (c->mux_rcb(ssh, c) != 0) { | ||
2070 | debug("channel %d: mux_rcb failed", c->self); | ||
2071 | chan_mark_dead(ssh, c); | ||
2072 | return; | ||
2073 | } | ||
2074 | } | ||
1874 | 2075 | ||
1875 | if (c->wfd != -1 && FD_ISSET(c->wfd, writeset) && | 2076 | static void |
1876 | buffer_len(&c->output) > 0) { | 2077 | channel_post_mux_client_write(struct ssh *ssh, Channel *c, |
1877 | len = write(c->wfd, buffer_ptr(&c->output), | 2078 | fd_set *readset, fd_set *writeset) |
1878 | buffer_len(&c->output)); | 2079 | { |
1879 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) | 2080 | ssize_t len; |
1880 | return; | 2081 | int r; |
1881 | if (len <= 0) { | 2082 | |
1882 | chan_mark_dead(c); | 2083 | if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) || |
1883 | return; | 2084 | sshbuf_len(c->output) == 0) |
1884 | } | 2085 | return; |
1885 | buffer_consume(&c->output, len); | 2086 | |
2087 | len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output)); | ||
2088 | if (len < 0 && (errno == EINTR || errno == EAGAIN)) | ||
2089 | return; | ||
2090 | if (len <= 0) { | ||
2091 | chan_mark_dead(ssh, c); | ||
2092 | return; | ||
1886 | } | 2093 | } |
2094 | if ((r = sshbuf_consume(c->output, len)) != 0) | ||
2095 | fatal("%s: channel %d: consume: %s", __func__, | ||
2096 | c->self, ssh_err(r)); | ||
2097 | } | ||
2098 | |||
2099 | static void | ||
2100 | channel_post_mux_client(struct ssh *ssh, Channel *c, | ||
2101 | fd_set *readset, fd_set *writeset) | ||
2102 | { | ||
2103 | channel_post_mux_client_read(ssh, c, readset, writeset); | ||
2104 | channel_post_mux_client_write(ssh, c, readset, writeset); | ||
1887 | } | 2105 | } |
1888 | 2106 | ||
1889 | static void | 2107 | static void |
1890 | channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset) | 2108 | channel_post_mux_listener(struct ssh *ssh, Channel *c, |
2109 | fd_set *readset, fd_set *writeset) | ||
1891 | { | 2110 | { |
1892 | Channel *nc; | 2111 | Channel *nc; |
1893 | struct sockaddr_storage addr; | 2112 | struct sockaddr_storage addr; |
@@ -1926,97 +2145,98 @@ channel_post_mux_listener(Channel *c, fd_set *readset, fd_set *writeset) | |||
1926 | close(newsock); | 2145 | close(newsock); |
1927 | return; | 2146 | return; |
1928 | } | 2147 | } |
1929 | nc = channel_new("multiplex client", SSH_CHANNEL_MUX_CLIENT, | 2148 | nc = channel_new(ssh, "multiplex client", SSH_CHANNEL_MUX_CLIENT, |
1930 | newsock, newsock, -1, c->local_window_max, | 2149 | newsock, newsock, -1, c->local_window_max, |
1931 | c->local_maxpacket, 0, "mux-control", 1); | 2150 | c->local_maxpacket, 0, "mux-control", 1); |
1932 | nc->mux_rcb = c->mux_rcb; | 2151 | nc->mux_rcb = c->mux_rcb; |
1933 | debug3("%s: new mux channel %d fd %d", __func__, | 2152 | debug3("%s: new mux channel %d fd %d", __func__, nc->self, nc->sock); |
1934 | nc->self, nc->sock); | ||
1935 | /* establish state */ | 2153 | /* establish state */ |
1936 | nc->mux_rcb(nc); | 2154 | nc->mux_rcb(ssh, nc); |
1937 | /* mux state transitions must not elicit protocol messages */ | 2155 | /* mux state transitions must not elicit protocol messages */ |
1938 | nc->flags |= CHAN_LOCAL; | 2156 | nc->flags |= CHAN_LOCAL; |
1939 | } | 2157 | } |
1940 | 2158 | ||
1941 | static void | 2159 | static void |
1942 | channel_handler_init(void) | 2160 | channel_handler_init(struct ssh_channels *sc) |
1943 | { | 2161 | { |
1944 | int i; | 2162 | chan_fn **pre, **post; |
1945 | 2163 | ||
1946 | for (i = 0; i < SSH_CHANNEL_MAX_TYPE; i++) { | 2164 | if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL || |
1947 | channel_pre[i] = NULL; | 2165 | (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL) |
1948 | channel_post[i] = NULL; | 2166 | fatal("%s: allocation failed", __func__); |
1949 | } | 2167 | |
1950 | channel_pre[SSH_CHANNEL_OPEN] = &channel_pre_open; | 2168 | pre[SSH_CHANNEL_OPEN] = &channel_pre_open; |
1951 | channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; | 2169 | pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; |
1952 | channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | 2170 | pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; |
1953 | channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; | 2171 | pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; |
1954 | channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; | 2172 | pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; |
1955 | channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; | 2173 | pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; |
1956 | channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; | 2174 | pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; |
1957 | channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; | 2175 | pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; |
1958 | channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; | 2176 | pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; |
1959 | channel_pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; | 2177 | pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; |
1960 | channel_pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; | 2178 | pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; |
1961 | channel_pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; | 2179 | pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; |
1962 | 2180 | ||
1963 | channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; | 2181 | post[SSH_CHANNEL_OPEN] = &channel_post_open; |
1964 | channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | 2182 | post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; |
1965 | channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; | 2183 | post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; |
1966 | channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; | 2184 | post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; |
1967 | channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; | 2185 | post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; |
1968 | channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; | 2186 | post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; |
1969 | channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | 2187 | post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; |
1970 | channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; | 2188 | post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; |
1971 | channel_post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; | 2189 | post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; |
1972 | channel_post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; | 2190 | post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; |
1973 | channel_post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; | 2191 | post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; |
2192 | |||
2193 | sc->channel_pre = pre; | ||
2194 | sc->channel_post = post; | ||
1974 | } | 2195 | } |
1975 | 2196 | ||
1976 | /* gc dead channels */ | 2197 | /* gc dead channels */ |
1977 | static void | 2198 | static void |
1978 | channel_garbage_collect(Channel *c) | 2199 | channel_garbage_collect(struct ssh *ssh, Channel *c) |
1979 | { | 2200 | { |
1980 | if (c == NULL) | 2201 | if (c == NULL) |
1981 | return; | 2202 | return; |
1982 | if (c->detach_user != NULL) { | 2203 | if (c->detach_user != NULL) { |
1983 | if (!chan_is_dead(c, c->detach_close)) | 2204 | if (!chan_is_dead(ssh, c, c->detach_close)) |
1984 | return; | 2205 | return; |
1985 | debug2("channel %d: gc: notify user", c->self); | 2206 | debug2("channel %d: gc: notify user", c->self); |
1986 | c->detach_user(c->self, NULL); | 2207 | c->detach_user(ssh, c->self, NULL); |
1987 | /* if we still have a callback */ | 2208 | /* if we still have a callback */ |
1988 | if (c->detach_user != NULL) | 2209 | if (c->detach_user != NULL) |
1989 | return; | 2210 | return; |
1990 | debug2("channel %d: gc: user detached", c->self); | 2211 | debug2("channel %d: gc: user detached", c->self); |
1991 | } | 2212 | } |
1992 | if (!chan_is_dead(c, 1)) | 2213 | if (!chan_is_dead(ssh, c, 1)) |
1993 | return; | 2214 | return; |
1994 | debug2("channel %d: garbage collecting", c->self); | 2215 | debug2("channel %d: garbage collecting", c->self); |
1995 | channel_free(c); | 2216 | channel_free(ssh, c); |
1996 | } | 2217 | } |
1997 | 2218 | ||
2219 | enum channel_table { CHAN_PRE, CHAN_POST }; | ||
2220 | |||
1998 | static void | 2221 | static void |
1999 | channel_handler(struct ssh *ssh, chan_fn *ftab[], | 2222 | channel_handler(struct ssh *ssh, int table, |
2000 | fd_set *readset, fd_set *writeset, time_t *unpause_secs) | 2223 | fd_set *readset, fd_set *writeset, time_t *unpause_secs) |
2001 | { | 2224 | { |
2002 | static int did_init = 0; | 2225 | struct ssh_channels *sc = ssh->chanctxt; |
2226 | chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post; | ||
2003 | u_int i, oalloc; | 2227 | u_int i, oalloc; |
2004 | Channel *c; | 2228 | Channel *c; |
2005 | time_t now; | 2229 | time_t now; |
2006 | 2230 | ||
2007 | if (!did_init) { | ||
2008 | channel_handler_init(); | ||
2009 | did_init = 1; | ||
2010 | } | ||
2011 | now = monotime(); | 2231 | now = monotime(); |
2012 | if (unpause_secs != NULL) | 2232 | if (unpause_secs != NULL) |
2013 | *unpause_secs = 0; | 2233 | *unpause_secs = 0; |
2014 | for (i = 0, oalloc = channels_alloc; i < oalloc; i++) { | 2234 | for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) { |
2015 | c = channels[i]; | 2235 | c = sc->channels[i]; |
2016 | if (c == NULL) | 2236 | if (c == NULL) |
2017 | continue; | 2237 | continue; |
2018 | if (c->delayed) { | 2238 | if (c->delayed) { |
2019 | if (ftab == channel_pre) | 2239 | if (table == CHAN_PRE) |
2020 | c->delayed = 0; | 2240 | c->delayed = 0; |
2021 | else | 2241 | else |
2022 | continue; | 2242 | continue; |
@@ -2026,7 +2246,7 @@ channel_handler(struct ssh *ssh, chan_fn *ftab[], | |||
2026 | * Run handlers that are not paused. | 2246 | * Run handlers that are not paused. |
2027 | */ | 2247 | */ |
2028 | if (c->notbefore <= now) | 2248 | if (c->notbefore <= now) |
2029 | (*ftab[c->type])(c, readset, writeset); | 2249 | (*ftab[c->type])(ssh, c, readset, writeset); |
2030 | else if (unpause_secs != NULL) { | 2250 | else if (unpause_secs != NULL) { |
2031 | /* | 2251 | /* |
2032 | * Collect the time that the earliest | 2252 | * Collect the time that the earliest |
@@ -2040,7 +2260,7 @@ channel_handler(struct ssh *ssh, chan_fn *ftab[], | |||
2040 | *unpause_secs = c->notbefore - now; | 2260 | *unpause_secs = c->notbefore - now; |
2041 | } | 2261 | } |
2042 | } | 2262 | } |
2043 | channel_garbage_collect(c); | 2263 | channel_garbage_collect(ssh, c); |
2044 | } | 2264 | } |
2045 | if (unpause_secs != NULL && *unpause_secs != 0) | 2265 | if (unpause_secs != NULL && *unpause_secs != 0) |
2046 | debug3("%s: first channel unpauses in %d seconds", | 2266 | debug3("%s: first channel unpauses in %d seconds", |
@@ -2057,7 +2277,7 @@ channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp, | |||
2057 | { | 2277 | { |
2058 | u_int n, sz, nfdset; | 2278 | u_int n, sz, nfdset; |
2059 | 2279 | ||
2060 | n = MAXIMUM(*maxfdp, channel_max_fd); | 2280 | n = MAXIMUM(*maxfdp, ssh->chanctxt->channel_max_fd); |
2061 | 2281 | ||
2062 | nfdset = howmany(n+1, NFDBITS); | 2282 | nfdset = howmany(n+1, NFDBITS); |
2063 | /* Explicitly test here, because xrealloc isn't always called */ | 2283 | /* Explicitly test here, because xrealloc isn't always called */ |
@@ -2076,7 +2296,7 @@ channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp, | |||
2076 | memset(*writesetp, 0, sz); | 2296 | memset(*writesetp, 0, sz); |
2077 | 2297 | ||
2078 | if (!ssh_packet_is_rekeying(ssh)) | 2298 | if (!ssh_packet_is_rekeying(ssh)) |
2079 | channel_handler(ssh, channel_pre, *readsetp, *writesetp, | 2299 | channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp, |
2080 | minwait_secs); | 2300 | minwait_secs); |
2081 | } | 2301 | } |
2082 | 2302 | ||
@@ -2087,19 +2307,128 @@ channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp, | |||
2087 | void | 2307 | void |
2088 | channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset) | 2308 | channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset) |
2089 | { | 2309 | { |
2090 | channel_handler(ssh, channel_post, readset, writeset, NULL); | 2310 | channel_handler(ssh, CHAN_POST, readset, writeset, NULL); |
2311 | } | ||
2312 | |||
2313 | /* | ||
2314 | * Enqueue data for channels with open or draining c->input. | ||
2315 | */ | ||
2316 | static void | ||
2317 | channel_output_poll_input_open(struct ssh *ssh, Channel *c) | ||
2318 | { | ||
2319 | size_t len, dlen; | ||
2320 | int r; | ||
2321 | |||
2322 | if ((len = sshbuf_len(c->input)) == 0) { | ||
2323 | if (c->istate == CHAN_INPUT_WAIT_DRAIN) { | ||
2324 | /* | ||
2325 | * input-buffer is empty and read-socket shutdown: | ||
2326 | * tell peer, that we will not send more data: | ||
2327 | * send IEOF. | ||
2328 | * hack for extended data: delay EOF if EFD still | ||
2329 | * in use. | ||
2330 | */ | ||
2331 | if (CHANNEL_EFD_INPUT_ACTIVE(c)) | ||
2332 | debug2("channel %d: " | ||
2333 | "ibuf_empty delayed efd %d/(%zu)", | ||
2334 | c->self, c->efd, sshbuf_len(c->extended)); | ||
2335 | else | ||
2336 | chan_ibuf_empty(ssh, c); | ||
2337 | } | ||
2338 | return; | ||
2339 | } | ||
2340 | |||
2341 | if (c->datagram) { | ||
2342 | /* Check datagram will fit; drop if not */ | ||
2343 | if ((r = sshbuf_peek_string_direct(c->input, NULL, &dlen)) != 0) | ||
2344 | fatal("%s: channel %d: peek datagram: %s", __func__, | ||
2345 | c->self, ssh_err(r)); | ||
2346 | /* | ||
2347 | * XXX this does tail-drop on the datagram queue which is | ||
2348 | * usually suboptimal compared to head-drop. Better to have | ||
2349 | * backpressure at read time? (i.e. read + discard) | ||
2350 | */ | ||
2351 | if (dlen > c->remote_window || dlen > c->remote_maxpacket) { | ||
2352 | debug("channel %d: datagram too big", c->self); | ||
2353 | return; | ||
2354 | } | ||
2355 | /* Enqueue it */ | ||
2356 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || | ||
2357 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || | ||
2358 | (r = sshpkt_put_stringb(ssh, c->input)) != 0 || | ||
2359 | (r = sshpkt_send(ssh)) != 0) { | ||
2360 | fatal("%s: channel %i: datagram: %s", __func__, | ||
2361 | c->self, ssh_err(r)); | ||
2362 | } | ||
2363 | c->remote_window -= dlen; | ||
2364 | return; | ||
2365 | } | ||
2366 | |||
2367 | /* Enqueue packet for buffered data. */ | ||
2368 | if (len > c->remote_window) | ||
2369 | len = c->remote_window; | ||
2370 | if (len > c->remote_maxpacket) | ||
2371 | len = c->remote_maxpacket; | ||
2372 | if (len == 0) | ||
2373 | return; | ||
2374 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || | ||
2375 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || | ||
2376 | (r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 || | ||
2377 | (r = sshpkt_send(ssh)) != 0) { | ||
2378 | fatal("%s: channel %i: data: %s", __func__, | ||
2379 | c->self, ssh_err(r)); | ||
2380 | } | ||
2381 | if ((r = sshbuf_consume(c->input, len)) != 0) | ||
2382 | fatal("%s: channel %i: consume: %s", __func__, | ||
2383 | c->self, ssh_err(r)); | ||
2384 | c->remote_window -= len; | ||
2091 | } | 2385 | } |
2092 | 2386 | ||
2387 | /* | ||
2388 | * Enqueue data for channels with open c->extended in read mode. | ||
2389 | */ | ||
2390 | static void | ||
2391 | channel_output_poll_extended_read(struct ssh *ssh, Channel *c) | ||
2392 | { | ||
2393 | size_t len; | ||
2394 | int r; | ||
2395 | |||
2396 | if ((len = sshbuf_len(c->extended)) == 0) | ||
2397 | return; | ||
2398 | |||
2399 | debug2("channel %d: rwin %u elen %zu euse %d", c->self, | ||
2400 | c->remote_window, sshbuf_len(c->extended), c->extended_usage); | ||
2401 | if (len > c->remote_window) | ||
2402 | len = c->remote_window; | ||
2403 | if (len > c->remote_maxpacket) | ||
2404 | len = c->remote_maxpacket; | ||
2405 | if (len == 0) | ||
2406 | return; | ||
2407 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 || | ||
2408 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || | ||
2409 | (r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 || | ||
2410 | (r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 || | ||
2411 | (r = sshpkt_send(ssh)) != 0) { | ||
2412 | fatal("%s: channel %i: data: %s", __func__, | ||
2413 | c->self, ssh_err(r)); | ||
2414 | } | ||
2415 | if ((r = sshbuf_consume(c->extended, len)) != 0) | ||
2416 | fatal("%s: channel %i: consume: %s", __func__, | ||
2417 | c->self, ssh_err(r)); | ||
2418 | c->remote_window -= len; | ||
2419 | debug2("channel %d: sent ext data %zu", c->self, len); | ||
2420 | } | ||
2093 | 2421 | ||
2094 | /* If there is data to send to the connection, enqueue some of it now. */ | 2422 | /* If there is data to send to the connection, enqueue some of it now. */ |
2095 | void | 2423 | void |
2096 | channel_output_poll(void) | 2424 | channel_output_poll(struct ssh *ssh) |
2097 | { | 2425 | { |
2426 | struct ssh_channels *sc = ssh->chanctxt; | ||
2098 | Channel *c; | 2427 | Channel *c; |
2099 | u_int i, len; | 2428 | u_int i; |
2100 | 2429 | ||
2101 | for (i = 0; i < channels_alloc; i++) { | 2430 | for (i = 0; i < sc->channels_alloc; i++) { |
2102 | c = channels[i]; | 2431 | c = sc->channels[i]; |
2103 | if (c == NULL) | 2432 | if (c == NULL) |
2104 | continue; | 2433 | continue; |
2105 | 2434 | ||
@@ -2111,87 +2440,19 @@ channel_output_poll(void) | |||
2111 | continue; | 2440 | continue; |
2112 | if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { | 2441 | if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) { |
2113 | /* XXX is this true? */ | 2442 | /* XXX is this true? */ |
2114 | debug3("channel %d: will not send data after close", c->self); | 2443 | debug3("channel %d: will not send data after close", |
2444 | c->self); | ||
2115 | continue; | 2445 | continue; |
2116 | } | 2446 | } |
2117 | 2447 | ||
2118 | /* Get the amount of buffered data for this channel. */ | 2448 | /* Get the amount of buffered data for this channel. */ |
2119 | if ((c->istate == CHAN_INPUT_OPEN || | 2449 | if (c->istate == CHAN_INPUT_OPEN || |
2120 | c->istate == CHAN_INPUT_WAIT_DRAIN) && | 2450 | c->istate == CHAN_INPUT_WAIT_DRAIN) |
2121 | (len = buffer_len(&c->input)) > 0) { | 2451 | channel_output_poll_input_open(ssh, c); |
2122 | if (c->datagram) { | ||
2123 | if (len > 0) { | ||
2124 | u_char *data; | ||
2125 | u_int dlen; | ||
2126 | |||
2127 | data = buffer_get_string(&c->input, | ||
2128 | &dlen); | ||
2129 | if (dlen > c->remote_window || | ||
2130 | dlen > c->remote_maxpacket) { | ||
2131 | debug("channel %d: datagram " | ||
2132 | "too big for channel", | ||
2133 | c->self); | ||
2134 | free(data); | ||
2135 | continue; | ||
2136 | } | ||
2137 | packet_start(SSH2_MSG_CHANNEL_DATA); | ||
2138 | packet_put_int(c->remote_id); | ||
2139 | packet_put_string(data, dlen); | ||
2140 | packet_send(); | ||
2141 | c->remote_window -= dlen; | ||
2142 | free(data); | ||
2143 | } | ||
2144 | continue; | ||
2145 | } | ||
2146 | /* | ||
2147 | * Send some data for the other side over the secure | ||
2148 | * connection. | ||
2149 | */ | ||
2150 | if (len > c->remote_window) | ||
2151 | len = c->remote_window; | ||
2152 | if (len > c->remote_maxpacket) | ||
2153 | len = c->remote_maxpacket; | ||
2154 | if (len > 0) { | ||
2155 | packet_start(SSH2_MSG_CHANNEL_DATA); | ||
2156 | packet_put_int(c->remote_id); | ||
2157 | packet_put_string(buffer_ptr(&c->input), len); | ||
2158 | packet_send(); | ||
2159 | buffer_consume(&c->input, len); | ||
2160 | c->remote_window -= len; | ||
2161 | } | ||
2162 | } else if (c->istate == CHAN_INPUT_WAIT_DRAIN) { | ||
2163 | /* | ||
2164 | * input-buffer is empty and read-socket shutdown: | ||
2165 | * tell peer, that we will not send more data: send IEOF. | ||
2166 | * hack for extended data: delay EOF if EFD still in use. | ||
2167 | */ | ||
2168 | if (CHANNEL_EFD_INPUT_ACTIVE(c)) | ||
2169 | debug2("channel %d: ibuf_empty delayed efd %d/(%d)", | ||
2170 | c->self, c->efd, buffer_len(&c->extended)); | ||
2171 | else | ||
2172 | chan_ibuf_empty(c); | ||
2173 | } | ||
2174 | /* Send extended data, i.e. stderr */ | 2452 | /* Send extended data, i.e. stderr */ |
2175 | if (!(c->flags & CHAN_EOF_SENT) && | 2453 | if (!(c->flags & CHAN_EOF_SENT) && |
2176 | c->remote_window > 0 && | 2454 | c->extended_usage == CHAN_EXTENDED_READ) |
2177 | (len = buffer_len(&c->extended)) > 0 && | 2455 | channel_output_poll_extended_read(ssh, c); |
2178 | c->extended_usage == CHAN_EXTENDED_READ) { | ||
2179 | debug2("channel %d: rwin %u elen %u euse %d", | ||
2180 | c->self, c->remote_window, buffer_len(&c->extended), | ||
2181 | c->extended_usage); | ||
2182 | if (len > c->remote_window) | ||
2183 | len = c->remote_window; | ||
2184 | if (len > c->remote_maxpacket) | ||
2185 | len = c->remote_maxpacket; | ||
2186 | packet_start(SSH2_MSG_CHANNEL_EXTENDED_DATA); | ||
2187 | packet_put_int(c->remote_id); | ||
2188 | packet_put_int(SSH2_EXTENDED_DATA_STDERR); | ||
2189 | packet_put_string(buffer_ptr(&c->extended), len); | ||
2190 | packet_send(); | ||
2191 | buffer_consume(&c->extended, len); | ||
2192 | c->remote_window -= len; | ||
2193 | debug2("channel %d: sent ext data %d", c->self, len); | ||
2194 | } | ||
2195 | } | 2456 | } |
2196 | } | 2457 | } |
2197 | 2458 | ||
@@ -2236,10 +2497,9 @@ channel_output_poll(void) | |||
2236 | * on channel creation. | 2497 | * on channel creation. |
2237 | */ | 2498 | */ |
2238 | int | 2499 | int |
2239 | channel_proxy_downstream(Channel *downstream) | 2500 | channel_proxy_downstream(struct ssh *ssh, Channel *downstream) |
2240 | { | 2501 | { |
2241 | Channel *c = NULL; | 2502 | Channel *c = NULL; |
2242 | struct ssh *ssh = active_state; | ||
2243 | struct sshbuf *original = NULL, *modified = NULL; | 2503 | struct sshbuf *original = NULL, *modified = NULL; |
2244 | const u_char *cp; | 2504 | const u_char *cp; |
2245 | char *ctype = NULL, *listen_host = NULL; | 2505 | char *ctype = NULL, *listen_host = NULL; |
@@ -2248,8 +2508,8 @@ channel_proxy_downstream(Channel *downstream) | |||
2248 | int ret = -1, r, idx; | 2508 | int ret = -1, r, idx; |
2249 | u_int id, remote_id, listen_port; | 2509 | u_int id, remote_id, listen_port; |
2250 | 2510 | ||
2251 | /* sshbuf_dump(&downstream->input, stderr); */ | 2511 | /* sshbuf_dump(downstream->input, stderr); */ |
2252 | if ((r = sshbuf_get_string_direct(&downstream->input, &cp, &have)) | 2512 | if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have)) |
2253 | != 0) { | 2513 | != 0) { |
2254 | error("%s: malformed message: %s", __func__, ssh_err(r)); | 2514 | error("%s: malformed message: %s", __func__, ssh_err(r)); |
2255 | return -1; | 2515 | return -1; |
@@ -2278,7 +2538,7 @@ channel_proxy_downstream(Channel *downstream) | |||
2278 | error("%s: parse error %s", __func__, ssh_err(r)); | 2538 | error("%s: parse error %s", __func__, ssh_err(r)); |
2279 | goto out; | 2539 | goto out; |
2280 | } | 2540 | } |
2281 | c = channel_new("mux proxy", SSH_CHANNEL_MUX_PROXY, | 2541 | c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY, |
2282 | -1, -1, -1, 0, 0, 0, ctype, 1); | 2542 | -1, -1, -1, 0, 0, 0, ctype, 1); |
2283 | c->mux_ctx = downstream; /* point to mux client */ | 2543 | c->mux_ctx = downstream; /* point to mux client */ |
2284 | c->mux_downstream_id = id; /* original downstream id */ | 2544 | c->mux_downstream_id = id; /* original downstream id */ |
@@ -2286,7 +2546,7 @@ channel_proxy_downstream(Channel *downstream) | |||
2286 | (r = sshbuf_put_u32(modified, c->self)) != 0 || | 2546 | (r = sshbuf_put_u32(modified, c->self)) != 0 || |
2287 | (r = sshbuf_putb(modified, original)) != 0) { | 2547 | (r = sshbuf_putb(modified, original)) != 0) { |
2288 | error("%s: compose error %s", __func__, ssh_err(r)); | 2548 | error("%s: compose error %s", __func__, ssh_err(r)); |
2289 | channel_free(c); | 2549 | channel_free(ssh, c); |
2290 | goto out; | 2550 | goto out; |
2291 | } | 2551 | } |
2292 | break; | 2552 | break; |
@@ -2305,7 +2565,7 @@ channel_proxy_downstream(Channel *downstream) | |||
2305 | error("%s: parse error %s", __func__, ssh_err(r)); | 2565 | error("%s: parse error %s", __func__, ssh_err(r)); |
2306 | goto out; | 2566 | goto out; |
2307 | } | 2567 | } |
2308 | c = channel_new("mux proxy", SSH_CHANNEL_MUX_PROXY, | 2568 | c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY, |
2309 | -1, -1, -1, 0, 0, 0, "mux-down-connect", 1); | 2569 | -1, -1, -1, 0, 0, 0, "mux-down-connect", 1); |
2310 | c->mux_ctx = downstream; /* point to mux client */ | 2570 | c->mux_ctx = downstream; /* point to mux client */ |
2311 | c->mux_downstream_id = id; | 2571 | c->mux_downstream_id = id; |
@@ -2314,7 +2574,7 @@ channel_proxy_downstream(Channel *downstream) | |||
2314 | (r = sshbuf_put_u32(modified, c->self)) != 0 || | 2574 | (r = sshbuf_put_u32(modified, c->self)) != 0 || |
2315 | (r = sshbuf_putb(modified, original)) != 0) { | 2575 | (r = sshbuf_putb(modified, original)) != 0) { |
2316 | error("%s: compose error %s", __func__, ssh_err(r)); | 2576 | error("%s: compose error %s", __func__, ssh_err(r)); |
2317 | channel_free(c); | 2577 | channel_free(ssh, c); |
2318 | goto out; | 2578 | goto out; |
2319 | } | 2579 | } |
2320 | break; | 2580 | break; |
@@ -2343,23 +2603,17 @@ channel_proxy_downstream(Channel *downstream) | |||
2343 | goto out; | 2603 | goto out; |
2344 | } | 2604 | } |
2345 | /* Record that connection to this host/port is permitted. */ | 2605 | /* Record that connection to this host/port is permitted. */ |
2346 | permitted_opens = xreallocarray(permitted_opens, | 2606 | idx = fwd_perm_list_add(ssh, FWDPERM_USER, "<mux>", -1, |
2347 | num_permitted_opens + 1, sizeof(*permitted_opens)); | 2607 | listen_host, NULL, (int)listen_port, downstream); |
2348 | idx = num_permitted_opens++; | ||
2349 | permitted_opens[idx].host_to_connect = xstrdup("<mux>"); | ||
2350 | permitted_opens[idx].port_to_connect = -1; | ||
2351 | permitted_opens[idx].listen_host = listen_host; | ||
2352 | permitted_opens[idx].listen_port = (int)listen_port; | ||
2353 | permitted_opens[idx].downstream = downstream; | ||
2354 | listen_host = NULL; | 2608 | listen_host = NULL; |
2355 | break; | 2609 | break; |
2356 | case SSH2_MSG_CHANNEL_CLOSE: | 2610 | case SSH2_MSG_CHANNEL_CLOSE: |
2357 | if (have < 4) | 2611 | if (have < 4) |
2358 | break; | 2612 | break; |
2359 | remote_id = PEEK_U32(cp); | 2613 | remote_id = PEEK_U32(cp); |
2360 | if ((c = channel_by_remote_id(remote_id)) != NULL) { | 2614 | if ((c = channel_by_remote_id(ssh, remote_id)) != NULL) { |
2361 | if (c->flags & CHAN_CLOSE_RCVD) | 2615 | if (c->flags & CHAN_CLOSE_RCVD) |
2362 | channel_free(c); | 2616 | channel_free(ssh, c); |
2363 | else | 2617 | else |
2364 | c->flags |= CHAN_CLOSE_SENT; | 2618 | c->flags |= CHAN_CLOSE_SENT; |
2365 | } | 2619 | } |
@@ -2446,7 +2700,7 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) | |||
2446 | (r = sshbuf_put_u8(b, type)) != 0 || | 2700 | (r = sshbuf_put_u8(b, type)) != 0 || |
2447 | (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 || | 2701 | (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 || |
2448 | (r = sshbuf_put(b, cp, len)) != 0 || | 2702 | (r = sshbuf_put(b, cp, len)) != 0 || |
2449 | (r = sshbuf_put_stringb(&downstream->output, b)) != 0) { | 2703 | (r = sshbuf_put_stringb(downstream->output, b)) != 0) { |
2450 | error("%s: compose for muxclient %s", __func__, ssh_err(r)); | 2704 | error("%s: compose for muxclient %s", __func__, ssh_err(r)); |
2451 | goto out; | 2705 | goto out; |
2452 | } | 2706 | } |
@@ -2464,7 +2718,7 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) | |||
2464 | break; | 2718 | break; |
2465 | case SSH2_MSG_CHANNEL_CLOSE: | 2719 | case SSH2_MSG_CHANNEL_CLOSE: |
2466 | if (c->flags & CHAN_CLOSE_SENT) | 2720 | if (c->flags & CHAN_CLOSE_SENT) |
2467 | channel_free(c); | 2721 | channel_free(ssh, c); |
2468 | else | 2722 | else |
2469 | c->flags |= CHAN_CLOSE_RCVD; | 2723 | c->flags |= CHAN_CLOSE_RCVD; |
2470 | break; | 2724 | break; |
@@ -2475,20 +2729,46 @@ channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) | |||
2475 | 2729 | ||
2476 | /* -- protocol input */ | 2730 | /* -- protocol input */ |
2477 | 2731 | ||
2478 | /* ARGSUSED */ | 2732 | /* Parse a channel ID from the current packet */ |
2733 | static int | ||
2734 | channel_parse_id(struct ssh *ssh, const char *where, const char *what) | ||
2735 | { | ||
2736 | u_int32_t id; | ||
2737 | int r; | ||
2738 | |||
2739 | if ((r = sshpkt_get_u32(ssh, &id)) != 0) { | ||
2740 | error("%s: parse id: %s", where, ssh_err(r)); | ||
2741 | ssh_packet_disconnect(ssh, "Invalid %s message", what); | ||
2742 | } | ||
2743 | if (id > INT_MAX) { | ||
2744 | error("%s: bad channel id %u: %s", where, id, ssh_err(r)); | ||
2745 | ssh_packet_disconnect(ssh, "Invalid %s channel id", what); | ||
2746 | } | ||
2747 | return (int)id; | ||
2748 | } | ||
2749 | |||
2750 | /* Lookup a channel from an ID in the current packet */ | ||
2751 | static Channel * | ||
2752 | channel_from_packet_id(struct ssh *ssh, const char *where, const char *what) | ||
2753 | { | ||
2754 | int id = channel_parse_id(ssh, where, what); | ||
2755 | Channel *c; | ||
2756 | |||
2757 | if ((c = channel_lookup(ssh, id)) == NULL) { | ||
2758 | ssh_packet_disconnect(ssh, | ||
2759 | "%s packet referred to nonexistent channel %d", what, id); | ||
2760 | } | ||
2761 | return c; | ||
2762 | } | ||
2763 | |||
2479 | int | 2764 | int |
2480 | channel_input_data(int type, u_int32_t seq, struct ssh *ssh) | 2765 | channel_input_data(int type, u_int32_t seq, struct ssh *ssh) |
2481 | { | 2766 | { |
2482 | int id; | ||
2483 | const u_char *data; | 2767 | const u_char *data; |
2484 | u_int data_len, win_len; | 2768 | size_t data_len, win_len; |
2485 | Channel *c; | 2769 | Channel *c = channel_from_packet_id(ssh, __func__, "data"); |
2770 | int r; | ||
2486 | 2771 | ||
2487 | /* Get the channel number and verify it. */ | ||
2488 | id = packet_get_int(); | ||
2489 | c = channel_lookup(id); | ||
2490 | if (c == NULL) | ||
2491 | packet_disconnect("Received data for nonexistent channel %d.", id); | ||
2492 | if (channel_proxy_upstream(c, type, seq, ssh)) | 2772 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2493 | return 0; | 2773 | return 0; |
2494 | 2774 | ||
@@ -2498,17 +2778,19 @@ channel_input_data(int type, u_int32_t seq, struct ssh *ssh) | |||
2498 | return 0; | 2778 | return 0; |
2499 | 2779 | ||
2500 | /* Get the data. */ | 2780 | /* Get the data. */ |
2501 | data = packet_get_string_ptr(&data_len); | 2781 | if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) |
2782 | fatal("%s: channel %d: get data: %s", __func__, | ||
2783 | c->self, ssh_err(r)); | ||
2784 | ssh_packet_check_eom(ssh); | ||
2785 | |||
2502 | win_len = data_len; | 2786 | win_len = data_len; |
2503 | if (c->datagram) | 2787 | if (c->datagram) |
2504 | win_len += 4; /* string length header */ | 2788 | win_len += 4; /* string length header */ |
2505 | 2789 | ||
2506 | /* | 2790 | /* |
2507 | * Ignore data for protocol > 1.3 if output end is no longer open. | 2791 | * The sending side reduces its window as it sends data, so we |
2508 | * For protocol 2 the sending side is reducing its window as it sends | 2792 | * must 'fake' consumption of the data in order to ensure that window |
2509 | * data, so we must 'fake' consumption of the data in order to ensure | 2793 | * updates are sent back. Otherwise the connection might deadlock. |
2510 | * that window updates are sent back. Otherwise the connection might | ||
2511 | * deadlock. | ||
2512 | */ | 2794 | */ |
2513 | if (c->ostate != CHAN_OUTPUT_OPEN) { | 2795 | if (c->ostate != CHAN_OUTPUT_OPEN) { |
2514 | c->local_window -= win_len; | 2796 | c->local_window -= win_len; |
@@ -2517,149 +2799,148 @@ channel_input_data(int type, u_int32_t seq, struct ssh *ssh) | |||
2517 | } | 2799 | } |
2518 | 2800 | ||
2519 | if (win_len > c->local_maxpacket) { | 2801 | if (win_len > c->local_maxpacket) { |
2520 | logit("channel %d: rcvd big packet %d, maxpack %d", | 2802 | logit("channel %d: rcvd big packet %zu, maxpack %u", |
2521 | c->self, win_len, c->local_maxpacket); | 2803 | c->self, win_len, c->local_maxpacket); |
2804 | return 0; | ||
2522 | } | 2805 | } |
2523 | if (win_len > c->local_window) { | 2806 | if (win_len > c->local_window) { |
2524 | logit("channel %d: rcvd too much data %d, win %d", | 2807 | logit("channel %d: rcvd too much data %zu, win %u", |
2525 | c->self, win_len, c->local_window); | 2808 | c->self, win_len, c->local_window); |
2526 | return 0; | 2809 | return 0; |
2527 | } | 2810 | } |
2528 | c->local_window -= win_len; | 2811 | c->local_window -= win_len; |
2529 | 2812 | ||
2530 | if (c->datagram) | 2813 | if (c->datagram) { |
2531 | buffer_put_string(&c->output, data, data_len); | 2814 | if ((r = sshbuf_put_string(c->output, data, data_len)) != 0) |
2532 | else | 2815 | fatal("%s: channel %d: append datagram: %s", |
2533 | buffer_append(&c->output, data, data_len); | 2816 | __func__, c->self, ssh_err(r)); |
2534 | packet_check_eom(); | 2817 | } else if ((r = sshbuf_put(c->output, data, data_len)) != 0) |
2818 | fatal("%s: channel %d: append data: %s", | ||
2819 | __func__, c->self, ssh_err(r)); | ||
2820 | |||
2535 | return 0; | 2821 | return 0; |
2536 | } | 2822 | } |
2537 | 2823 | ||
2538 | /* ARGSUSED */ | ||
2539 | int | 2824 | int |
2540 | channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) | 2825 | channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) |
2541 | { | 2826 | { |
2542 | int id; | 2827 | const u_char *data; |
2543 | char *data; | 2828 | size_t data_len; |
2544 | u_int data_len, tcode; | 2829 | u_int32_t tcode; |
2545 | Channel *c; | 2830 | Channel *c = channel_from_packet_id(ssh, __func__, "extended data"); |
2546 | 2831 | int r; | |
2547 | /* Get the channel number and verify it. */ | ||
2548 | id = packet_get_int(); | ||
2549 | c = channel_lookup(id); | ||
2550 | 2832 | ||
2551 | if (c == NULL) | ||
2552 | packet_disconnect("Received extended_data for bad channel %d.", id); | ||
2553 | if (channel_proxy_upstream(c, type, seq, ssh)) | 2833 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2554 | return 0; | 2834 | return 0; |
2555 | if (c->type != SSH_CHANNEL_OPEN) { | 2835 | if (c->type != SSH_CHANNEL_OPEN) { |
2556 | logit("channel %d: ext data for non open", id); | 2836 | logit("channel %d: ext data for non open", c->self); |
2557 | return 0; | 2837 | return 0; |
2558 | } | 2838 | } |
2559 | if (c->flags & CHAN_EOF_RCVD) { | 2839 | if (c->flags & CHAN_EOF_RCVD) { |
2560 | if (datafellows & SSH_BUG_EXTEOF) | 2840 | if (datafellows & SSH_BUG_EXTEOF) |
2561 | debug("channel %d: accepting ext data after eof", id); | 2841 | debug("channel %d: accepting ext data after eof", |
2842 | c->self); | ||
2562 | else | 2843 | else |
2563 | packet_disconnect("Received extended_data after EOF " | 2844 | ssh_packet_disconnect(ssh, "Received extended_data " |
2564 | "on channel %d.", id); | 2845 | "after EOF on channel %d.", c->self); |
2846 | } | ||
2847 | |||
2848 | if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) { | ||
2849 | error("%s: parse tcode: %s", __func__, ssh_err(r)); | ||
2850 | ssh_packet_disconnect(ssh, "Invalid extended_data message"); | ||
2565 | } | 2851 | } |
2566 | tcode = packet_get_int(); | ||
2567 | if (c->efd == -1 || | 2852 | if (c->efd == -1 || |
2568 | c->extended_usage != CHAN_EXTENDED_WRITE || | 2853 | c->extended_usage != CHAN_EXTENDED_WRITE || |
2569 | tcode != SSH2_EXTENDED_DATA_STDERR) { | 2854 | tcode != SSH2_EXTENDED_DATA_STDERR) { |
2570 | logit("channel %d: bad ext data", c->self); | 2855 | logit("channel %d: bad ext data", c->self); |
2571 | return 0; | 2856 | return 0; |
2572 | } | 2857 | } |
2573 | data = packet_get_string(&data_len); | 2858 | if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) { |
2574 | packet_check_eom(); | 2859 | error("%s: parse data: %s", __func__, ssh_err(r)); |
2860 | ssh_packet_disconnect(ssh, "Invalid extended_data message"); | ||
2861 | } | ||
2862 | ssh_packet_check_eom(ssh); | ||
2863 | |||
2575 | if (data_len > c->local_window) { | 2864 | if (data_len > c->local_window) { |
2576 | logit("channel %d: rcvd too much extended_data %d, win %d", | 2865 | logit("channel %d: rcvd too much extended_data %zu, win %u", |
2577 | c->self, data_len, c->local_window); | 2866 | c->self, data_len, c->local_window); |
2578 | free(data); | ||
2579 | return 0; | 2867 | return 0; |
2580 | } | 2868 | } |
2581 | debug2("channel %d: rcvd ext data %d", c->self, data_len); | 2869 | debug2("channel %d: rcvd ext data %zu", c->self, data_len); |
2870 | /* XXX sshpkt_getb? */ | ||
2871 | if ((r = sshbuf_put(c->extended, data, data_len)) != 0) | ||
2872 | error("%s: append: %s", __func__, ssh_err(r)); | ||
2582 | c->local_window -= data_len; | 2873 | c->local_window -= data_len; |
2583 | buffer_append(&c->extended, data, data_len); | ||
2584 | free(data); | ||
2585 | return 0; | 2874 | return 0; |
2586 | } | 2875 | } |
2587 | 2876 | ||
2588 | /* ARGSUSED */ | ||
2589 | int | 2877 | int |
2590 | channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) | 2878 | channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) |
2591 | { | 2879 | { |
2592 | int id; | 2880 | Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); |
2593 | Channel *c; | 2881 | |
2882 | ssh_packet_check_eom(ssh); | ||
2594 | 2883 | ||
2595 | id = packet_get_int(); | ||
2596 | packet_check_eom(); | ||
2597 | c = channel_lookup(id); | ||
2598 | if (c == NULL) | ||
2599 | packet_disconnect("Received ieof for nonexistent channel %d.", id); | ||
2600 | if (channel_proxy_upstream(c, type, seq, ssh)) | 2884 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2601 | return 0; | 2885 | return 0; |
2602 | chan_rcvd_ieof(c); | 2886 | chan_rcvd_ieof(ssh, c); |
2603 | 2887 | ||
2604 | /* XXX force input close */ | 2888 | /* XXX force input close */ |
2605 | if (c->force_drain && c->istate == CHAN_INPUT_OPEN) { | 2889 | if (c->force_drain && c->istate == CHAN_INPUT_OPEN) { |
2606 | debug("channel %d: FORCE input drain", c->self); | 2890 | debug("channel %d: FORCE input drain", c->self); |
2607 | c->istate = CHAN_INPUT_WAIT_DRAIN; | 2891 | c->istate = CHAN_INPUT_WAIT_DRAIN; |
2608 | if (buffer_len(&c->input) == 0) | 2892 | if (sshbuf_len(c->input) == 0) |
2609 | chan_ibuf_empty(c); | 2893 | chan_ibuf_empty(ssh, c); |
2610 | } | 2894 | } |
2611 | return 0; | 2895 | return 0; |
2612 | } | 2896 | } |
2613 | 2897 | ||
2614 | /* ARGSUSED */ | ||
2615 | int | 2898 | int |
2616 | channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) | 2899 | channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) |
2617 | { | 2900 | { |
2618 | int id = packet_get_int(); | 2901 | Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); |
2619 | Channel *c = channel_lookup(id); | ||
2620 | 2902 | ||
2621 | if (c == NULL) | ||
2622 | packet_disconnect("Received oclose for nonexistent channel %d.", id); | ||
2623 | if (channel_proxy_upstream(c, type, seq, ssh)) | 2903 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2624 | return 0; | 2904 | return 0; |
2625 | packet_check_eom(); | 2905 | ssh_packet_check_eom(ssh); |
2626 | chan_rcvd_oclose(c); | 2906 | chan_rcvd_oclose(ssh, c); |
2627 | return 0; | 2907 | return 0; |
2628 | } | 2908 | } |
2629 | 2909 | ||
2630 | /* ARGSUSED */ | ||
2631 | int | 2910 | int |
2632 | channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) | 2911 | channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) |
2633 | { | 2912 | { |
2634 | int id, remote_id; | 2913 | Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation"); |
2635 | Channel *c; | 2914 | u_int32_t remote_window, remote_maxpacket; |
2636 | 2915 | int r; | |
2637 | id = packet_get_int(); | ||
2638 | c = channel_lookup(id); | ||
2639 | 2916 | ||
2640 | if (c==NULL) | ||
2641 | packet_disconnect("Received open confirmation for " | ||
2642 | "unknown channel %d.", id); | ||
2643 | if (channel_proxy_upstream(c, type, seq, ssh)) | 2917 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2644 | return 0; | 2918 | return 0; |
2645 | if (c->type != SSH_CHANNEL_OPENING) | 2919 | if (c->type != SSH_CHANNEL_OPENING) |
2646 | packet_disconnect("Received open confirmation for " | 2920 | packet_disconnect("Received open confirmation for " |
2647 | "non-opening channel %d.", id); | 2921 | "non-opening channel %d.", c->self); |
2648 | remote_id = packet_get_int(); | 2922 | /* |
2649 | /* Record the remote channel number and mark that the channel is now open. */ | 2923 | * Record the remote channel number and mark that the channel |
2650 | c->remote_id = remote_id; | 2924 | * is now open. |
2651 | c->type = SSH_CHANNEL_OPEN; | 2925 | */ |
2926 | c->remote_id = channel_parse_id(ssh, __func__, "open confirmation"); | ||
2927 | if ((r = sshpkt_get_u32(ssh, &remote_window)) != 0 || | ||
2928 | (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0) { | ||
2929 | error("%s: window/maxpacket: %s", __func__, ssh_err(r)); | ||
2930 | packet_disconnect("Invalid open confirmation message"); | ||
2931 | } | ||
2932 | ssh_packet_check_eom(ssh); | ||
2652 | 2933 | ||
2653 | c->remote_window = packet_get_int(); | 2934 | c->remote_window = remote_window; |
2654 | c->remote_maxpacket = packet_get_int(); | 2935 | c->remote_maxpacket = remote_maxpacket; |
2936 | c->type = SSH_CHANNEL_OPEN; | ||
2655 | if (c->open_confirm) { | 2937 | if (c->open_confirm) { |
2656 | debug2("callback start"); | 2938 | debug2("%s: channel %d: callback start", __func__, c->self); |
2657 | c->open_confirm(c->self, 1, c->open_confirm_ctx); | 2939 | c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx); |
2658 | debug2("callback done"); | 2940 | debug2("%s: channel %d: callback done", __func__, c->self); |
2659 | } | 2941 | } |
2660 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, | 2942 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, |
2661 | c->remote_window, c->remote_maxpacket); | 2943 | c->remote_window, c->remote_maxpacket); |
2662 | packet_check_eom(); | ||
2663 | return 0; | 2944 | return 0; |
2664 | } | 2945 | } |
2665 | 2946 | ||
@@ -2679,97 +2960,97 @@ reason2txt(int reason) | |||
2679 | return "unknown reason"; | 2960 | return "unknown reason"; |
2680 | } | 2961 | } |
2681 | 2962 | ||
2682 | /* ARGSUSED */ | ||
2683 | int | 2963 | int |
2684 | channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) | 2964 | channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) |
2685 | { | 2965 | { |
2686 | int id, reason; | 2966 | Channel *c = channel_from_packet_id(ssh, __func__, "open failure"); |
2687 | char *msg = NULL, *lang = NULL; | 2967 | u_int32_t reason; |
2688 | Channel *c; | 2968 | char *msg = NULL; |
2689 | 2969 | int r; | |
2690 | id = packet_get_int(); | ||
2691 | c = channel_lookup(id); | ||
2692 | 2970 | ||
2693 | if (c==NULL) | ||
2694 | packet_disconnect("Received open failure for " | ||
2695 | "unknown channel %d.", id); | ||
2696 | if (channel_proxy_upstream(c, type, seq, ssh)) | 2971 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2697 | return 0; | 2972 | return 0; |
2698 | if (c->type != SSH_CHANNEL_OPENING) | 2973 | if (c->type != SSH_CHANNEL_OPENING) |
2699 | packet_disconnect("Received open failure for " | 2974 | packet_disconnect("Received open failure for " |
2700 | "non-opening channel %d.", id); | 2975 | "non-opening channel %d.", c->self); |
2701 | reason = packet_get_int(); | 2976 | if ((r = sshpkt_get_u32(ssh, &reason)) != 0) { |
2702 | if (!(datafellows & SSH_BUG_OPENFAILURE)) { | 2977 | error("%s: reason: %s", __func__, ssh_err(r)); |
2703 | msg = packet_get_string(NULL); | 2978 | packet_disconnect("Invalid open failure message"); |
2704 | lang = packet_get_string(NULL); | 2979 | } |
2980 | if ((datafellows & SSH_BUG_OPENFAILURE) == 0) { | ||
2981 | /* skip language */ | ||
2982 | if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || | ||
2983 | (r = sshpkt_get_string_direct(ssh, NULL, NULL)) == 0) { | ||
2984 | error("%s: message/lang: %s", __func__, ssh_err(r)); | ||
2985 | packet_disconnect("Invalid open failure message"); | ||
2986 | } | ||
2705 | } | 2987 | } |
2706 | logit("channel %d: open failed: %s%s%s", id, | 2988 | ssh_packet_check_eom(ssh); |
2989 | logit("channel %d: open failed: %s%s%s", c->self, | ||
2707 | reason2txt(reason), msg ? ": ": "", msg ? msg : ""); | 2990 | reason2txt(reason), msg ? ": ": "", msg ? msg : ""); |
2708 | free(msg); | 2991 | free(msg); |
2709 | free(lang); | ||
2710 | if (c->open_confirm) { | 2992 | if (c->open_confirm) { |
2711 | debug2("callback start"); | 2993 | debug2("%s: channel %d: callback start", __func__, c->self); |
2712 | c->open_confirm(c->self, 0, c->open_confirm_ctx); | 2994 | c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx); |
2713 | debug2("callback done"); | 2995 | debug2("%s: channel %d: callback done", __func__, c->self); |
2714 | } | 2996 | } |
2715 | packet_check_eom(); | ||
2716 | /* Schedule the channel for cleanup/deletion. */ | 2997 | /* Schedule the channel for cleanup/deletion. */ |
2717 | chan_mark_dead(c); | 2998 | chan_mark_dead(ssh, c); |
2718 | return 0; | 2999 | return 0; |
2719 | } | 3000 | } |
2720 | 3001 | ||
2721 | /* ARGSUSED */ | ||
2722 | int | 3002 | int |
2723 | channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) | 3003 | channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) |
2724 | { | 3004 | { |
3005 | int id = channel_parse_id(ssh, __func__, "window adjust"); | ||
2725 | Channel *c; | 3006 | Channel *c; |
2726 | int id; | 3007 | u_int32_t adjust; |
2727 | u_int adjust, tmp; | 3008 | u_int new_rwin; |
2728 | 3009 | int r; | |
2729 | /* Get the channel number and verify it. */ | ||
2730 | id = packet_get_int(); | ||
2731 | c = channel_lookup(id); | ||
2732 | 3010 | ||
2733 | if (c == NULL) { | 3011 | if ((c = channel_lookup(ssh, id)) == NULL) { |
2734 | logit("Received window adjust for non-open channel %d.", id); | 3012 | logit("Received window adjust for non-open channel %d.", id); |
2735 | return 0; | 3013 | return 0; |
2736 | } | 3014 | } |
3015 | |||
2737 | if (channel_proxy_upstream(c, type, seq, ssh)) | 3016 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2738 | return 0; | 3017 | return 0; |
2739 | adjust = packet_get_int(); | 3018 | if ((r = sshpkt_get_u32(ssh, &adjust)) != 0) { |
2740 | packet_check_eom(); | 3019 | error("%s: adjust: %s", __func__, ssh_err(r)); |
2741 | debug2("channel %d: rcvd adjust %u", id, adjust); | 3020 | packet_disconnect("Invalid window adjust message"); |
2742 | if ((tmp = c->remote_window + adjust) < c->remote_window) | 3021 | } |
3022 | ssh_packet_check_eom(ssh); | ||
3023 | debug2("channel %d: rcvd adjust %u", c->self, adjust); | ||
3024 | if ((new_rwin = c->remote_window + adjust) < c->remote_window) { | ||
2743 | fatal("channel %d: adjust %u overflows remote window %u", | 3025 | fatal("channel %d: adjust %u overflows remote window %u", |
2744 | id, adjust, c->remote_window); | 3026 | c->self, adjust, c->remote_window); |
2745 | c->remote_window = tmp; | 3027 | } |
3028 | c->remote_window = new_rwin; | ||
2746 | return 0; | 3029 | return 0; |
2747 | } | 3030 | } |
2748 | 3031 | ||
2749 | /* ARGSUSED */ | ||
2750 | int | 3032 | int |
2751 | channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) | 3033 | channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) |
2752 | { | 3034 | { |
3035 | int id = channel_parse_id(ssh, __func__, "status confirm"); | ||
2753 | Channel *c; | 3036 | Channel *c; |
2754 | struct channel_confirm *cc; | 3037 | struct channel_confirm *cc; |
2755 | int id; | ||
2756 | 3038 | ||
2757 | /* Reset keepalive timeout */ | 3039 | /* Reset keepalive timeout */ |
2758 | packet_set_alive_timeouts(0); | 3040 | packet_set_alive_timeouts(0); |
2759 | 3041 | ||
2760 | id = packet_get_int(); | 3042 | debug2("%s: type %d id %d", __func__, type, id); |
2761 | debug2("channel_input_status_confirm: type %d id %d", type, id); | ||
2762 | 3043 | ||
2763 | if ((c = channel_lookup(id)) == NULL) { | 3044 | if ((c = channel_lookup(ssh, id)) == NULL) { |
2764 | logit("channel_input_status_confirm: %d: unknown", id); | 3045 | logit("%s: %d: unknown", __func__, id); |
2765 | return 0; | 3046 | return 0; |
2766 | } | 3047 | } |
2767 | if (channel_proxy_upstream(c, type, seq, ssh)) | 3048 | if (channel_proxy_upstream(c, type, seq, ssh)) |
2768 | return 0; | 3049 | return 0; |
2769 | packet_check_eom(); | 3050 | ssh_packet_check_eom(ssh); |
2770 | if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) | 3051 | if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL) |
2771 | return 0; | 3052 | return 0; |
2772 | cc->cb(type, c, cc->ctx); | 3053 | cc->cb(ssh, type, c, cc->ctx); |
2773 | TAILQ_REMOVE(&c->status_confirms, cc, entry); | 3054 | TAILQ_REMOVE(&c->status_confirms, cc, entry); |
2774 | explicit_bzero(cc, sizeof(*cc)); | 3055 | explicit_bzero(cc, sizeof(*cc)); |
2775 | free(cc); | 3056 | free(cc); |
@@ -2779,9 +3060,9 @@ channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) | |||
2779 | /* -- tcp forwarding */ | 3060 | /* -- tcp forwarding */ |
2780 | 3061 | ||
2781 | void | 3062 | void |
2782 | channel_set_af(int af) | 3063 | channel_set_af(struct ssh *ssh, int af) |
2783 | { | 3064 | { |
2784 | IPv4or6 = af; | 3065 | ssh->chanctxt->IPv4or6 = af; |
2785 | } | 3066 | } |
2786 | 3067 | ||
2787 | 3068 | ||
@@ -2849,8 +3130,9 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, | |||
2849 | } | 3130 | } |
2850 | 3131 | ||
2851 | static int | 3132 | static int |
2852 | channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, | 3133 | channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, |
2853 | int *allocated_listen_port, struct ForwardOptions *fwd_opts) | 3134 | struct Forward *fwd, int *allocated_listen_port, |
3135 | struct ForwardOptions *fwd_opts) | ||
2854 | { | 3136 | { |
2855 | Channel *c; | 3137 | Channel *c; |
2856 | int sock, r, success = 0, wildcard = 0, is_client; | 3138 | int sock, r, success = 0, wildcard = 0, is_client; |
@@ -2887,7 +3169,7 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, | |||
2887 | * set to NULL and hints.ai_flags is not AI_PASSIVE | 3169 | * set to NULL and hints.ai_flags is not AI_PASSIVE |
2888 | */ | 3170 | */ |
2889 | memset(&hints, 0, sizeof(hints)); | 3171 | memset(&hints, 0, sizeof(hints)); |
2890 | hints.ai_family = IPv4or6; | 3172 | hints.ai_family = ssh->chanctxt->IPv4or6; |
2891 | hints.ai_flags = wildcard ? AI_PASSIVE : 0; | 3173 | hints.ai_flags = wildcard ? AI_PASSIVE : 0; |
2892 | hints.ai_socktype = SOCK_STREAM; | 3174 | hints.ai_socktype = SOCK_STREAM; |
2893 | snprintf(strport, sizeof strport, "%d", fwd->listen_port); | 3175 | snprintf(strport, sizeof strport, "%d", fwd->listen_port); |
@@ -2921,12 +3203,14 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, | |||
2921 | * If allocating a port for -R forwards, then use the | 3203 | * If allocating a port for -R forwards, then use the |
2922 | * same port for all address families. | 3204 | * same port for all address families. |
2923 | */ | 3205 | */ |
2924 | if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && | 3206 | if (type == SSH_CHANNEL_RPORT_LISTENER && |
2925 | allocated_listen_port != NULL && *allocated_listen_port > 0) | 3207 | fwd->listen_port == 0 && allocated_listen_port != NULL && |
3208 | *allocated_listen_port > 0) | ||
2926 | *lport_p = htons(*allocated_listen_port); | 3209 | *lport_p = htons(*allocated_listen_port); |
2927 | 3210 | ||
2928 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), | 3211 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), |
2929 | strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | 3212 | strport, sizeof(strport), |
3213 | NI_NUMERICHOST|NI_NUMERICSERV) != 0) { | ||
2930 | error("%s: getnameinfo failed", __func__); | 3214 | error("%s: getnameinfo failed", __func__); |
2931 | continue; | 3215 | continue; |
2932 | } | 3216 | } |
@@ -2947,7 +3231,10 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, | |||
2947 | 3231 | ||
2948 | /* Bind the socket to the address. */ | 3232 | /* Bind the socket to the address. */ |
2949 | if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { | 3233 | if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
2950 | /* address can be in use ipv6 address is already bound */ | 3234 | /* |
3235 | * address can be in if use ipv6 address is | ||
3236 | * already bound | ||
3237 | */ | ||
2951 | if (!ai->ai_next) | 3238 | if (!ai->ai_next) |
2952 | error("bind: %.100s", strerror(errno)); | 3239 | error("bind: %.100s", strerror(errno)); |
2953 | else | 3240 | else |
@@ -2967,7 +3254,8 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, | |||
2967 | * fwd->listen_port == 0 requests a dynamically allocated port - | 3254 | * fwd->listen_port == 0 requests a dynamically allocated port - |
2968 | * record what we got. | 3255 | * record what we got. |
2969 | */ | 3256 | */ |
2970 | if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 && | 3257 | if (type == SSH_CHANNEL_RPORT_LISTENER && |
3258 | fwd->listen_port == 0 && | ||
2971 | allocated_listen_port != NULL && | 3259 | allocated_listen_port != NULL && |
2972 | *allocated_listen_port == 0) { | 3260 | *allocated_listen_port == 0) { |
2973 | *allocated_listen_port = get_local_port(sock); | 3261 | *allocated_listen_port = get_local_port(sock); |
@@ -2976,7 +3264,7 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, | |||
2976 | } | 3264 | } |
2977 | 3265 | ||
2978 | /* Allocate a channel number for the socket. */ | 3266 | /* Allocate a channel number for the socket. */ |
2979 | c = channel_new("port listener", type, sock, sock, -1, | 3267 | c = channel_new(ssh, "port listener", type, sock, sock, -1, |
2980 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | 3268 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
2981 | 0, "port listener", 1); | 3269 | 0, "port listener", 1); |
2982 | c->path = xstrdup(host); | 3270 | c->path = xstrdup(host); |
@@ -2997,8 +3285,8 @@ channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd, | |||
2997 | } | 3285 | } |
2998 | 3286 | ||
2999 | static int | 3287 | static int |
3000 | channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd, | 3288 | channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type, |
3001 | struct ForwardOptions *fwd_opts) | 3289 | struct Forward *fwd, struct ForwardOptions *fwd_opts) |
3002 | { | 3290 | { |
3003 | struct sockaddr_un sunaddr; | 3291 | struct sockaddr_un sunaddr; |
3004 | const char *path; | 3292 | const char *path; |
@@ -3060,7 +3348,7 @@ channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd, | |||
3060 | debug("Local forwarding listening on path %s.", fwd->listen_path); | 3348 | debug("Local forwarding listening on path %s.", fwd->listen_path); |
3061 | 3349 | ||
3062 | /* Allocate a channel number for the socket. */ | 3350 | /* Allocate a channel number for the socket. */ |
3063 | c = channel_new("unix listener", type, sock, sock, -1, | 3351 | c = channel_new(ssh, "unix listener", type, sock, sock, -1, |
3064 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | 3352 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
3065 | 0, "unix listener", 1); | 3353 | 0, "unix listener", 1); |
3066 | c->path = xstrdup(path); | 3354 | c->path = xstrdup(path); |
@@ -3071,66 +3359,71 @@ channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd, | |||
3071 | } | 3359 | } |
3072 | 3360 | ||
3073 | static int | 3361 | static int |
3074 | channel_cancel_rport_listener_tcpip(const char *host, u_short port) | 3362 | channel_cancel_rport_listener_tcpip(struct ssh *ssh, |
3363 | const char *host, u_short port) | ||
3075 | { | 3364 | { |
3076 | u_int i; | 3365 | u_int i; |
3077 | int found = 0; | 3366 | int found = 0; |
3078 | 3367 | ||
3079 | for (i = 0; i < channels_alloc; i++) { | 3368 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
3080 | Channel *c = channels[i]; | 3369 | Channel *c = ssh->chanctxt->channels[i]; |
3081 | if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER) | 3370 | if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER) |
3082 | continue; | 3371 | continue; |
3083 | if (strcmp(c->path, host) == 0 && c->listening_port == port) { | 3372 | if (strcmp(c->path, host) == 0 && c->listening_port == port) { |
3084 | debug2("%s: close channel %d", __func__, i); | 3373 | debug2("%s: close channel %d", __func__, i); |
3085 | channel_free(c); | 3374 | channel_free(ssh, c); |
3086 | found = 1; | 3375 | found = 1; |
3087 | } | 3376 | } |
3088 | } | 3377 | } |
3089 | 3378 | ||
3090 | return (found); | 3379 | return found; |
3091 | } | 3380 | } |
3092 | 3381 | ||
3093 | static int | 3382 | static int |
3094 | channel_cancel_rport_listener_streamlocal(const char *path) | 3383 | channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path) |
3095 | { | 3384 | { |
3096 | u_int i; | 3385 | u_int i; |
3097 | int found = 0; | 3386 | int found = 0; |
3098 | 3387 | ||
3099 | for (i = 0; i < channels_alloc; i++) { | 3388 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
3100 | Channel *c = channels[i]; | 3389 | Channel *c = ssh->chanctxt->channels[i]; |
3101 | if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER) | 3390 | if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER) |
3102 | continue; | 3391 | continue; |
3103 | if (c->path == NULL) | 3392 | if (c->path == NULL) |
3104 | continue; | 3393 | continue; |
3105 | if (strcmp(c->path, path) == 0) { | 3394 | if (strcmp(c->path, path) == 0) { |
3106 | debug2("%s: close channel %d", __func__, i); | 3395 | debug2("%s: close channel %d", __func__, i); |
3107 | channel_free(c); | 3396 | channel_free(ssh, c); |
3108 | found = 1; | 3397 | found = 1; |
3109 | } | 3398 | } |
3110 | } | 3399 | } |
3111 | 3400 | ||
3112 | return (found); | 3401 | return found; |
3113 | } | 3402 | } |
3114 | 3403 | ||
3115 | int | 3404 | int |
3116 | channel_cancel_rport_listener(struct Forward *fwd) | 3405 | channel_cancel_rport_listener(struct ssh *ssh, struct Forward *fwd) |
3117 | { | 3406 | { |
3118 | if (fwd->listen_path != NULL) | 3407 | if (fwd->listen_path != NULL) { |
3119 | return channel_cancel_rport_listener_streamlocal(fwd->listen_path); | 3408 | return channel_cancel_rport_listener_streamlocal(ssh, |
3120 | else | 3409 | fwd->listen_path); |
3121 | return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port); | 3410 | } else { |
3411 | return channel_cancel_rport_listener_tcpip(ssh, | ||
3412 | fwd->listen_host, fwd->listen_port); | ||
3413 | } | ||
3122 | } | 3414 | } |
3123 | 3415 | ||
3124 | static int | 3416 | static int |
3125 | channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport, | 3417 | channel_cancel_lport_listener_tcpip(struct ssh *ssh, |
3126 | int cport, struct ForwardOptions *fwd_opts) | 3418 | const char *lhost, u_short lport, int cport, |
3419 | struct ForwardOptions *fwd_opts) | ||
3127 | { | 3420 | { |
3128 | u_int i; | 3421 | u_int i; |
3129 | int found = 0; | 3422 | int found = 0; |
3130 | const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts); | 3423 | const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts); |
3131 | 3424 | ||
3132 | for (i = 0; i < channels_alloc; i++) { | 3425 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
3133 | Channel *c = channels[i]; | 3426 | Channel *c = ssh->chanctxt->channels[i]; |
3134 | if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER) | 3427 | if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER) |
3135 | continue; | 3428 | continue; |
3136 | if (c->listening_port != lport) | 3429 | if (c->listening_port != lport) |
@@ -3148,16 +3441,16 @@ channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport, | |||
3148 | continue; | 3441 | continue; |
3149 | if (addr == NULL || strcmp(c->listening_addr, addr) == 0) { | 3442 | if (addr == NULL || strcmp(c->listening_addr, addr) == 0) { |
3150 | debug2("%s: close channel %d", __func__, i); | 3443 | debug2("%s: close channel %d", __func__, i); |
3151 | channel_free(c); | 3444 | channel_free(ssh, c); |
3152 | found = 1; | 3445 | found = 1; |
3153 | } | 3446 | } |
3154 | } | 3447 | } |
3155 | 3448 | ||
3156 | return (found); | 3449 | return found; |
3157 | } | 3450 | } |
3158 | 3451 | ||
3159 | static int | 3452 | static int |
3160 | channel_cancel_lport_listener_streamlocal(const char *path) | 3453 | channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path) |
3161 | { | 3454 | { |
3162 | u_int i; | 3455 | u_int i; |
3163 | int found = 0; | 3456 | int found = 0; |
@@ -3167,54 +3460,59 @@ channel_cancel_lport_listener_streamlocal(const char *path) | |||
3167 | return 0; | 3460 | return 0; |
3168 | } | 3461 | } |
3169 | 3462 | ||
3170 | for (i = 0; i < channels_alloc; i++) { | 3463 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) { |
3171 | Channel *c = channels[i]; | 3464 | Channel *c = ssh->chanctxt->channels[i]; |
3172 | if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER) | 3465 | if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER) |
3173 | continue; | 3466 | continue; |
3174 | if (c->listening_addr == NULL) | 3467 | if (c->listening_addr == NULL) |
3175 | continue; | 3468 | continue; |
3176 | if (strcmp(c->listening_addr, path) == 0) { | 3469 | if (strcmp(c->listening_addr, path) == 0) { |
3177 | debug2("%s: close channel %d", __func__, i); | 3470 | debug2("%s: close channel %d", __func__, i); |
3178 | channel_free(c); | 3471 | channel_free(ssh, c); |
3179 | found = 1; | 3472 | found = 1; |
3180 | } | 3473 | } |
3181 | } | 3474 | } |
3182 | 3475 | ||
3183 | return (found); | 3476 | return found; |
3184 | } | 3477 | } |
3185 | 3478 | ||
3186 | int | 3479 | int |
3187 | channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) | 3480 | channel_cancel_lport_listener(struct ssh *ssh, |
3481 | struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) | ||
3188 | { | 3482 | { |
3189 | if (fwd->listen_path != NULL) | 3483 | if (fwd->listen_path != NULL) { |
3190 | return channel_cancel_lport_listener_streamlocal(fwd->listen_path); | 3484 | return channel_cancel_lport_listener_streamlocal(ssh, |
3191 | else | 3485 | fwd->listen_path); |
3192 | return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts); | 3486 | } else { |
3487 | return channel_cancel_lport_listener_tcpip(ssh, | ||
3488 | fwd->listen_host, fwd->listen_port, cport, fwd_opts); | ||
3489 | } | ||
3193 | } | 3490 | } |
3194 | 3491 | ||
3195 | /* protocol local port fwd, used by ssh */ | 3492 | /* protocol local port fwd, used by ssh */ |
3196 | int | 3493 | int |
3197 | channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts) | 3494 | channel_setup_local_fwd_listener(struct ssh *ssh, |
3495 | struct Forward *fwd, struct ForwardOptions *fwd_opts) | ||
3198 | { | 3496 | { |
3199 | if (fwd->listen_path != NULL) { | 3497 | if (fwd->listen_path != NULL) { |
3200 | return channel_setup_fwd_listener_streamlocal( | 3498 | return channel_setup_fwd_listener_streamlocal(ssh, |
3201 | SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts); | 3499 | SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts); |
3202 | } else { | 3500 | } else { |
3203 | return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER, | 3501 | return channel_setup_fwd_listener_tcpip(ssh, |
3204 | fwd, NULL, fwd_opts); | 3502 | SSH_CHANNEL_PORT_LISTENER, fwd, NULL, fwd_opts); |
3205 | } | 3503 | } |
3206 | } | 3504 | } |
3207 | 3505 | ||
3208 | /* protocol v2 remote port fwd, used by sshd */ | 3506 | /* protocol v2 remote port fwd, used by sshd */ |
3209 | int | 3507 | int |
3210 | channel_setup_remote_fwd_listener(struct Forward *fwd, | 3508 | channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd, |
3211 | int *allocated_listen_port, struct ForwardOptions *fwd_opts) | 3509 | int *allocated_listen_port, struct ForwardOptions *fwd_opts) |
3212 | { | 3510 | { |
3213 | if (fwd->listen_path != NULL) { | 3511 | if (fwd->listen_path != NULL) { |
3214 | return channel_setup_fwd_listener_streamlocal( | 3512 | return channel_setup_fwd_listener_streamlocal(ssh, |
3215 | SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); | 3513 | SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); |
3216 | } else { | 3514 | } else { |
3217 | return channel_setup_fwd_listener_tcpip( | 3515 | return channel_setup_fwd_listener_tcpip(ssh, |
3218 | SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port, | 3516 | SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port, |
3219 | fwd_opts); | 3517 | fwd_opts); |
3220 | } | 3518 | } |
@@ -3248,56 +3546,61 @@ channel_rfwd_bind_host(const char *listen_host) | |||
3248 | * channel_update_permitted_opens(). | 3546 | * channel_update_permitted_opens(). |
3249 | */ | 3547 | */ |
3250 | int | 3548 | int |
3251 | channel_request_remote_forwarding(struct Forward *fwd) | 3549 | channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) |
3252 | { | 3550 | { |
3253 | int success = 0, idx = -1; | 3551 | int r, success = 0, idx = -1; |
3552 | char *host_to_connect, *listen_host, *listen_path; | ||
3553 | int port_to_connect, listen_port; | ||
3254 | 3554 | ||
3255 | /* Send the forward request to the remote side. */ | 3555 | /* Send the forward request to the remote side. */ |
3256 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | ||
3257 | if (fwd->listen_path != NULL) { | 3556 | if (fwd->listen_path != NULL) { |
3258 | packet_put_cstring("streamlocal-forward@openssh.com"); | 3557 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || |
3259 | packet_put_char(1); /* boolean: want reply */ | 3558 | (r = sshpkt_put_cstring(ssh, |
3260 | packet_put_cstring(fwd->listen_path); | 3559 | "streamlocal-forward@openssh.com")) != 0 || |
3560 | (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */ | ||
3561 | (r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 || | ||
3562 | (r = sshpkt_send(ssh)) != 0 || | ||
3563 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
3564 | fatal("%s: request streamlocal: %s", | ||
3565 | __func__, ssh_err(r)); | ||
3261 | } else { | 3566 | } else { |
3262 | packet_put_cstring("tcpip-forward"); | 3567 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || |
3263 | packet_put_char(1); /* boolean: want reply */ | 3568 | (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 || |
3264 | packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host)); | 3569 | (r = sshpkt_put_u8(ssh, 1)) != 0 || /* want reply */ |
3265 | packet_put_int(fwd->listen_port); | 3570 | (r = sshpkt_put_cstring(ssh, |
3571 | channel_rfwd_bind_host(fwd->listen_host))) != 0 || | ||
3572 | (r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 || | ||
3573 | (r = sshpkt_send(ssh)) != 0 || | ||
3574 | (r = ssh_packet_write_wait(ssh)) != 0) | ||
3575 | fatal("%s: request tcpip-forward: %s", | ||
3576 | __func__, ssh_err(r)); | ||
3266 | } | 3577 | } |
3267 | packet_send(); | ||
3268 | packet_write_wait(); | ||
3269 | /* Assume that server accepts the request */ | 3578 | /* Assume that server accepts the request */ |
3270 | success = 1; | 3579 | success = 1; |
3271 | if (success) { | 3580 | if (success) { |
3272 | /* Record that connection to this host/port is permitted. */ | 3581 | /* Record that connection to this host/port is permitted. */ |
3273 | permitted_opens = xreallocarray(permitted_opens, | 3582 | host_to_connect = listen_host = listen_path = NULL; |
3274 | num_permitted_opens + 1, sizeof(*permitted_opens)); | 3583 | port_to_connect = listen_port = 0; |
3275 | idx = num_permitted_opens++; | ||
3276 | if (fwd->connect_path != NULL) { | 3584 | if (fwd->connect_path != NULL) { |
3277 | permitted_opens[idx].host_to_connect = | 3585 | host_to_connect = xstrdup(fwd->connect_path); |
3278 | xstrdup(fwd->connect_path); | 3586 | port_to_connect = PORT_STREAMLOCAL; |
3279 | permitted_opens[idx].port_to_connect = | ||
3280 | PORT_STREAMLOCAL; | ||
3281 | } else { | 3587 | } else { |
3282 | permitted_opens[idx].host_to_connect = | 3588 | host_to_connect = xstrdup(fwd->connect_host); |
3283 | xstrdup(fwd->connect_host); | 3589 | port_to_connect = fwd->connect_port; |
3284 | permitted_opens[idx].port_to_connect = | ||
3285 | fwd->connect_port; | ||
3286 | } | 3590 | } |
3287 | if (fwd->listen_path != NULL) { | 3591 | if (fwd->listen_path != NULL) { |
3288 | permitted_opens[idx].listen_host = NULL; | 3592 | listen_path = xstrdup(fwd->listen_path); |
3289 | permitted_opens[idx].listen_path = | 3593 | listen_port = PORT_STREAMLOCAL; |
3290 | xstrdup(fwd->listen_path); | ||
3291 | permitted_opens[idx].listen_port = PORT_STREAMLOCAL; | ||
3292 | } else { | 3594 | } else { |
3293 | permitted_opens[idx].listen_host = | 3595 | if (fwd->listen_host != NULL) |
3294 | fwd->listen_host ? xstrdup(fwd->listen_host) : NULL; | 3596 | listen_host = xstrdup(fwd->listen_host); |
3295 | permitted_opens[idx].listen_path = NULL; | 3597 | listen_port = fwd->listen_port; |
3296 | permitted_opens[idx].listen_port = fwd->listen_port; | ||
3297 | } | 3598 | } |
3298 | permitted_opens[idx].downstream = NULL; | 3599 | idx = fwd_perm_list_add(ssh, FWDPERM_USER, |
3600 | host_to_connect, port_to_connect, | ||
3601 | listen_host, listen_path, listen_port, NULL); | ||
3299 | } | 3602 | } |
3300 | return (idx); | 3603 | return idx; |
3301 | } | 3604 | } |
3302 | 3605 | ||
3303 | static int | 3606 | static int |
@@ -3362,33 +3665,33 @@ open_listen_match_streamlocal(ForwardPermission *allowed_open, | |||
3362 | * local side. | 3665 | * local side. |
3363 | */ | 3666 | */ |
3364 | static int | 3667 | static int |
3365 | channel_request_rforward_cancel_tcpip(const char *host, u_short port) | 3668 | channel_request_rforward_cancel_tcpip(struct ssh *ssh, |
3669 | const char *host, u_short port) | ||
3366 | { | 3670 | { |
3367 | int i; | 3671 | struct ssh_channels *sc = ssh->chanctxt; |
3672 | int r; | ||
3673 | u_int i; | ||
3674 | ForwardPermission *fp; | ||
3368 | 3675 | ||
3369 | for (i = 0; i < num_permitted_opens; i++) { | 3676 | for (i = 0; i < sc->num_permitted_opens; i++) { |
3370 | if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0)) | 3677 | fp = &sc->permitted_opens[i]; |
3678 | if (open_listen_match_tcpip(fp, host, port, 0)) | ||
3371 | break; | 3679 | break; |
3680 | fp = NULL; | ||
3372 | } | 3681 | } |
3373 | if (i >= num_permitted_opens) { | 3682 | if (fp == NULL) { |
3374 | debug("%s: requested forward not found", __func__); | 3683 | debug("%s: requested forward not found", __func__); |
3375 | return -1; | 3684 | return -1; |
3376 | } | 3685 | } |
3377 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 3686 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || |
3378 | packet_put_cstring("cancel-tcpip-forward"); | 3687 | (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 || |
3379 | packet_put_char(0); | 3688 | (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */ |
3380 | packet_put_cstring(channel_rfwd_bind_host(host)); | 3689 | (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 || |
3381 | packet_put_int(port); | 3690 | (r = sshpkt_put_u32(ssh, port)) != 0 || |
3382 | packet_send(); | 3691 | (r = sshpkt_send(ssh)) != 0) |
3383 | 3692 | fatal("%s: send cancel: %s", __func__, ssh_err(r)); | |
3384 | permitted_opens[i].listen_port = 0; | 3693 | |
3385 | permitted_opens[i].port_to_connect = 0; | 3694 | fwd_perm_clear(fp); /* unregister */ |
3386 | free(permitted_opens[i].host_to_connect); | ||
3387 | permitted_opens[i].host_to_connect = NULL; | ||
3388 | free(permitted_opens[i].listen_host); | ||
3389 | permitted_opens[i].listen_host = NULL; | ||
3390 | permitted_opens[i].listen_path = NULL; | ||
3391 | permitted_opens[i].downstream = NULL; | ||
3392 | 3695 | ||
3393 | return 0; | 3696 | return 0; |
3394 | } | 3697 | } |
@@ -3398,32 +3701,32 @@ channel_request_rforward_cancel_tcpip(const char *host, u_short port) | |||
3398 | * path from local side. | 3701 | * path from local side. |
3399 | */ | 3702 | */ |
3400 | static int | 3703 | static int |
3401 | channel_request_rforward_cancel_streamlocal(const char *path) | 3704 | channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) |
3402 | { | 3705 | { |
3403 | int i; | 3706 | struct ssh_channels *sc = ssh->chanctxt; |
3707 | int r; | ||
3708 | u_int i; | ||
3709 | ForwardPermission *fp; | ||
3404 | 3710 | ||
3405 | for (i = 0; i < num_permitted_opens; i++) { | 3711 | for (i = 0; i < sc->num_permitted_opens; i++) { |
3406 | if (open_listen_match_streamlocal(&permitted_opens[i], path)) | 3712 | fp = &sc->permitted_opens[i]; |
3713 | if (open_listen_match_streamlocal(fp, path)) | ||
3407 | break; | 3714 | break; |
3715 | fp = NULL; | ||
3408 | } | 3716 | } |
3409 | if (i >= num_permitted_opens) { | 3717 | if (fp == NULL) { |
3410 | debug("%s: requested forward not found", __func__); | 3718 | debug("%s: requested forward not found", __func__); |
3411 | return -1; | 3719 | return -1; |
3412 | } | 3720 | } |
3413 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 3721 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 || |
3414 | packet_put_cstring("cancel-streamlocal-forward@openssh.com"); | 3722 | (r = sshpkt_put_cstring(ssh, |
3415 | packet_put_char(0); | 3723 | "cancel-streamlocal-forward@openssh.com")) != 0 || |
3416 | packet_put_cstring(path); | 3724 | (r = sshpkt_put_u8(ssh, 0)) != 0 || /* want reply */ |
3417 | packet_send(); | 3725 | (r = sshpkt_put_cstring(ssh, path)) != 0 || |
3418 | 3726 | (r = sshpkt_send(ssh)) != 0) | |
3419 | permitted_opens[i].listen_port = 0; | 3727 | fatal("%s: send cancel: %s", __func__, ssh_err(r)); |
3420 | permitted_opens[i].port_to_connect = 0; | 3728 | |
3421 | free(permitted_opens[i].host_to_connect); | 3729 | fwd_perm_clear(fp); /* unregister */ |
3422 | permitted_opens[i].host_to_connect = NULL; | ||
3423 | permitted_opens[i].listen_host = NULL; | ||
3424 | free(permitted_opens[i].listen_path); | ||
3425 | permitted_opens[i].listen_path = NULL; | ||
3426 | permitted_opens[i].downstream = NULL; | ||
3427 | 3730 | ||
3428 | return 0; | 3731 | return 0; |
3429 | } | 3732 | } |
@@ -3432,14 +3735,15 @@ channel_request_rforward_cancel_streamlocal(const char *path) | |||
3432 | * Request cancellation of remote forwarding of a connection from local side. | 3735 | * Request cancellation of remote forwarding of a connection from local side. |
3433 | */ | 3736 | */ |
3434 | int | 3737 | int |
3435 | channel_request_rforward_cancel(struct Forward *fwd) | 3738 | channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd) |
3436 | { | 3739 | { |
3437 | if (fwd->listen_path != NULL) { | 3740 | if (fwd->listen_path != NULL) { |
3438 | return (channel_request_rforward_cancel_streamlocal( | 3741 | return channel_request_rforward_cancel_streamlocal(ssh, |
3439 | fwd->listen_path)); | 3742 | fwd->listen_path); |
3440 | } else { | 3743 | } else { |
3441 | return (channel_request_rforward_cancel_tcpip(fwd->listen_host, | 3744 | return channel_request_rforward_cancel_tcpip(ssh, |
3442 | fwd->listen_port ? fwd->listen_port : fwd->allocated_port)); | 3745 | fwd->listen_host, |
3746 | fwd->listen_port ? fwd->listen_port : fwd->allocated_port); | ||
3443 | } | 3747 | } |
3444 | } | 3748 | } |
3445 | 3749 | ||
@@ -3449,28 +3753,20 @@ channel_request_rforward_cancel(struct Forward *fwd) | |||
3449 | * anyway, and the server has no way to know but to trust the client anyway. | 3753 | * anyway, and the server has no way to know but to trust the client anyway. |
3450 | */ | 3754 | */ |
3451 | void | 3755 | void |
3452 | channel_permit_all_opens(void) | 3756 | channel_permit_all_opens(struct ssh *ssh) |
3453 | { | 3757 | { |
3454 | if (num_permitted_opens == 0) | 3758 | if (ssh->chanctxt->num_permitted_opens == 0) |
3455 | all_opens_permitted = 1; | 3759 | ssh->chanctxt->all_opens_permitted = 1; |
3456 | } | 3760 | } |
3457 | 3761 | ||
3458 | void | 3762 | void |
3459 | channel_add_permitted_opens(char *host, int port) | 3763 | channel_add_permitted_opens(struct ssh *ssh, char *host, int port) |
3460 | { | 3764 | { |
3461 | debug("allow port forwarding to host %s port %d", host, port); | 3765 | struct ssh_channels *sc = ssh->chanctxt; |
3462 | 3766 | ||
3463 | permitted_opens = xreallocarray(permitted_opens, | 3767 | debug("allow port forwarding to host %s port %d", host, port); |
3464 | num_permitted_opens + 1, sizeof(*permitted_opens)); | 3768 | fwd_perm_list_add(ssh, FWDPERM_USER, host, port, NULL, NULL, 0, NULL); |
3465 | permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); | 3769 | sc->all_opens_permitted = 0; |
3466 | permitted_opens[num_permitted_opens].port_to_connect = port; | ||
3467 | permitted_opens[num_permitted_opens].listen_host = NULL; | ||
3468 | permitted_opens[num_permitted_opens].listen_path = NULL; | ||
3469 | permitted_opens[num_permitted_opens].listen_port = 0; | ||
3470 | permitted_opens[num_permitted_opens].downstream = NULL; | ||
3471 | num_permitted_opens++; | ||
3472 | |||
3473 | all_opens_permitted = 0; | ||
3474 | } | 3770 | } |
3475 | 3771 | ||
3476 | /* | 3772 | /* |
@@ -3479,105 +3775,61 @@ channel_add_permitted_opens(char *host, int port) | |||
3479 | * passed then they entry will be invalidated. | 3775 | * passed then they entry will be invalidated. |
3480 | */ | 3776 | */ |
3481 | void | 3777 | void |
3482 | channel_update_permitted_opens(int idx, int newport) | 3778 | channel_update_permitted_opens(struct ssh *ssh, int idx, int newport) |
3483 | { | 3779 | { |
3484 | if (idx < 0 || idx >= num_permitted_opens) { | 3780 | struct ssh_channels *sc = ssh->chanctxt; |
3485 | debug("channel_update_permitted_opens: index out of range:" | 3781 | |
3486 | " %d num_permitted_opens %d", idx, num_permitted_opens); | 3782 | if (idx < 0 || (u_int)idx >= sc->num_permitted_opens) { |
3783 | debug("%s: index out of range: %d num_permitted_opens %d", | ||
3784 | __func__, idx, sc->num_permitted_opens); | ||
3487 | return; | 3785 | return; |
3488 | } | 3786 | } |
3489 | debug("%s allowed port %d for forwarding to host %s port %d", | 3787 | debug("%s allowed port %d for forwarding to host %s port %d", |
3490 | newport > 0 ? "Updating" : "Removing", | 3788 | newport > 0 ? "Updating" : "Removing", |
3491 | newport, | 3789 | newport, |
3492 | permitted_opens[idx].host_to_connect, | 3790 | sc->permitted_opens[idx].host_to_connect, |
3493 | permitted_opens[idx].port_to_connect); | 3791 | sc->permitted_opens[idx].port_to_connect); |
3494 | if (newport >= 0) { | 3792 | if (newport <= 0) |
3495 | permitted_opens[idx].listen_port = | 3793 | fwd_perm_clear(&sc->permitted_opens[idx]); |
3794 | else { | ||
3795 | sc->permitted_opens[idx].listen_port = | ||
3496 | (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; | 3796 | (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport; |
3497 | } else { | ||
3498 | permitted_opens[idx].listen_port = 0; | ||
3499 | permitted_opens[idx].port_to_connect = 0; | ||
3500 | free(permitted_opens[idx].host_to_connect); | ||
3501 | permitted_opens[idx].host_to_connect = NULL; | ||
3502 | free(permitted_opens[idx].listen_host); | ||
3503 | permitted_opens[idx].listen_host = NULL; | ||
3504 | free(permitted_opens[idx].listen_path); | ||
3505 | permitted_opens[idx].listen_path = NULL; | ||
3506 | } | 3797 | } |
3507 | } | 3798 | } |
3508 | 3799 | ||
3509 | int | 3800 | int |
3510 | channel_add_adm_permitted_opens(char *host, int port) | 3801 | channel_add_adm_permitted_opens(struct ssh *ssh, char *host, int port) |
3511 | { | 3802 | { |
3512 | debug("config allows port forwarding to host %s port %d", host, port); | 3803 | debug("config allows port forwarding to host %s port %d", host, port); |
3513 | 3804 | return fwd_perm_list_add(ssh, FWDPERM_ADMIN, host, port, | |
3514 | permitted_adm_opens = xreallocarray(permitted_adm_opens, | 3805 | NULL, NULL, 0, NULL); |
3515 | num_adm_permitted_opens + 1, sizeof(*permitted_adm_opens)); | ||
3516 | permitted_adm_opens[num_adm_permitted_opens].host_to_connect | ||
3517 | = xstrdup(host); | ||
3518 | permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; | ||
3519 | permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL; | ||
3520 | permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL; | ||
3521 | permitted_adm_opens[num_adm_permitted_opens].listen_port = 0; | ||
3522 | return ++num_adm_permitted_opens; | ||
3523 | } | ||
3524 | |||
3525 | void | ||
3526 | channel_disable_adm_local_opens(void) | ||
3527 | { | ||
3528 | channel_clear_adm_permitted_opens(); | ||
3529 | permitted_adm_opens = xcalloc(sizeof(*permitted_adm_opens), 1); | ||
3530 | permitted_adm_opens[num_adm_permitted_opens].host_to_connect = NULL; | ||
3531 | num_adm_permitted_opens = 1; | ||
3532 | } | 3806 | } |
3533 | 3807 | ||
3534 | void | 3808 | void |
3535 | channel_clear_permitted_opens(void) | 3809 | channel_disable_adm_local_opens(struct ssh *ssh) |
3536 | { | 3810 | { |
3537 | int i; | 3811 | channel_clear_adm_permitted_opens(ssh); |
3538 | 3812 | fwd_perm_list_add(ssh, FWDPERM_ADMIN, NULL, 0, NULL, NULL, 0, NULL); | |
3539 | for (i = 0; i < num_permitted_opens; i++) { | ||
3540 | free(permitted_opens[i].host_to_connect); | ||
3541 | free(permitted_opens[i].listen_host); | ||
3542 | free(permitted_opens[i].listen_path); | ||
3543 | } | ||
3544 | free(permitted_opens); | ||
3545 | permitted_opens = NULL; | ||
3546 | num_permitted_opens = 0; | ||
3547 | } | 3813 | } |
3548 | 3814 | ||
3549 | void | 3815 | void |
3550 | channel_clear_adm_permitted_opens(void) | 3816 | channel_clear_permitted_opens(struct ssh *ssh) |
3551 | { | 3817 | { |
3552 | int i; | 3818 | struct ssh_channels *sc = ssh->chanctxt; |
3553 | 3819 | ||
3554 | for (i = 0; i < num_adm_permitted_opens; i++) { | 3820 | sc->permitted_opens = xrecallocarray(sc->permitted_opens, |
3555 | free(permitted_adm_opens[i].host_to_connect); | 3821 | sc->num_permitted_opens, 0, sizeof(*sc->permitted_opens)); |
3556 | free(permitted_adm_opens[i].listen_host); | 3822 | sc->num_permitted_opens = 0; |
3557 | free(permitted_adm_opens[i].listen_path); | ||
3558 | } | ||
3559 | free(permitted_adm_opens); | ||
3560 | permitted_adm_opens = NULL; | ||
3561 | num_adm_permitted_opens = 0; | ||
3562 | } | 3823 | } |
3563 | 3824 | ||
3564 | void | 3825 | void |
3565 | channel_print_adm_permitted_opens(void) | 3826 | channel_clear_adm_permitted_opens(struct ssh *ssh) |
3566 | { | 3827 | { |
3567 | int i; | 3828 | struct ssh_channels *sc = ssh->chanctxt; |
3568 | 3829 | ||
3569 | printf("permitopen"); | 3830 | sc->permitted_adm_opens = xrecallocarray(sc->permitted_adm_opens, |
3570 | if (num_adm_permitted_opens == 0) { | 3831 | sc->num_adm_permitted_opens, 0, sizeof(*sc->permitted_adm_opens)); |
3571 | printf(" any\n"); | 3832 | sc->num_adm_permitted_opens = 0; |
3572 | return; | ||
3573 | } | ||
3574 | for (i = 0; i < num_adm_permitted_opens; i++) | ||
3575 | if (permitted_adm_opens[i].host_to_connect == NULL) | ||
3576 | printf(" none"); | ||
3577 | else | ||
3578 | printf(" %s:%d", permitted_adm_opens[i].host_to_connect, | ||
3579 | permitted_adm_opens[i].port_to_connect); | ||
3580 | printf("\n"); | ||
3581 | } | 3833 | } |
3582 | 3834 | ||
3583 | /* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */ | 3835 | /* returns port number, FWD_PERMIT_ANY_PORT or -1 on error */ |
@@ -3599,7 +3851,8 @@ connect_next(struct channel_connect *cctx) | |||
3599 | { | 3851 | { |
3600 | int sock, saved_errno; | 3852 | int sock, saved_errno; |
3601 | struct sockaddr_un *sunaddr; | 3853 | struct sockaddr_un *sunaddr; |
3602 | char ntop[NI_MAXHOST], strport[MAXIMUM(NI_MAXSERV,sizeof(sunaddr->sun_path))]; | 3854 | char ntop[NI_MAXHOST]; |
3855 | char strport[MAXIMUM(NI_MAXSERV, sizeof(sunaddr->sun_path))]; | ||
3603 | 3856 | ||
3604 | for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { | 3857 | for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { |
3605 | switch (cctx->ai->ai_family) { | 3858 | switch (cctx->ai->ai_family) { |
@@ -3669,8 +3922,8 @@ channel_connect_ctx_free(struct channel_connect *cctx) | |||
3669 | * passing back the failure reason if appropriate. | 3922 | * passing back the failure reason if appropriate. |
3670 | */ | 3923 | */ |
3671 | static Channel * | 3924 | static Channel * |
3672 | connect_to_reason(const char *name, int port, char *ctype, char *rname, | 3925 | connect_to_reason(struct ssh *ssh, const char *name, int port, |
3673 | int *reason, const char **errmsg) | 3926 | char *ctype, char *rname, int *reason, const char **errmsg) |
3674 | { | 3927 | { |
3675 | struct addrinfo hints; | 3928 | struct addrinfo hints; |
3676 | int gaierr; | 3929 | int gaierr; |
@@ -3708,7 +3961,7 @@ connect_to_reason(const char *name, int port, char *ctype, char *rname, | |||
3708 | cctx.aitop = ai; | 3961 | cctx.aitop = ai; |
3709 | } else { | 3962 | } else { |
3710 | memset(&hints, 0, sizeof(hints)); | 3963 | memset(&hints, 0, sizeof(hints)); |
3711 | hints.ai_family = IPv4or6; | 3964 | hints.ai_family = ssh->chanctxt->IPv4or6; |
3712 | hints.ai_socktype = SOCK_STREAM; | 3965 | hints.ai_socktype = SOCK_STREAM; |
3713 | snprintf(strport, sizeof strport, "%d", port); | 3966 | snprintf(strport, sizeof strport, "%d", port); |
3714 | if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) | 3967 | if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) |
@@ -3733,7 +3986,7 @@ connect_to_reason(const char *name, int port, char *ctype, char *rname, | |||
3733 | channel_connect_ctx_free(&cctx); | 3986 | channel_connect_ctx_free(&cctx); |
3734 | return NULL; | 3987 | return NULL; |
3735 | } | 3988 | } |
3736 | c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, | 3989 | c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, |
3737 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); | 3990 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); |
3738 | c->connect_ctx = cctx; | 3991 | c->connect_ctx = cctx; |
3739 | return c; | 3992 | return c; |
@@ -3741,9 +3994,10 @@ connect_to_reason(const char *name, int port, char *ctype, char *rname, | |||
3741 | 3994 | ||
3742 | /* Return CONNECTING channel to remote host:port or local socket path */ | 3995 | /* Return CONNECTING channel to remote host:port or local socket path */ |
3743 | static Channel * | 3996 | static Channel * |
3744 | connect_to(const char *name, int port, char *ctype, char *rname) | 3997 | connect_to(struct ssh *ssh, const char *name, int port, |
3998 | char *ctype, char *rname) | ||
3745 | { | 3999 | { |
3746 | return connect_to_reason(name, port, ctype, rname, NULL, NULL); | 4000 | return connect_to_reason(ssh, name, port, ctype, rname, NULL, NULL); |
3747 | } | 4001 | } |
3748 | 4002 | ||
3749 | /* | 4003 | /* |
@@ -3751,19 +4005,21 @@ connect_to(const char *name, int port, char *ctype, char *rname) | |||
3751 | * that needs to deal with this connection. | 4005 | * that needs to deal with this connection. |
3752 | */ | 4006 | */ |
3753 | Channel * | 4007 | Channel * |
3754 | channel_connect_by_listen_address(const char *listen_host, | 4008 | channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host, |
3755 | u_short listen_port, char *ctype, char *rname) | 4009 | u_short listen_port, char *ctype, char *rname) |
3756 | { | 4010 | { |
3757 | int i; | 4011 | struct ssh_channels *sc = ssh->chanctxt; |
3758 | 4012 | u_int i; | |
3759 | for (i = 0; i < num_permitted_opens; i++) { | 4013 | ForwardPermission *fp; |
3760 | if (open_listen_match_tcpip(&permitted_opens[i], listen_host, | 4014 | |
3761 | listen_port, 1)) { | 4015 | for (i = 0; i < sc->num_permitted_opens; i++) { |
3762 | if (permitted_opens[i].downstream) | 4016 | fp = &sc->permitted_opens[i]; |
3763 | return permitted_opens[i].downstream; | 4017 | if (open_listen_match_tcpip(fp, listen_host, listen_port, 1)) { |
3764 | return connect_to( | 4018 | if (fp->downstream) |
3765 | permitted_opens[i].host_to_connect, | 4019 | return fp->downstream; |
3766 | permitted_opens[i].port_to_connect, ctype, rname); | 4020 | return connect_to(ssh, |
4021 | fp->host_to_connect, fp->port_to_connect, | ||
4022 | ctype, rname); | ||
3767 | } | 4023 | } |
3768 | } | 4024 | } |
3769 | error("WARNING: Server requests forwarding for unknown listen_port %d", | 4025 | error("WARNING: Server requests forwarding for unknown listen_port %d", |
@@ -3772,15 +4028,19 @@ channel_connect_by_listen_address(const char *listen_host, | |||
3772 | } | 4028 | } |
3773 | 4029 | ||
3774 | Channel * | 4030 | Channel * |
3775 | channel_connect_by_listen_path(const char *path, char *ctype, char *rname) | 4031 | channel_connect_by_listen_path(struct ssh *ssh, const char *path, |
4032 | char *ctype, char *rname) | ||
3776 | { | 4033 | { |
3777 | int i; | 4034 | struct ssh_channels *sc = ssh->chanctxt; |
3778 | 4035 | u_int i; | |
3779 | for (i = 0; i < num_permitted_opens; i++) { | 4036 | ForwardPermission *fp; |
3780 | if (open_listen_match_streamlocal(&permitted_opens[i], path)) { | 4037 | |
3781 | return connect_to( | 4038 | for (i = 0; i < sc->num_permitted_opens; i++) { |
3782 | permitted_opens[i].host_to_connect, | 4039 | fp = &sc->permitted_opens[i]; |
3783 | permitted_opens[i].port_to_connect, ctype, rname); | 4040 | if (open_listen_match_streamlocal(fp, path)) { |
4041 | return connect_to(ssh, | ||
4042 | fp->host_to_connect, fp->port_to_connect, | ||
4043 | ctype, rname); | ||
3784 | } | 4044 | } |
3785 | } | 4045 | } |
3786 | error("WARNING: Server requests forwarding for unknown path %.100s", | 4046 | error("WARNING: Server requests forwarding for unknown path %.100s", |
@@ -3790,27 +4050,33 @@ channel_connect_by_listen_path(const char *path, char *ctype, char *rname) | |||
3790 | 4050 | ||
3791 | /* Check if connecting to that port is permitted and connect. */ | 4051 | /* Check if connecting to that port is permitted and connect. */ |
3792 | Channel * | 4052 | Channel * |
3793 | channel_connect_to_port(const char *host, u_short port, char *ctype, | 4053 | channel_connect_to_port(struct ssh *ssh, const char *host, u_short port, |
3794 | char *rname, int *reason, const char **errmsg) | 4054 | char *ctype, char *rname, int *reason, const char **errmsg) |
3795 | { | 4055 | { |
3796 | int i, permit, permit_adm = 1; | 4056 | struct ssh_channels *sc = ssh->chanctxt; |
4057 | u_int i, permit, permit_adm = 1; | ||
4058 | ForwardPermission *fp; | ||
3797 | 4059 | ||
3798 | permit = all_opens_permitted; | 4060 | permit = sc->all_opens_permitted; |
3799 | if (!permit) { | 4061 | if (!permit) { |
3800 | for (i = 0; i < num_permitted_opens; i++) | 4062 | for (i = 0; i < sc->num_permitted_opens; i++) { |
3801 | if (open_match(&permitted_opens[i], host, port)) { | 4063 | fp = &sc->permitted_opens[i]; |
4064 | if (open_match(fp, host, port)) { | ||
3802 | permit = 1; | 4065 | permit = 1; |
3803 | break; | 4066 | break; |
3804 | } | 4067 | } |
4068 | } | ||
3805 | } | 4069 | } |
3806 | 4070 | ||
3807 | if (num_adm_permitted_opens > 0) { | 4071 | if (sc->num_adm_permitted_opens > 0) { |
3808 | permit_adm = 0; | 4072 | permit_adm = 0; |
3809 | for (i = 0; i < num_adm_permitted_opens; i++) | 4073 | for (i = 0; i < sc->num_adm_permitted_opens; i++) { |
3810 | if (open_match(&permitted_adm_opens[i], host, port)) { | 4074 | fp = &sc->permitted_adm_opens[i]; |
4075 | if (open_match(fp, host, port)) { | ||
3811 | permit_adm = 1; | 4076 | permit_adm = 1; |
3812 | break; | 4077 | break; |
3813 | } | 4078 | } |
4079 | } | ||
3814 | } | 4080 | } |
3815 | 4081 | ||
3816 | if (!permit || !permit_adm) { | 4082 | if (!permit || !permit_adm) { |
@@ -3820,31 +4086,38 @@ channel_connect_to_port(const char *host, u_short port, char *ctype, | |||
3820 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; | 4086 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; |
3821 | return NULL; | 4087 | return NULL; |
3822 | } | 4088 | } |
3823 | return connect_to_reason(host, port, ctype, rname, reason, errmsg); | 4089 | return connect_to_reason(ssh, host, port, ctype, rname, reason, errmsg); |
3824 | } | 4090 | } |
3825 | 4091 | ||
3826 | /* Check if connecting to that path is permitted and connect. */ | 4092 | /* Check if connecting to that path is permitted and connect. */ |
3827 | Channel * | 4093 | Channel * |
3828 | channel_connect_to_path(const char *path, char *ctype, char *rname) | 4094 | channel_connect_to_path(struct ssh *ssh, const char *path, |
4095 | char *ctype, char *rname) | ||
3829 | { | 4096 | { |
3830 | int i, permit, permit_adm = 1; | 4097 | struct ssh_channels *sc = ssh->chanctxt; |
4098 | u_int i, permit, permit_adm = 1; | ||
4099 | ForwardPermission *fp; | ||
3831 | 4100 | ||
3832 | permit = all_opens_permitted; | 4101 | permit = sc->all_opens_permitted; |
3833 | if (!permit) { | 4102 | if (!permit) { |
3834 | for (i = 0; i < num_permitted_opens; i++) | 4103 | for (i = 0; i < sc->num_permitted_opens; i++) { |
3835 | if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) { | 4104 | fp = &sc->permitted_opens[i]; |
4105 | if (open_match(fp, path, PORT_STREAMLOCAL)) { | ||
3836 | permit = 1; | 4106 | permit = 1; |
3837 | break; | 4107 | break; |
3838 | } | 4108 | } |
4109 | } | ||
3839 | } | 4110 | } |
3840 | 4111 | ||
3841 | if (num_adm_permitted_opens > 0) { | 4112 | if (sc->num_adm_permitted_opens > 0) { |
3842 | permit_adm = 0; | 4113 | permit_adm = 0; |
3843 | for (i = 0; i < num_adm_permitted_opens; i++) | 4114 | for (i = 0; i < sc->num_adm_permitted_opens; i++) { |
3844 | if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) { | 4115 | fp = &sc->permitted_adm_opens[i]; |
4116 | if (open_match(fp, path, PORT_STREAMLOCAL)) { | ||
3845 | permit_adm = 1; | 4117 | permit_adm = 1; |
3846 | break; | 4118 | break; |
3847 | } | 4119 | } |
4120 | } | ||
3848 | } | 4121 | } |
3849 | 4122 | ||
3850 | if (!permit || !permit_adm) { | 4123 | if (!permit || !permit_adm) { |
@@ -3852,27 +4125,31 @@ channel_connect_to_path(const char *path, char *ctype, char *rname) | |||
3852 | "but the request was denied.", path); | 4125 | "but the request was denied.", path); |
3853 | return NULL; | 4126 | return NULL; |
3854 | } | 4127 | } |
3855 | return connect_to(path, PORT_STREAMLOCAL, ctype, rname); | 4128 | return connect_to(ssh, path, PORT_STREAMLOCAL, ctype, rname); |
3856 | } | 4129 | } |
3857 | 4130 | ||
3858 | void | 4131 | void |
3859 | channel_send_window_changes(void) | 4132 | channel_send_window_changes(struct ssh *ssh) |
3860 | { | 4133 | { |
3861 | u_int i; | 4134 | struct ssh_channels *sc = ssh->chanctxt; |
3862 | struct winsize ws; | 4135 | struct winsize ws; |
4136 | int r; | ||
4137 | u_int i; | ||
3863 | 4138 | ||
3864 | for (i = 0; i < channels_alloc; i++) { | 4139 | for (i = 0; i < sc->channels_alloc; i++) { |
3865 | if (channels[i] == NULL || !channels[i]->client_tty || | 4140 | if (sc->channels[i] == NULL || !sc->channels[i]->client_tty || |
3866 | channels[i]->type != SSH_CHANNEL_OPEN) | 4141 | sc->channels[i]->type != SSH_CHANNEL_OPEN) |
3867 | continue; | 4142 | continue; |
3868 | if (ioctl(channels[i]->rfd, TIOCGWINSZ, &ws) < 0) | 4143 | if (ioctl(sc->channels[i]->rfd, TIOCGWINSZ, &ws) < 0) |
3869 | continue; | 4144 | continue; |
3870 | channel_request_start(i, "window-change", 0); | 4145 | channel_request_start(ssh, i, "window-change", 0); |
3871 | packet_put_int((u_int)ws.ws_col); | 4146 | if ((r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 || |
3872 | packet_put_int((u_int)ws.ws_row); | 4147 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 || |
3873 | packet_put_int((u_int)ws.ws_xpixel); | 4148 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 || |
3874 | packet_put_int((u_int)ws.ws_ypixel); | 4149 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 || |
3875 | packet_send(); | 4150 | (r = sshpkt_send(ssh)) != 0) |
4151 | fatal("%s: channel %u: send window-change: %s", | ||
4152 | __func__, i, ssh_err(r)); | ||
3876 | } | 4153 | } |
3877 | } | 4154 | } |
3878 | 4155 | ||
@@ -3884,8 +4161,9 @@ channel_send_window_changes(void) | |||
3884 | * stored in display_numberp , or -1 if an error occurs. | 4161 | * stored in display_numberp , or -1 if an error occurs. |
3885 | */ | 4162 | */ |
3886 | int | 4163 | int |
3887 | x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | 4164 | x11_create_display_inet(struct ssh *ssh, int x11_display_offset, |
3888 | int single_connection, u_int *display_numberp, int **chanids) | 4165 | int x11_use_localhost, int single_connection, |
4166 | u_int *display_numberp, int **chanids) | ||
3889 | { | 4167 | { |
3890 | Channel *nc = NULL; | 4168 | Channel *nc = NULL; |
3891 | int display_number, sock; | 4169 | int display_number, sock; |
@@ -3902,16 +4180,18 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | |||
3902 | display_number++) { | 4180 | display_number++) { |
3903 | port = 6000 + display_number; | 4181 | port = 6000 + display_number; |
3904 | memset(&hints, 0, sizeof(hints)); | 4182 | memset(&hints, 0, sizeof(hints)); |
3905 | hints.ai_family = IPv4or6; | 4183 | hints.ai_family = ssh->chanctxt->IPv4or6; |
3906 | hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; | 4184 | hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; |
3907 | hints.ai_socktype = SOCK_STREAM; | 4185 | hints.ai_socktype = SOCK_STREAM; |
3908 | snprintf(strport, sizeof strport, "%d", port); | 4186 | snprintf(strport, sizeof strport, "%d", port); |
3909 | if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) { | 4187 | if ((gaierr = getaddrinfo(NULL, strport, |
4188 | &hints, &aitop)) != 0) { | ||
3910 | error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr)); | 4189 | error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr)); |
3911 | return -1; | 4190 | return -1; |
3912 | } | 4191 | } |
3913 | for (ai = aitop; ai; ai = ai->ai_next) { | 4192 | for (ai = aitop; ai; ai = ai->ai_next) { |
3914 | if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) | 4193 | if (ai->ai_family != AF_INET && |
4194 | ai->ai_family != AF_INET6) | ||
3915 | continue; | 4195 | continue; |
3916 | sock = socket(ai->ai_family, ai->ai_socktype, | 4196 | sock = socket(ai->ai_family, ai->ai_socktype, |
3917 | ai->ai_protocol); | 4197 | ai->ai_protocol); |
@@ -3935,12 +4215,11 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | |||
3935 | if (x11_use_localhost) | 4215 | if (x11_use_localhost) |
3936 | channel_set_reuseaddr(sock); | 4216 | channel_set_reuseaddr(sock); |
3937 | if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { | 4217 | if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
3938 | debug2("bind port %d: %.100s", port, strerror(errno)); | 4218 | debug2("%s: bind port %d: %.100s", __func__, |
4219 | port, strerror(errno)); | ||
3939 | close(sock); | 4220 | close(sock); |
3940 | 4221 | for (n = 0; n < num_socks; n++) | |
3941 | for (n = 0; n < num_socks; n++) { | ||
3942 | close(socks[n]); | 4222 | close(socks[n]); |
3943 | } | ||
3944 | num_socks = 0; | 4223 | num_socks = 0; |
3945 | break; | 4224 | break; |
3946 | } | 4225 | } |
@@ -3970,7 +4249,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | |||
3970 | *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); | 4249 | *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); |
3971 | for (n = 0; n < num_socks; n++) { | 4250 | for (n = 0; n < num_socks; n++) { |
3972 | sock = socks[n]; | 4251 | sock = socks[n]; |
3973 | nc = channel_new("x11 listener", | 4252 | nc = channel_new(ssh, "x11 listener", |
3974 | SSH_CHANNEL_X11_LISTENER, sock, sock, -1, | 4253 | SSH_CHANNEL_X11_LISTENER, sock, sock, -1, |
3975 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, | 4254 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, |
3976 | 0, "X11 inet listener", 1); | 4255 | 0, "X11 inet listener", 1); |
@@ -3981,7 +4260,7 @@ x11_create_display_inet(int x11_display_offset, int x11_use_localhost, | |||
3981 | 4260 | ||
3982 | /* Return the display number for the DISPLAY environment variable. */ | 4261 | /* Return the display number for the DISPLAY environment variable. */ |
3983 | *display_numberp = display_number; | 4262 | *display_numberp = display_number; |
3984 | return (0); | 4263 | return 0; |
3985 | } | 4264 | } |
3986 | 4265 | ||
3987 | static int | 4266 | static int |
@@ -4039,7 +4318,7 @@ is_path_to_xsocket(const char *display, char *path, size_t pathlen) | |||
4039 | #endif | 4318 | #endif |
4040 | 4319 | ||
4041 | int | 4320 | int |
4042 | x11_connect_display(void) | 4321 | x11_connect_display(struct ssh *ssh) |
4043 | { | 4322 | { |
4044 | u_int display_number; | 4323 | u_int display_number; |
4045 | const char *display; | 4324 | const char *display; |
@@ -4084,9 +4363,10 @@ x11_connect_display(void) | |||
4084 | if (strncmp(display, "unix:", 5) == 0 || | 4363 | if (strncmp(display, "unix:", 5) == 0 || |
4085 | display[0] == ':') { | 4364 | display[0] == ':') { |
4086 | /* Connect to the unix domain socket. */ | 4365 | /* Connect to the unix domain socket. */ |
4087 | if (sscanf(strrchr(display, ':') + 1, "%u", &display_number) != 1) { | 4366 | if (sscanf(strrchr(display, ':') + 1, "%u", |
4088 | error("Could not parse display number from DISPLAY: %.100s", | 4367 | &display_number) != 1) { |
4089 | display); | 4368 | error("Could not parse display number from DISPLAY: " |
4369 | "%.100s", display); | ||
4090 | return -1; | 4370 | return -1; |
4091 | } | 4371 | } |
4092 | /* Create a socket. */ | 4372 | /* Create a socket. */ |
@@ -4108,7 +4388,10 @@ x11_connect_display(void) | |||
4108 | return -1; | 4388 | return -1; |
4109 | } | 4389 | } |
4110 | *cp = 0; | 4390 | *cp = 0; |
4111 | /* buf now contains the host name. But first we parse the display number. */ | 4391 | /* |
4392 | * buf now contains the host name. But first we parse the | ||
4393 | * display number. | ||
4394 | */ | ||
4112 | if (sscanf(cp + 1, "%u", &display_number) != 1) { | 4395 | if (sscanf(cp + 1, "%u", &display_number) != 1) { |
4113 | error("Could not parse display number from DISPLAY: %.100s", | 4396 | error("Could not parse display number from DISPLAY: %.100s", |
4114 | display); | 4397 | display); |
@@ -4117,7 +4400,7 @@ x11_connect_display(void) | |||
4117 | 4400 | ||
4118 | /* Look up the host address */ | 4401 | /* Look up the host address */ |
4119 | memset(&hints, 0, sizeof(hints)); | 4402 | memset(&hints, 0, sizeof(hints)); |
4120 | hints.ai_family = IPv4or6; | 4403 | hints.ai_family = ssh->chanctxt->IPv4or6; |
4121 | hints.ai_socktype = SOCK_STREAM; | 4404 | hints.ai_socktype = SOCK_STREAM; |
4122 | snprintf(strport, sizeof strport, "%u", 6000 + display_number); | 4405 | snprintf(strport, sizeof strport, "%u", 6000 + display_number); |
4123 | if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { | 4406 | if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { |
@@ -4144,8 +4427,8 @@ x11_connect_display(void) | |||
4144 | } | 4427 | } |
4145 | freeaddrinfo(aitop); | 4428 | freeaddrinfo(aitop); |
4146 | if (!ai) { | 4429 | if (!ai) { |
4147 | error("connect %.100s port %u: %.100s", buf, 6000 + display_number, | 4430 | error("connect %.100s port %u: %.100s", buf, |
4148 | strerror(errno)); | 4431 | 6000 + display_number, strerror(errno)); |
4149 | return -1; | 4432 | return -1; |
4150 | } | 4433 | } |
4151 | set_nodelay(sock); | 4434 | set_nodelay(sock); |
@@ -4158,18 +4441,19 @@ x11_connect_display(void) | |||
4158 | * This should be called in the client only. | 4441 | * This should be called in the client only. |
4159 | */ | 4442 | */ |
4160 | void | 4443 | void |
4161 | x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, | 4444 | x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id, |
4162 | const char *proto, const char *data, int want_reply) | 4445 | const char *disp, const char *proto, const char *data, int want_reply) |
4163 | { | 4446 | { |
4447 | struct ssh_channels *sc = ssh->chanctxt; | ||
4164 | u_int data_len = (u_int) strlen(data) / 2; | 4448 | u_int data_len = (u_int) strlen(data) / 2; |
4165 | u_int i, value; | 4449 | u_int i, value; |
4166 | char *new_data; | ||
4167 | int screen_number; | ||
4168 | const char *cp; | 4450 | const char *cp; |
4451 | char *new_data; | ||
4452 | int r, screen_number; | ||
4169 | 4453 | ||
4170 | if (x11_saved_display == NULL) | 4454 | if (sc->x11_saved_display == NULL) |
4171 | x11_saved_display = xstrdup(disp); | 4455 | sc->x11_saved_display = xstrdup(disp); |
4172 | else if (strcmp(disp, x11_saved_display) != 0) { | 4456 | else if (strcmp(disp, sc->x11_saved_display) != 0) { |
4173 | error("x11_request_forwarding_with_spoofing: different " | 4457 | error("x11_request_forwarding_with_spoofing: different " |
4174 | "$DISPLAY already forwarded"); | 4458 | "$DISPLAY already forwarded"); |
4175 | return; | 4459 | return; |
@@ -4183,36 +4467,37 @@ x11_request_forwarding_with_spoofing(int client_session_id, const char *disp, | |||
4183 | else | 4467 | else |
4184 | screen_number = 0; | 4468 | screen_number = 0; |
4185 | 4469 | ||
4186 | if (x11_saved_proto == NULL) { | 4470 | if (sc->x11_saved_proto == NULL) { |
4187 | /* Save protocol name. */ | 4471 | /* Save protocol name. */ |
4188 | x11_saved_proto = xstrdup(proto); | 4472 | sc->x11_saved_proto = xstrdup(proto); |
4189 | 4473 | ||
4190 | /* Extract real authentication data. */ | 4474 | /* Extract real authentication data. */ |
4191 | x11_saved_data = xmalloc(data_len); | 4475 | sc->x11_saved_data = xmalloc(data_len); |
4192 | for (i = 0; i < data_len; i++) { | 4476 | for (i = 0; i < data_len; i++) { |
4193 | if (sscanf(data + 2 * i, "%2x", &value) != 1) | 4477 | if (sscanf(data + 2 * i, "%2x", &value) != 1) |
4194 | fatal("x11_request_forwarding: bad " | 4478 | fatal("x11_request_forwarding: bad " |
4195 | "authentication data: %.100s", data); | 4479 | "authentication data: %.100s", data); |
4196 | x11_saved_data[i] = value; | 4480 | sc->x11_saved_data[i] = value; |
4197 | } | 4481 | } |
4198 | x11_saved_data_len = data_len; | 4482 | sc->x11_saved_data_len = data_len; |
4199 | 4483 | ||
4200 | /* Generate fake data of the same length. */ | 4484 | /* Generate fake data of the same length. */ |
4201 | x11_fake_data = xmalloc(data_len); | 4485 | sc->x11_fake_data = xmalloc(data_len); |
4202 | arc4random_buf(x11_fake_data, data_len); | 4486 | arc4random_buf(sc->x11_fake_data, data_len); |
4203 | x11_fake_data_len = data_len; | 4487 | sc->x11_fake_data_len = data_len; |
4204 | } | 4488 | } |
4205 | 4489 | ||
4206 | /* Convert the fake data into hex. */ | 4490 | /* Convert the fake data into hex. */ |
4207 | new_data = tohex(x11_fake_data, data_len); | 4491 | new_data = tohex(sc->x11_fake_data, data_len); |
4208 | 4492 | ||
4209 | /* Send the request packet. */ | 4493 | /* Send the request packet. */ |
4210 | channel_request_start(client_session_id, "x11-req", want_reply); | 4494 | channel_request_start(ssh, client_session_id, "x11-req", want_reply); |
4211 | packet_put_char(0); /* XXX bool single connection */ | 4495 | if ((r = sshpkt_put_u8(ssh, 0)) != 0 || /* bool: single connection */ |
4212 | packet_put_cstring(proto); | 4496 | (r = sshpkt_put_cstring(ssh, proto)) != 0 || |
4213 | packet_put_cstring(new_data); | 4497 | (r = sshpkt_put_cstring(ssh, new_data)) != 0 || |
4214 | packet_put_int(screen_number); | 4498 | (r = sshpkt_put_u32(ssh, screen_number)) != 0 || |
4215 | packet_send(); | 4499 | (r = sshpkt_send(ssh)) != 0 || |
4216 | packet_write_wait(); | 4500 | (r = ssh_packet_write_wait(ssh)) != 0) |
4501 | fatal("%s: send x11-req: %s", __func__, ssh_err(r)); | ||
4217 | free(new_data); | 4502 | free(new_data); |
4218 | } | 4503 | } |
diff --git a/channels.h b/channels.h index 5ecb4d7c0..f04c43afa 100644 --- a/channels.h +++ b/channels.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: channels.h,v 1.127 2017/08/30 03:59:08 djm Exp $ */ | 1 | /* $OpenBSD: channels.h,v 1.128 2017/09/12 06:32:07 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -64,16 +64,18 @@ | |||
64 | struct ssh; | 64 | struct ssh; |
65 | struct Channel; | 65 | struct Channel; |
66 | typedef struct Channel Channel; | 66 | typedef struct Channel Channel; |
67 | struct fwd_perm_list; | ||
67 | 68 | ||
68 | typedef void channel_open_fn(int, int, void *); | 69 | typedef void channel_open_fn(struct ssh *, int, int, void *); |
69 | typedef void channel_callback_fn(int, void *); | 70 | typedef void channel_callback_fn(struct ssh *, int, void *); |
70 | typedef int channel_infilter_fn(struct Channel *, char *, int); | 71 | typedef int channel_infilter_fn(struct ssh *, struct Channel *, char *, int); |
71 | typedef void channel_filter_cleanup_fn(int, void *); | 72 | typedef void channel_filter_cleanup_fn(struct ssh *, int, void *); |
72 | typedef u_char *channel_outfilter_fn(struct Channel *, u_char **, u_int *); | 73 | typedef u_char *channel_outfilter_fn(struct ssh *, struct Channel *, |
74 | u_char **, size_t *); | ||
73 | 75 | ||
74 | /* Channel success/failure callbacks */ | 76 | /* Channel success/failure callbacks */ |
75 | typedef void channel_confirm_cb(int, struct Channel *, void *); | 77 | typedef void channel_confirm_cb(struct ssh *, int, struct Channel *, void *); |
76 | typedef void channel_confirm_abandon_cb(struct Channel *, void *); | 78 | typedef void channel_confirm_abandon_cb(struct ssh *, struct Channel *, void *); |
77 | struct channel_confirm { | 79 | struct channel_confirm { |
78 | TAILQ_ENTRY(channel_confirm) entry; | 80 | TAILQ_ENTRY(channel_confirm) entry; |
79 | channel_confirm_cb *cb; | 81 | channel_confirm_cb *cb; |
@@ -90,12 +92,13 @@ struct channel_connect { | |||
90 | }; | 92 | }; |
91 | 93 | ||
92 | /* Callbacks for mux channels back into client-specific code */ | 94 | /* Callbacks for mux channels back into client-specific code */ |
93 | typedef int mux_callback_fn(struct Channel *); | 95 | typedef int mux_callback_fn(struct ssh *, struct Channel *); |
94 | 96 | ||
95 | struct Channel { | 97 | struct Channel { |
96 | int type; /* channel type/state */ | 98 | int type; /* channel type/state */ |
97 | int self; /* my own channel identifier */ | 99 | int self; /* my own channel identifier */ |
98 | int remote_id; /* channel identifier for remote peer */ | 100 | int remote_id; /* channel identifier for remote peer */ |
101 | /* XXX should be uint32_t */ | ||
99 | u_int istate; /* input from channel (state of receive half) */ | 102 | u_int istate; /* input from channel (state of receive half) */ |
100 | u_int ostate; /* output to channel (state of transmit half) */ | 103 | u_int ostate; /* output to channel (state of transmit half) */ |
101 | int flags; /* close sent/rcvd */ | 104 | int flags; /* close sent/rcvd */ |
@@ -116,11 +119,12 @@ struct Channel { | |||
116 | * to a matching pre-select handler. | 119 | * to a matching pre-select handler. |
117 | * this way post-select handlers are not | 120 | * this way post-select handlers are not |
118 | * accidentally called if a FD gets reused */ | 121 | * accidentally called if a FD gets reused */ |
119 | Buffer input; /* data read from socket, to be sent over | 122 | struct sshbuf *input; /* data read from socket, to be sent over |
120 | * encrypted connection */ | 123 | * encrypted connection */ |
121 | Buffer output; /* data received over encrypted connection for | 124 | struct sshbuf *output; /* data received over encrypted connection for |
122 | * send on socket */ | 125 | * send on socket */ |
123 | Buffer extended; | 126 | struct sshbuf *extended; |
127 | |||
124 | char *path; | 128 | char *path; |
125 | /* path for unix domain sockets, or host name for forwards */ | 129 | /* path for unix domain sockets, or host name for forwards */ |
126 | int listening_port; /* port being listened for forwards */ | 130 | int listening_port; /* port being listened for forwards */ |
@@ -156,6 +160,7 @@ struct Channel { | |||
156 | int datagram; | 160 | int datagram; |
157 | 161 | ||
158 | /* non-blocking connect */ | 162 | /* non-blocking connect */ |
163 | /* XXX make this a pointer so the structure can be opaque */ | ||
159 | struct channel_connect connect_ctx; | 164 | struct channel_connect connect_ctx; |
160 | 165 | ||
161 | /* multiplexing protocol hook, called for each packet received */ | 166 | /* multiplexing protocol hook, called for each packet received */ |
@@ -195,44 +200,55 @@ struct Channel { | |||
195 | #define CHAN_EOF_RCVD 0x08 | 200 | #define CHAN_EOF_RCVD 0x08 |
196 | #define CHAN_LOCAL 0x10 | 201 | #define CHAN_LOCAL 0x10 |
197 | 202 | ||
198 | #define CHAN_RBUF 16*1024 | 203 | /* Read buffer size */ |
204 | #define CHAN_RBUF (16*1024) | ||
205 | |||
206 | /* Hard limit on number of channels */ | ||
207 | #define CHANNELS_MAX_CHANNELS (16*1024) | ||
199 | 208 | ||
200 | /* check whether 'efd' is still in use */ | 209 | /* check whether 'efd' is still in use */ |
201 | #define CHANNEL_EFD_INPUT_ACTIVE(c) \ | 210 | #define CHANNEL_EFD_INPUT_ACTIVE(c) \ |
202 | (c->extended_usage == CHAN_EXTENDED_READ && \ | 211 | (c->extended_usage == CHAN_EXTENDED_READ && \ |
203 | (c->efd != -1 || \ | 212 | (c->efd != -1 || \ |
204 | buffer_len(&c->extended) > 0)) | 213 | sshbuf_len(c->extended) > 0)) |
205 | #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ | 214 | #define CHANNEL_EFD_OUTPUT_ACTIVE(c) \ |
206 | (c->extended_usage == CHAN_EXTENDED_WRITE && \ | 215 | (c->extended_usage == CHAN_EXTENDED_WRITE && \ |
207 | c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ | 216 | c->efd != -1 && (!(c->flags & (CHAN_EOF_RCVD|CHAN_CLOSE_RCVD)) || \ |
208 | buffer_len(&c->extended) > 0)) | 217 | sshbuf_len(c->extended) > 0)) |
218 | |||
219 | /* Add channel management structures to SSH transport instance */ | ||
220 | void channel_init_channels(struct ssh *ssh); | ||
209 | 221 | ||
210 | /* channel management */ | 222 | /* channel management */ |
211 | 223 | ||
212 | Channel *channel_by_id(int); | 224 | Channel *channel_by_id(struct ssh *, int); |
213 | Channel *channel_by_remote_id(int); | 225 | Channel *channel_by_remote_id(struct ssh *, int); |
214 | Channel *channel_lookup(int); | 226 | Channel *channel_lookup(struct ssh *, int); |
215 | Channel *channel_new(char *, int, int, int, int, u_int, u_int, int, char *, int); | 227 | Channel *channel_new(struct ssh *, char *, int, int, int, int, |
216 | void channel_set_fds(int, int, int, int, int, int, int, u_int); | 228 | u_int, u_int, int, char *, int); |
217 | void channel_free(Channel *); | 229 | void channel_set_fds(struct ssh *, int, int, int, int, int, |
218 | void channel_free_all(void); | 230 | int, int, u_int); |
219 | void channel_stop_listening(void); | 231 | void channel_free(struct ssh *, Channel *); |
220 | 232 | void channel_free_all(struct ssh *); | |
221 | void channel_send_open(int); | 233 | void channel_stop_listening(struct ssh *); |
222 | void channel_request_start(int, char *, int); | 234 | |
223 | void channel_register_cleanup(int, channel_callback_fn *, int); | 235 | void channel_send_open(struct ssh *, int); |
224 | void channel_register_open_confirm(int, channel_open_fn *, void *); | 236 | void channel_request_start(struct ssh *, int, char *, int); |
225 | void channel_register_filter(int, channel_infilter_fn *, | 237 | void channel_register_cleanup(struct ssh *, int, |
226 | channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); | 238 | channel_callback_fn *, int); |
227 | void channel_register_status_confirm(int, channel_confirm_cb *, | 239 | void channel_register_open_confirm(struct ssh *, int, |
228 | channel_confirm_abandon_cb *, void *); | 240 | channel_open_fn *, void *); |
229 | void channel_cancel_cleanup(int); | 241 | void channel_register_filter(struct ssh *, int, channel_infilter_fn *, |
230 | int channel_close_fd(int *); | 242 | channel_outfilter_fn *, channel_filter_cleanup_fn *, void *); |
231 | void channel_send_window_changes(void); | 243 | void channel_register_status_confirm(struct ssh *, int, |
244 | channel_confirm_cb *, channel_confirm_abandon_cb *, void *); | ||
245 | void channel_cancel_cleanup(struct ssh *, int); | ||
246 | int channel_close_fd(struct ssh *, int *); | ||
247 | void channel_send_window_changes(struct ssh *); | ||
232 | 248 | ||
233 | /* mux proxy support */ | 249 | /* mux proxy support */ |
234 | 250 | ||
235 | int channel_proxy_downstream(Channel *mc); | 251 | int channel_proxy_downstream(struct ssh *, Channel *mc); |
236 | int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *); | 252 | int channel_proxy_upstream(Channel *, int, u_int32_t, struct ssh *); |
237 | 253 | ||
238 | /* protocol handler */ | 254 | /* protocol handler */ |
@@ -252,63 +268,69 @@ int channel_input_status_confirm(int, u_int32_t, struct ssh *); | |||
252 | void channel_prepare_select(struct ssh *, fd_set **, fd_set **, int *, | 268 | void channel_prepare_select(struct ssh *, fd_set **, fd_set **, int *, |
253 | u_int*, time_t*); | 269 | u_int*, time_t*); |
254 | void channel_after_select(struct ssh *, fd_set *, fd_set *); | 270 | void channel_after_select(struct ssh *, fd_set *, fd_set *); |
255 | void channel_output_poll(void); | 271 | void channel_output_poll(struct ssh *); |
256 | 272 | ||
257 | int channel_not_very_much_buffered_data(void); | 273 | int channel_not_very_much_buffered_data(struct ssh *); |
258 | void channel_close_all(void); | 274 | void channel_close_all(struct ssh *); |
259 | int channel_still_open(void); | 275 | int channel_still_open(struct ssh *); |
260 | char *channel_open_message(void); | 276 | char *channel_open_message(struct ssh *); |
261 | int channel_find_open(void); | 277 | int channel_find_open(struct ssh *); |
262 | 278 | ||
263 | /* tcp forwarding */ | 279 | /* tcp forwarding */ |
264 | struct Forward; | 280 | struct Forward; |
265 | struct ForwardOptions; | 281 | struct ForwardOptions; |
266 | void channel_set_af(int af); | 282 | void channel_set_af(struct ssh *, int af); |
267 | void channel_permit_all_opens(void); | 283 | void channel_permit_all_opens(struct ssh *); |
268 | void channel_add_permitted_opens(char *, int); | 284 | void channel_add_permitted_opens(struct ssh *, char *, int); |
269 | int channel_add_adm_permitted_opens(char *, int); | 285 | int channel_add_adm_permitted_opens(struct ssh *, char *, int); |
270 | void channel_disable_adm_local_opens(void); | 286 | void channel_copy_adm_permitted_opens(struct ssh *, |
271 | void channel_update_permitted_opens(int, int); | 287 | const struct fwd_perm_list *); |
272 | void channel_clear_permitted_opens(void); | 288 | void channel_disable_adm_local_opens(struct ssh *); |
273 | void channel_clear_adm_permitted_opens(void); | 289 | void channel_update_permitted_opens(struct ssh *, int, int); |
274 | void channel_print_adm_permitted_opens(void); | 290 | void channel_clear_permitted_opens(struct ssh *); |
275 | Channel *channel_connect_to_port(const char *, u_short, char *, char *, int *, | 291 | void channel_clear_adm_permitted_opens(struct ssh *); |
276 | const char **); | 292 | void channel_print_adm_permitted_opens(struct ssh *); |
277 | Channel *channel_connect_to_path(const char *, char *, char *); | 293 | Channel *channel_connect_to_port(struct ssh *, const char *, u_short, |
278 | Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); | 294 | char *, char *, int *, const char **); |
279 | Channel *channel_connect_by_listen_address(const char *, u_short, | 295 | Channel *channel_connect_to_path(struct ssh *, const char *, char *, char *); |
280 | char *, char *); | 296 | Channel *channel_connect_stdio_fwd(struct ssh *, const char*, |
281 | Channel *channel_connect_by_listen_path(const char *, char *, char *); | 297 | u_short, int, int); |
282 | int channel_request_remote_forwarding(struct Forward *); | 298 | Channel *channel_connect_by_listen_address(struct ssh *, const char *, |
283 | int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *); | 299 | u_short, char *, char *); |
284 | int channel_request_rforward_cancel(struct Forward *); | 300 | Channel *channel_connect_by_listen_path(struct ssh *, const char *, |
285 | int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *); | 301 | char *, char *); |
286 | int channel_cancel_rport_listener(struct Forward *); | 302 | int channel_request_remote_forwarding(struct ssh *, struct Forward *); |
287 | int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *); | 303 | int channel_setup_local_fwd_listener(struct ssh *, struct Forward *, |
304 | struct ForwardOptions *); | ||
305 | int channel_request_rforward_cancel(struct ssh *, struct Forward *); | ||
306 | int channel_setup_remote_fwd_listener(struct ssh *, struct Forward *, | ||
307 | int *, struct ForwardOptions *); | ||
308 | int channel_cancel_rport_listener(struct ssh *, struct Forward *); | ||
309 | int channel_cancel_lport_listener(struct ssh *, struct Forward *, | ||
310 | int, struct ForwardOptions *); | ||
288 | int permitopen_port(const char *); | 311 | int permitopen_port(const char *); |
289 | 312 | ||
290 | /* x11 forwarding */ | 313 | /* x11 forwarding */ |
291 | 314 | ||
292 | void channel_set_x11_refuse_time(u_int); | 315 | void channel_set_x11_refuse_time(struct ssh *, u_int); |
293 | int x11_connect_display(void); | 316 | int x11_connect_display(struct ssh *); |
294 | int x11_create_display_inet(int, int, int, u_int *, int **); | 317 | int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **); |
295 | void x11_request_forwarding_with_spoofing(int, const char *, const char *, | 318 | void x11_request_forwarding_with_spoofing(struct ssh *, int, |
296 | const char *, int); | 319 | const char *, const char *, const char *, int); |
297 | 320 | ||
298 | /* channel close */ | 321 | /* channel close */ |
299 | 322 | ||
300 | int chan_is_dead(Channel *, int); | 323 | int chan_is_dead(struct ssh *, Channel *, int); |
301 | void chan_mark_dead(Channel *); | 324 | void chan_mark_dead(struct ssh *, Channel *); |
302 | 325 | ||
303 | /* channel events */ | 326 | /* channel events */ |
304 | 327 | ||
305 | void chan_rcvd_oclose(Channel *); | 328 | void chan_rcvd_oclose(struct ssh *, Channel *); |
306 | void chan_rcvd_eow(Channel *); /* SSH2-only */ | 329 | void chan_rcvd_eow(struct ssh *, Channel *); |
307 | void chan_read_failed(Channel *); | 330 | void chan_read_failed(struct ssh *, Channel *); |
308 | void chan_ibuf_empty(Channel *); | 331 | void chan_ibuf_empty(struct ssh *, Channel *); |
309 | 332 | void chan_rcvd_ieof(struct ssh *, Channel *); | |
310 | void chan_rcvd_ieof(Channel *); | 333 | void chan_write_failed(struct ssh *, Channel *); |
311 | void chan_write_failed(Channel *); | 334 | void chan_obuf_empty(struct ssh *, Channel *); |
312 | void chan_obuf_empty(Channel *); | ||
313 | 335 | ||
314 | #endif | 336 | #endif |
diff --git a/clientloop.c b/clientloop.c index 2934c4763..1218b3b71 100644 --- a/clientloop.c +++ b/clientloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.c,v 1.302 2017/08/30 03:59:08 djm Exp $ */ | 1 | /* $OpenBSD: clientloop.c,v 1.303 2017/09/12 06:32:07 djm 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 |
@@ -177,6 +177,7 @@ struct channel_reply_ctx { | |||
177 | }; | 177 | }; |
178 | 178 | ||
179 | /* Global request success/failure callbacks */ | 179 | /* Global request success/failure callbacks */ |
180 | /* XXX move to struct ssh? */ | ||
180 | struct global_confirm { | 181 | struct global_confirm { |
181 | TAILQ_ENTRY(global_confirm) entry; | 182 | TAILQ_ENTRY(global_confirm) entry; |
182 | global_confirm_cb *cb; | 183 | global_confirm_cb *cb; |
@@ -244,13 +245,13 @@ get_current_time(void) | |||
244 | * control master process, or if there is no ControlPersist timeout. | 245 | * control master process, or if there is no ControlPersist timeout. |
245 | */ | 246 | */ |
246 | static void | 247 | static void |
247 | set_control_persist_exit_time(void) | 248 | set_control_persist_exit_time(struct ssh *ssh) |
248 | { | 249 | { |
249 | if (muxserver_sock == -1 || !options.control_persist | 250 | if (muxserver_sock == -1 || !options.control_persist |
250 | || options.control_persist_timeout == 0) { | 251 | || options.control_persist_timeout == 0) { |
251 | /* not using a ControlPersist timeout */ | 252 | /* not using a ControlPersist timeout */ |
252 | control_persist_exit_time = 0; | 253 | control_persist_exit_time = 0; |
253 | } else if (channel_still_open()) { | 254 | } else if (channel_still_open(ssh)) { |
254 | /* some client connections are still open */ | 255 | /* some client connections are still open */ |
255 | if (control_persist_exit_time > 0) | 256 | if (control_persist_exit_time > 0) |
256 | debug2("%s: cancel scheduled exit", __func__); | 257 | debug2("%s: cancel scheduled exit", __func__); |
@@ -288,8 +289,9 @@ client_x11_display_valid(const char *display) | |||
288 | #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" | 289 | #define SSH_X11_PROTO "MIT-MAGIC-COOKIE-1" |
289 | #define X11_TIMEOUT_SLACK 60 | 290 | #define X11_TIMEOUT_SLACK 60 |
290 | int | 291 | int |
291 | client_x11_get_proto(const char *display, const char *xauth_path, | 292 | client_x11_get_proto(struct ssh *ssh, const char *display, |
292 | u_int trusted, u_int timeout, char **_proto, char **_data) | 293 | const char *xauth_path, u_int trusted, u_int timeout, |
294 | char **_proto, char **_data) | ||
293 | { | 295 | { |
294 | char cmd[1024], line[512], xdisplay[512]; | 296 | char cmd[1024], line[512], xdisplay[512]; |
295 | char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; | 297 | char xauthfile[PATH_MAX], xauthdir[PATH_MAX]; |
@@ -373,7 +375,8 @@ client_x11_get_proto(const char *display, const char *xauth_path, | |||
373 | x11_refuse_time = UINT_MAX; | 375 | x11_refuse_time = UINT_MAX; |
374 | else | 376 | else |
375 | x11_refuse_time = now + timeout; | 377 | x11_refuse_time = now + timeout; |
376 | channel_set_x11_refuse_time(x11_refuse_time); | 378 | channel_set_x11_refuse_time(ssh, |
379 | x11_refuse_time); | ||
377 | } | 380 | } |
378 | if (system(cmd) == 0) | 381 | if (system(cmd) == 0) |
379 | generated = 1; | 382 | generated = 1; |
@@ -446,7 +449,7 @@ client_x11_get_proto(const char *display, const char *xauth_path, | |||
446 | */ | 449 | */ |
447 | 450 | ||
448 | static void | 451 | static void |
449 | client_check_window_change(void) | 452 | client_check_window_change(struct ssh *ssh) |
450 | { | 453 | { |
451 | if (!received_window_change_signal) | 454 | if (!received_window_change_signal) |
452 | return; | 455 | return; |
@@ -455,7 +458,7 @@ client_check_window_change(void) | |||
455 | 458 | ||
456 | debug2("%s: changed", __func__); | 459 | debug2("%s: changed", __func__); |
457 | 460 | ||
458 | channel_send_window_changes(); | 461 | channel_send_window_changes(ssh); |
459 | } | 462 | } |
460 | 463 | ||
461 | static int | 464 | static int |
@@ -466,7 +469,7 @@ client_global_request_reply(int type, u_int32_t seq, struct ssh *ssh) | |||
466 | if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) | 469 | if ((gc = TAILQ_FIRST(&global_confirms)) == NULL) |
467 | return 0; | 470 | return 0; |
468 | if (gc->cb != NULL) | 471 | if (gc->cb != NULL) |
469 | gc->cb(type, seq, gc->ctx); | 472 | gc->cb(ssh, type, seq, gc->ctx); |
470 | if (--gc->ref_count <= 0) { | 473 | if (--gc->ref_count <= 0) { |
471 | TAILQ_REMOVE(&global_confirms, gc, entry); | 474 | TAILQ_REMOVE(&global_confirms, gc, entry); |
472 | explicit_bzero(gc, sizeof(*gc)); | 475 | explicit_bzero(gc, sizeof(*gc)); |
@@ -497,7 +500,8 @@ server_alive_check(void) | |||
497 | * one of the file descriptors). | 500 | * one of the file descriptors). |
498 | */ | 501 | */ |
499 | static void | 502 | static void |
500 | client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | 503 | client_wait_until_can_do_something(struct ssh *ssh, |
504 | fd_set **readsetp, fd_set **writesetp, | ||
501 | int *maxfdp, u_int *nallocp, int rekeying) | 505 | int *maxfdp, u_int *nallocp, int rekeying) |
502 | { | 506 | { |
503 | struct timeval tv, *tvp; | 507 | struct timeval tv, *tvp; |
@@ -510,7 +514,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
510 | nallocp, &minwait_secs); | 514 | nallocp, &minwait_secs); |
511 | 515 | ||
512 | /* channel_prepare_select could have closed the last channel */ | 516 | /* channel_prepare_select could have closed the last channel */ |
513 | if (session_closed && !channel_still_open() && | 517 | if (session_closed && !channel_still_open(ssh) && |
514 | !packet_have_data_to_write()) { | 518 | !packet_have_data_to_write()) { |
515 | /* clear mask since we did not call select() */ | 519 | /* clear mask since we did not call select() */ |
516 | memset(*readsetp, 0, *nallocp); | 520 | memset(*readsetp, 0, *nallocp); |
@@ -537,7 +541,7 @@ client_wait_until_can_do_something(fd_set **readsetp, fd_set **writesetp, | |||
537 | } | 541 | } |
538 | if (options.rekey_interval > 0 && !rekeying) | 542 | if (options.rekey_interval > 0 && !rekeying) |
539 | timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); | 543 | timeout_secs = MINIMUM(timeout_secs, packet_get_rekey_timeout()); |
540 | set_control_persist_exit_time(); | 544 | set_control_persist_exit_time(ssh); |
541 | if (control_persist_exit_time > 0) { | 545 | if (control_persist_exit_time > 0) { |
542 | timeout_secs = MINIMUM(timeout_secs, | 546 | timeout_secs = MINIMUM(timeout_secs, |
543 | control_persist_exit_time - now); | 547 | control_persist_exit_time - now); |
@@ -668,7 +672,7 @@ client_process_net_input(fd_set *readset) | |||
668 | } | 672 | } |
669 | 673 | ||
670 | static void | 674 | static void |
671 | client_status_confirm(int type, Channel *c, void *ctx) | 675 | client_status_confirm(struct ssh *ssh, int type, Channel *c, void *ctx) |
672 | { | 676 | { |
673 | struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; | 677 | struct channel_reply_ctx *cr = (struct channel_reply_ctx *)ctx; |
674 | char errmsg[256]; | 678 | char errmsg[256]; |
@@ -707,8 +711,7 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
707 | * their stderr. | 711 | * their stderr. |
708 | */ | 712 | */ |
709 | if (tochan) { | 713 | if (tochan) { |
710 | buffer_append(&c->extended, errmsg, | 714 | buffer_append(c->extended, errmsg, strlen(errmsg)); |
711 | strlen(errmsg)); | ||
712 | } else | 715 | } else |
713 | error("%s", errmsg); | 716 | error("%s", errmsg); |
714 | if (cr->action == CONFIRM_TTY) { | 717 | if (cr->action == CONFIRM_TTY) { |
@@ -719,23 +722,23 @@ client_status_confirm(int type, Channel *c, void *ctx) | |||
719 | if (c->self == session_ident) | 722 | if (c->self == session_ident) |
720 | leave_raw_mode(0); | 723 | leave_raw_mode(0); |
721 | else | 724 | else |
722 | mux_tty_alloc_failed(c); | 725 | mux_tty_alloc_failed(ssh, c); |
723 | } else if (cr->action == CONFIRM_CLOSE) { | 726 | } else if (cr->action == CONFIRM_CLOSE) { |
724 | chan_read_failed(c); | 727 | chan_read_failed(ssh, c); |
725 | chan_write_failed(c); | 728 | chan_write_failed(ssh, c); |
726 | } | 729 | } |
727 | } | 730 | } |
728 | free(cr); | 731 | free(cr); |
729 | } | 732 | } |
730 | 733 | ||
731 | static void | 734 | static void |
732 | client_abandon_status_confirm(Channel *c, void *ctx) | 735 | client_abandon_status_confirm(struct ssh *ssh, Channel *c, void *ctx) |
733 | { | 736 | { |
734 | free(ctx); | 737 | free(ctx); |
735 | } | 738 | } |
736 | 739 | ||
737 | void | 740 | void |
738 | client_expect_confirm(int id, const char *request, | 741 | client_expect_confirm(struct ssh *ssh, int id, const char *request, |
739 | enum confirm_action action) | 742 | enum confirm_action action) |
740 | { | 743 | { |
741 | struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); | 744 | struct channel_reply_ctx *cr = xcalloc(1, sizeof(*cr)); |
@@ -743,7 +746,7 @@ client_expect_confirm(int id, const char *request, | |||
743 | cr->request_type = request; | 746 | cr->request_type = request; |
744 | cr->action = action; | 747 | cr->action = action; |
745 | 748 | ||
746 | channel_register_status_confirm(id, client_status_confirm, | 749 | channel_register_status_confirm(ssh, id, client_status_confirm, |
747 | client_abandon_status_confirm, cr); | 750 | client_abandon_status_confirm, cr); |
748 | } | 751 | } |
749 | 752 | ||
@@ -769,7 +772,7 @@ client_register_global_confirm(global_confirm_cb *cb, void *ctx) | |||
769 | } | 772 | } |
770 | 773 | ||
771 | static void | 774 | static void |
772 | process_cmdline(void) | 775 | process_cmdline(struct ssh *ssh) |
773 | { | 776 | { |
774 | void (*handler)(int); | 777 | void (*handler)(int); |
775 | char *s, *cmd; | 778 | char *s, *cmd; |
@@ -843,12 +846,12 @@ process_cmdline(void) | |||
843 | goto out; | 846 | goto out; |
844 | } | 847 | } |
845 | if (remote) | 848 | if (remote) |
846 | ok = channel_request_rforward_cancel(&fwd) == 0; | 849 | ok = channel_request_rforward_cancel(ssh, &fwd) == 0; |
847 | else if (dynamic) | 850 | else if (dynamic) |
848 | ok = channel_cancel_lport_listener(&fwd, | 851 | ok = channel_cancel_lport_listener(ssh, &fwd, |
849 | 0, &options.fwd_opts) > 0; | 852 | 0, &options.fwd_opts) > 0; |
850 | else | 853 | else |
851 | ok = channel_cancel_lport_listener(&fwd, | 854 | ok = channel_cancel_lport_listener(ssh, &fwd, |
852 | CHANNEL_CANCEL_PORT_STATIC, | 855 | CHANNEL_CANCEL_PORT_STATIC, |
853 | &options.fwd_opts) > 0; | 856 | &options.fwd_opts) > 0; |
854 | if (!ok) { | 857 | if (!ok) { |
@@ -862,13 +865,13 @@ process_cmdline(void) | |||
862 | goto out; | 865 | goto out; |
863 | } | 866 | } |
864 | if (local || dynamic) { | 867 | if (local || dynamic) { |
865 | if (!channel_setup_local_fwd_listener(&fwd, | 868 | if (!channel_setup_local_fwd_listener(ssh, &fwd, |
866 | &options.fwd_opts)) { | 869 | &options.fwd_opts)) { |
867 | logit("Port forwarding failed."); | 870 | logit("Port forwarding failed."); |
868 | goto out; | 871 | goto out; |
869 | } | 872 | } |
870 | } else { | 873 | } else { |
871 | if (channel_request_remote_forwarding(&fwd) < 0) { | 874 | if (channel_request_remote_forwarding(ssh, &fwd) < 0) { |
872 | logit("Port forwarding failed."); | 875 | logit("Port forwarding failed."); |
873 | goto out; | 876 | goto out; |
874 | } | 877 | } |
@@ -945,7 +948,8 @@ print_escape_help(Buffer *b, int escape_char, int mux_client, int using_stderr) | |||
945 | * Process the characters one by one. | 948 | * Process the characters one by one. |
946 | */ | 949 | */ |
947 | static int | 950 | static int |
948 | process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | 951 | process_escapes(struct ssh *ssh, Channel *c, |
952 | Buffer *bin, Buffer *bout, Buffer *berr, | ||
949 | char *buf, int len) | 953 | char *buf, int len) |
950 | { | 954 | { |
951 | char string[1024]; | 955 | char string[1024]; |
@@ -981,13 +985,15 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
981 | buffer_append(berr, string, strlen(string)); | 985 | buffer_append(berr, string, strlen(string)); |
982 | 986 | ||
983 | if (c && c->ctl_chan != -1) { | 987 | if (c && c->ctl_chan != -1) { |
984 | chan_read_failed(c); | 988 | chan_read_failed(ssh, c); |
985 | chan_write_failed(c); | 989 | chan_write_failed(ssh, c); |
986 | if (c->detach_user) | 990 | if (c->detach_user) { |
987 | c->detach_user(c->self, NULL); | 991 | c->detach_user(ssh, |
992 | c->self, NULL); | ||
993 | } | ||
988 | c->type = SSH_CHANNEL_ABANDONED; | 994 | c->type = SSH_CHANNEL_ABANDONED; |
989 | buffer_clear(&c->input); | 995 | buffer_clear(c->input); |
990 | chan_ibuf_empty(c); | 996 | chan_ibuf_empty(ssh, c); |
991 | return 0; | 997 | return 0; |
992 | } else | 998 | } else |
993 | quit_pending = 1; | 999 | quit_pending = 1; |
@@ -1025,7 +1031,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1025 | snprintf(string, sizeof string, | 1031 | snprintf(string, sizeof string, |
1026 | "%cB\r\n", efc->escape_char); | 1032 | "%cB\r\n", efc->escape_char); |
1027 | buffer_append(berr, string, strlen(string)); | 1033 | buffer_append(berr, string, strlen(string)); |
1028 | channel_request_start(c->self, "break", 0); | 1034 | channel_request_start(ssh, c->self, "break", 0); |
1029 | packet_put_int(1000); | 1035 | packet_put_int(1000); |
1030 | packet_send(); | 1036 | packet_send(); |
1031 | continue; | 1037 | continue; |
@@ -1077,7 +1083,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1077 | options.request_tty == REQUEST_TTY_FORCE); | 1083 | options.request_tty == REQUEST_TTY_FORCE); |
1078 | 1084 | ||
1079 | /* Stop listening for new connections. */ | 1085 | /* Stop listening for new connections. */ |
1080 | channel_stop_listening(); | 1086 | channel_stop_listening(ssh); |
1081 | 1087 | ||
1082 | snprintf(string, sizeof string, | 1088 | snprintf(string, sizeof string, |
1083 | "%c& [backgrounded]\n", efc->escape_char); | 1089 | "%c& [backgrounded]\n", efc->escape_char); |
@@ -1107,7 +1113,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1107 | snprintf(string, sizeof string, "%c#\r\n", | 1113 | snprintf(string, sizeof string, "%c#\r\n", |
1108 | efc->escape_char); | 1114 | efc->escape_char); |
1109 | buffer_append(berr, string, strlen(string)); | 1115 | buffer_append(berr, string, strlen(string)); |
1110 | s = channel_open_message(); | 1116 | s = channel_open_message(ssh); |
1111 | buffer_append(berr, s, strlen(s)); | 1117 | buffer_append(berr, s, strlen(s)); |
1112 | free(s); | 1118 | free(s); |
1113 | continue; | 1119 | continue; |
@@ -1115,7 +1121,7 @@ process_escapes(Channel *c, Buffer *bin, Buffer *bout, Buffer *berr, | |||
1115 | case 'C': | 1121 | case 'C': |
1116 | if (c && c->ctl_chan != -1) | 1122 | if (c && c->ctl_chan != -1) |
1117 | goto noescape; | 1123 | goto noescape; |
1118 | process_cmdline(); | 1124 | process_cmdline(ssh); |
1119 | continue; | 1125 | continue; |
1120 | 1126 | ||
1121 | default: | 1127 | default: |
@@ -1186,25 +1192,25 @@ client_new_escape_filter_ctx(int escape_char) | |||
1186 | 1192 | ||
1187 | /* Free the escape filter context on channel free */ | 1193 | /* Free the escape filter context on channel free */ |
1188 | void | 1194 | void |
1189 | client_filter_cleanup(int cid, void *ctx) | 1195 | client_filter_cleanup(struct ssh *ssh, int cid, void *ctx) |
1190 | { | 1196 | { |
1191 | free(ctx); | 1197 | free(ctx); |
1192 | } | 1198 | } |
1193 | 1199 | ||
1194 | int | 1200 | int |
1195 | client_simple_escape_filter(Channel *c, char *buf, int len) | 1201 | client_simple_escape_filter(struct ssh *ssh, Channel *c, char *buf, int len) |
1196 | { | 1202 | { |
1197 | if (c->extended_usage != CHAN_EXTENDED_WRITE) | 1203 | if (c->extended_usage != CHAN_EXTENDED_WRITE) |
1198 | return 0; | 1204 | return 0; |
1199 | 1205 | ||
1200 | return process_escapes(c, &c->input, &c->output, &c->extended, | 1206 | return process_escapes(ssh, c, c->input, c->output, c->extended, |
1201 | buf, len); | 1207 | buf, len); |
1202 | } | 1208 | } |
1203 | 1209 | ||
1204 | static void | 1210 | static void |
1205 | client_channel_closed(int id, void *arg) | 1211 | client_channel_closed(struct ssh *ssh, int id, void *arg) |
1206 | { | 1212 | { |
1207 | channel_cancel_cleanup(id); | 1213 | channel_cancel_cleanup(ssh, id); |
1208 | session_closed = 1; | 1214 | session_closed = 1; |
1209 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 1215 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
1210 | } | 1216 | } |
@@ -1215,9 +1221,9 @@ client_channel_closed(int id, void *arg) | |||
1215 | * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character | 1221 | * remote host. If escape_char != SSH_ESCAPECHAR_NONE, it is the character |
1216 | * used as an escape character for terminating or suspending the session. | 1222 | * used as an escape character for terminating or suspending the session. |
1217 | */ | 1223 | */ |
1218 | |||
1219 | int | 1224 | int |
1220 | client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | 1225 | client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, |
1226 | int ssh2_chan_id) | ||
1221 | { | 1227 | { |
1222 | fd_set *readset = NULL, *writeset = NULL; | 1228 | fd_set *readset = NULL, *writeset = NULL; |
1223 | double start_time, total_time; | 1229 | double start_time, total_time; |
@@ -1295,13 +1301,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1295 | session_ident = ssh2_chan_id; | 1301 | session_ident = ssh2_chan_id; |
1296 | if (session_ident != -1) { | 1302 | if (session_ident != -1) { |
1297 | if (escape_char_arg != SSH_ESCAPECHAR_NONE) { | 1303 | if (escape_char_arg != SSH_ESCAPECHAR_NONE) { |
1298 | channel_register_filter(session_ident, | 1304 | channel_register_filter(ssh, session_ident, |
1299 | client_simple_escape_filter, NULL, | 1305 | client_simple_escape_filter, NULL, |
1300 | client_filter_cleanup, | 1306 | client_filter_cleanup, |
1301 | client_new_escape_filter_ctx( | 1307 | client_new_escape_filter_ctx( |
1302 | escape_char_arg)); | 1308 | escape_char_arg)); |
1303 | } | 1309 | } |
1304 | channel_register_cleanup(session_ident, | 1310 | channel_register_cleanup(ssh, session_ident, |
1305 | client_channel_closed, 0); | 1311 | client_channel_closed, 0); |
1306 | } | 1312 | } |
1307 | 1313 | ||
@@ -1311,15 +1317,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1311 | /* Process buffered packets sent by the server. */ | 1317 | /* Process buffered packets sent by the server. */ |
1312 | client_process_buffered_input_packets(); | 1318 | client_process_buffered_input_packets(); |
1313 | 1319 | ||
1314 | if (session_closed && !channel_still_open()) | 1320 | if (session_closed && !channel_still_open(ssh)) |
1315 | break; | 1321 | break; |
1316 | 1322 | ||
1317 | if (ssh_packet_is_rekeying(active_state)) { | 1323 | if (ssh_packet_is_rekeying(ssh)) { |
1318 | debug("rekeying in progress"); | 1324 | debug("rekeying in progress"); |
1319 | } else if (need_rekeying) { | 1325 | } else if (need_rekeying) { |
1320 | /* manual rekey request */ | 1326 | /* manual rekey request */ |
1321 | debug("need rekeying"); | 1327 | debug("need rekeying"); |
1322 | if ((r = kex_start_rekex(active_state)) != 0) | 1328 | if ((r = kex_start_rekex(ssh)) != 0) |
1323 | fatal("%s: kex_start_rekex: %s", __func__, | 1329 | fatal("%s: kex_start_rekex: %s", __func__, |
1324 | ssh_err(r)); | 1330 | ssh_err(r)); |
1325 | need_rekeying = 0; | 1331 | need_rekeying = 0; |
@@ -1329,13 +1335,13 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1329 | * enqueue them for sending to the server. | 1335 | * enqueue them for sending to the server. |
1330 | */ | 1336 | */ |
1331 | if (packet_not_very_much_data_to_write()) | 1337 | if (packet_not_very_much_data_to_write()) |
1332 | channel_output_poll(); | 1338 | channel_output_poll(ssh); |
1333 | 1339 | ||
1334 | /* | 1340 | /* |
1335 | * Check if the window size has changed, and buffer a | 1341 | * Check if the window size has changed, and buffer a |
1336 | * message about it to the server if so. | 1342 | * message about it to the server if so. |
1337 | */ | 1343 | */ |
1338 | client_check_window_change(); | 1344 | client_check_window_change(ssh); |
1339 | 1345 | ||
1340 | if (quit_pending) | 1346 | if (quit_pending) |
1341 | break; | 1347 | break; |
@@ -1345,15 +1351,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1345 | * available on one of the descriptors). | 1351 | * available on one of the descriptors). |
1346 | */ | 1352 | */ |
1347 | max_fd2 = max_fd; | 1353 | max_fd2 = max_fd; |
1348 | client_wait_until_can_do_something(&readset, &writeset, | 1354 | client_wait_until_can_do_something(ssh, &readset, &writeset, |
1349 | &max_fd2, &nalloc, ssh_packet_is_rekeying(active_state)); | 1355 | &max_fd2, &nalloc, ssh_packet_is_rekeying(ssh)); |
1350 | 1356 | ||
1351 | if (quit_pending) | 1357 | if (quit_pending) |
1352 | break; | 1358 | break; |
1353 | 1359 | ||
1354 | /* Do channel operations unless rekeying in progress. */ | 1360 | /* Do channel operations unless rekeying in progress. */ |
1355 | if (!ssh_packet_is_rekeying(active_state)) | 1361 | if (!ssh_packet_is_rekeying(ssh)) |
1356 | channel_after_select(active_state, readset, writeset); | 1362 | channel_after_select(ssh, readset, writeset); |
1357 | 1363 | ||
1358 | /* Buffer input from the connection. */ | 1364 | /* Buffer input from the connection. */ |
1359 | client_process_net_input(readset); | 1365 | client_process_net_input(readset); |
@@ -1395,7 +1401,7 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1395 | packet_send(); | 1401 | packet_send(); |
1396 | packet_write_wait(); | 1402 | packet_write_wait(); |
1397 | 1403 | ||
1398 | channel_free_all(); | 1404 | channel_free_all(ssh); |
1399 | 1405 | ||
1400 | if (have_pty) | 1406 | if (have_pty) |
1401 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); | 1407 | leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); |
@@ -1463,8 +1469,8 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) | |||
1463 | /*********/ | 1469 | /*********/ |
1464 | 1470 | ||
1465 | static Channel * | 1471 | static Channel * |
1466 | client_request_forwarded_tcpip(const char *request_type, int rchan, | 1472 | client_request_forwarded_tcpip(struct ssh *ssh, const char *request_type, |
1467 | u_int rwindow, u_int rmaxpack) | 1473 | int rchan, u_int rwindow, u_int rmaxpack) |
1468 | { | 1474 | { |
1469 | Channel *c = NULL; | 1475 | Channel *c = NULL; |
1470 | struct sshbuf *b = NULL; | 1476 | struct sshbuf *b = NULL; |
@@ -1482,7 +1488,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, | |||
1482 | debug("%s: listen %s port %d, originator %s port %d", __func__, | 1488 | debug("%s: listen %s port %d, originator %s port %d", __func__, |
1483 | listen_address, listen_port, originator_address, originator_port); | 1489 | listen_address, listen_port, originator_address, originator_port); |
1484 | 1490 | ||
1485 | c = channel_connect_by_listen_address(listen_address, listen_port, | 1491 | c = channel_connect_by_listen_address(ssh, listen_address, listen_port, |
1486 | "forwarded-tcpip", originator_address); | 1492 | "forwarded-tcpip", originator_address); |
1487 | 1493 | ||
1488 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { | 1494 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
@@ -1501,7 +1507,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, | |||
1501 | (r = sshbuf_put_u32(b, listen_port)) != 0 || | 1507 | (r = sshbuf_put_u32(b, listen_port)) != 0 || |
1502 | (r = sshbuf_put_cstring(b, originator_address)) != 0 || | 1508 | (r = sshbuf_put_cstring(b, originator_address)) != 0 || |
1503 | (r = sshbuf_put_u32(b, originator_port)) != 0 || | 1509 | (r = sshbuf_put_u32(b, originator_port)) != 0 || |
1504 | (r = sshbuf_put_stringb(&c->output, b)) != 0) { | 1510 | (r = sshbuf_put_stringb(c->output, b)) != 0) { |
1505 | error("%s: compose for muxclient %s", __func__, | 1511 | error("%s: compose for muxclient %s", __func__, |
1506 | ssh_err(r)); | 1512 | ssh_err(r)); |
1507 | goto out; | 1513 | goto out; |
@@ -1516,7 +1522,8 @@ client_request_forwarded_tcpip(const char *request_type, int rchan, | |||
1516 | } | 1522 | } |
1517 | 1523 | ||
1518 | static Channel * | 1524 | static Channel * |
1519 | client_request_forwarded_streamlocal(const char *request_type, int rchan) | 1525 | client_request_forwarded_streamlocal(struct ssh *ssh, |
1526 | const char *request_type, int rchan) | ||
1520 | { | 1527 | { |
1521 | Channel *c = NULL; | 1528 | Channel *c = NULL; |
1522 | char *listen_path; | 1529 | char *listen_path; |
@@ -1530,14 +1537,14 @@ client_request_forwarded_streamlocal(const char *request_type, int rchan) | |||
1530 | 1537 | ||
1531 | debug("%s: %s", __func__, listen_path); | 1538 | debug("%s: %s", __func__, listen_path); |
1532 | 1539 | ||
1533 | c = channel_connect_by_listen_path(listen_path, | 1540 | c = channel_connect_by_listen_path(ssh, listen_path, |
1534 | "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); | 1541 | "forwarded-streamlocal@openssh.com", "forwarded-streamlocal"); |
1535 | free(listen_path); | 1542 | free(listen_path); |
1536 | return c; | 1543 | return c; |
1537 | } | 1544 | } |
1538 | 1545 | ||
1539 | static Channel * | 1546 | static Channel * |
1540 | client_request_x11(const char *request_type, int rchan) | 1547 | client_request_x11(struct ssh *ssh, const char *request_type, int rchan) |
1541 | { | 1548 | { |
1542 | Channel *c = NULL; | 1549 | Channel *c = NULL; |
1543 | char *originator; | 1550 | char *originator; |
@@ -1567,10 +1574,10 @@ client_request_x11(const char *request_type, int rchan) | |||
1567 | debug("client_request_x11: request from %s %d", originator, | 1574 | debug("client_request_x11: request from %s %d", originator, |
1568 | originator_port); | 1575 | originator_port); |
1569 | free(originator); | 1576 | free(originator); |
1570 | sock = x11_connect_display(); | 1577 | sock = x11_connect_display(ssh); |
1571 | if (sock < 0) | 1578 | if (sock < 0) |
1572 | return NULL; | 1579 | return NULL; |
1573 | c = channel_new("x11", | 1580 | c = channel_new(ssh, "x11", |
1574 | SSH_CHANNEL_X11_OPEN, sock, sock, -1, | 1581 | SSH_CHANNEL_X11_OPEN, sock, sock, -1, |
1575 | CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); | 1582 | CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, "x11", 1); |
1576 | c->force_drain = 1; | 1583 | c->force_drain = 1; |
@@ -1578,7 +1585,7 @@ client_request_x11(const char *request_type, int rchan) | |||
1578 | } | 1585 | } |
1579 | 1586 | ||
1580 | static Channel * | 1587 | static Channel * |
1581 | client_request_agent(const char *request_type, int rchan) | 1588 | client_request_agent(struct ssh *ssh, const char *request_type, int rchan) |
1582 | { | 1589 | { |
1583 | Channel *c = NULL; | 1590 | Channel *c = NULL; |
1584 | int r, sock; | 1591 | int r, sock; |
@@ -1595,7 +1602,7 @@ client_request_agent(const char *request_type, int rchan) | |||
1595 | __func__, ssh_err(r)); | 1602 | __func__, ssh_err(r)); |
1596 | return NULL; | 1603 | return NULL; |
1597 | } | 1604 | } |
1598 | c = channel_new("authentication agent connection", | 1605 | c = channel_new(ssh, "authentication agent connection", |
1599 | SSH_CHANNEL_OPEN, sock, sock, -1, | 1606 | SSH_CHANNEL_OPEN, sock, sock, -1, |
1600 | CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, | 1607 | CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, |
1601 | "authentication agent connection", 1); | 1608 | "authentication agent connection", 1); |
@@ -1604,7 +1611,8 @@ client_request_agent(const char *request_type, int rchan) | |||
1604 | } | 1611 | } |
1605 | 1612 | ||
1606 | int | 1613 | int |
1607 | client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) | 1614 | client_request_tun_fwd(struct ssh *ssh, int tun_mode, |
1615 | int local_tun, int remote_tun) | ||
1608 | { | 1616 | { |
1609 | Channel *c; | 1617 | Channel *c; |
1610 | int fd; | 1618 | int fd; |
@@ -1620,7 +1628,7 @@ client_request_tun_fwd(int tun_mode, int local_tun, int remote_tun) | |||
1620 | return -1; | 1628 | return -1; |
1621 | } | 1629 | } |
1622 | 1630 | ||
1623 | c = channel_new("tun", SSH_CHANNEL_OPENING, fd, fd, -1, | 1631 | c = channel_new(ssh, "tun", SSH_CHANNEL_OPENING, fd, fd, -1, |
1624 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); | 1632 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
1625 | c->datagram = 1; | 1633 | c->datagram = 1; |
1626 | 1634 | ||
@@ -1660,14 +1668,14 @@ client_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) | |||
1660 | ctype, rchan, rwindow, rmaxpack); | 1668 | ctype, rchan, rwindow, rmaxpack); |
1661 | 1669 | ||
1662 | if (strcmp(ctype, "forwarded-tcpip") == 0) { | 1670 | if (strcmp(ctype, "forwarded-tcpip") == 0) { |
1663 | c = client_request_forwarded_tcpip(ctype, rchan, rwindow, | 1671 | c = client_request_forwarded_tcpip(ssh, ctype, rchan, rwindow, |
1664 | rmaxpack); | 1672 | rmaxpack); |
1665 | } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { | 1673 | } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) { |
1666 | c = client_request_forwarded_streamlocal(ctype, rchan); | 1674 | c = client_request_forwarded_streamlocal(ssh, ctype, rchan); |
1667 | } else if (strcmp(ctype, "x11") == 0) { | 1675 | } else if (strcmp(ctype, "x11") == 0) { |
1668 | c = client_request_x11(ctype, rchan); | 1676 | c = client_request_x11(ssh, ctype, rchan); |
1669 | } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { | 1677 | } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { |
1670 | c = client_request_agent(ctype, rchan); | 1678 | c = client_request_agent(ssh, ctype, rchan); |
1671 | } | 1679 | } |
1672 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { | 1680 | if (c != NULL && c->type == SSH_CHANNEL_MUX_CLIENT) { |
1673 | debug3("proxied to downstream: %s", ctype); | 1681 | debug3("proxied to downstream: %s", ctype); |
@@ -1707,7 +1715,7 @@ client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) | |||
1707 | char *rtype; | 1715 | char *rtype; |
1708 | 1716 | ||
1709 | id = packet_get_int(); | 1717 | id = packet_get_int(); |
1710 | c = channel_lookup(id); | 1718 | c = channel_lookup(ssh, id); |
1711 | if (channel_proxy_upstream(c, type, seq, ssh)) | 1719 | if (channel_proxy_upstream(c, type, seq, ssh)) |
1712 | return 0; | 1720 | return 0; |
1713 | rtype = packet_get_string(NULL); | 1721 | rtype = packet_get_string(NULL); |
@@ -1723,11 +1731,11 @@ client_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) | |||
1723 | "unknown channel", id); | 1731 | "unknown channel", id); |
1724 | } else if (strcmp(rtype, "eow@openssh.com") == 0) { | 1732 | } else if (strcmp(rtype, "eow@openssh.com") == 0) { |
1725 | packet_check_eom(); | 1733 | packet_check_eom(); |
1726 | chan_rcvd_eow(c); | 1734 | chan_rcvd_eow(ssh, c); |
1727 | } else if (strcmp(rtype, "exit-status") == 0) { | 1735 | } else if (strcmp(rtype, "exit-status") == 0) { |
1728 | exitval = packet_get_int(); | 1736 | exitval = packet_get_int(); |
1729 | if (c->ctl_chan != -1) { | 1737 | if (c->ctl_chan != -1) { |
1730 | mux_exit_message(c, exitval); | 1738 | mux_exit_message(ssh, c, exitval); |
1731 | success = 1; | 1739 | success = 1; |
1732 | } else if (id == session_ident) { | 1740 | } else if (id == session_ident) { |
1733 | /* Record exit value of local session */ | 1741 | /* Record exit value of local session */ |
@@ -1895,9 +1903,9 @@ update_known_hosts(struct hostkeys_update_ctx *ctx) | |||
1895 | } | 1903 | } |
1896 | 1904 | ||
1897 | static void | 1905 | static void |
1898 | client_global_hostkeys_private_confirm(int type, u_int32_t seq, void *_ctx) | 1906 | client_global_hostkeys_private_confirm(struct ssh *ssh, int type, |
1907 | u_int32_t seq, void *_ctx) | ||
1899 | { | 1908 | { |
1900 | struct ssh *ssh = active_state; /* XXX */ | ||
1901 | struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; | 1909 | struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; |
1902 | size_t i, ndone; | 1910 | size_t i, ndone; |
1903 | struct sshbuf *signdata; | 1911 | struct sshbuf *signdata; |
@@ -2161,7 +2169,7 @@ client_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | |||
2161 | } | 2169 | } |
2162 | 2170 | ||
2163 | void | 2171 | void |
2164 | client_session2_setup(int id, int want_tty, int want_subsystem, | 2172 | client_session2_setup(struct ssh *ssh, int id, int want_tty, int want_subsystem, |
2165 | const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) | 2173 | const char *term, struct termios *tiop, int in_fd, Buffer *cmd, char **env) |
2166 | { | 2174 | { |
2167 | int len; | 2175 | int len; |
@@ -2169,8 +2177,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2169 | 2177 | ||
2170 | debug2("%s: id %d", __func__, id); | 2178 | debug2("%s: id %d", __func__, id); |
2171 | 2179 | ||
2172 | if ((c = channel_lookup(id)) == NULL) | 2180 | if ((c = channel_lookup(ssh, id)) == NULL) |
2173 | fatal("client_session2_setup: channel %d: unknown channel", id); | 2181 | fatal("%s: channel %d: unknown channel", __func__, id); |
2174 | 2182 | ||
2175 | packet_set_interactive(want_tty, | 2183 | packet_set_interactive(want_tty, |
2176 | options.ip_qos_interactive, options.ip_qos_bulk); | 2184 | options.ip_qos_interactive, options.ip_qos_bulk); |
@@ -2182,8 +2190,8 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2182 | if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) | 2190 | if (ioctl(in_fd, TIOCGWINSZ, &ws) < 0) |
2183 | memset(&ws, 0, sizeof(ws)); | 2191 | memset(&ws, 0, sizeof(ws)); |
2184 | 2192 | ||
2185 | channel_request_start(id, "pty-req", 1); | 2193 | channel_request_start(ssh, id, "pty-req", 1); |
2186 | client_expect_confirm(id, "PTY allocation", CONFIRM_TTY); | 2194 | client_expect_confirm(ssh, id, "PTY allocation", CONFIRM_TTY); |
2187 | packet_put_cstring(term != NULL ? term : ""); | 2195 | packet_put_cstring(term != NULL ? term : ""); |
2188 | packet_put_int((u_int)ws.ws_col); | 2196 | packet_put_int((u_int)ws.ws_col); |
2189 | packet_put_int((u_int)ws.ws_row); | 2197 | packet_put_int((u_int)ws.ws_row); |
@@ -2226,7 +2234,7 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2226 | } | 2234 | } |
2227 | 2235 | ||
2228 | debug("Sending env %s = %s", name, val); | 2236 | debug("Sending env %s = %s", name, val); |
2229 | channel_request_start(id, "env", 0); | 2237 | channel_request_start(ssh, id, "env", 0); |
2230 | packet_put_cstring(name); | 2238 | packet_put_cstring(name); |
2231 | packet_put_cstring(val); | 2239 | packet_put_cstring(val); |
2232 | packet_send(); | 2240 | packet_send(); |
@@ -2241,19 +2249,20 @@ client_session2_setup(int id, int want_tty, int want_subsystem, | |||
2241 | if (want_subsystem) { | 2249 | if (want_subsystem) { |
2242 | debug("Sending subsystem: %.*s", | 2250 | debug("Sending subsystem: %.*s", |
2243 | len, (u_char*)buffer_ptr(cmd)); | 2251 | len, (u_char*)buffer_ptr(cmd)); |
2244 | channel_request_start(id, "subsystem", 1); | 2252 | channel_request_start(ssh, id, "subsystem", 1); |
2245 | client_expect_confirm(id, "subsystem", CONFIRM_CLOSE); | 2253 | client_expect_confirm(ssh, id, "subsystem", |
2254 | CONFIRM_CLOSE); | ||
2246 | } else { | 2255 | } else { |
2247 | debug("Sending command: %.*s", | 2256 | debug("Sending command: %.*s", |
2248 | len, (u_char*)buffer_ptr(cmd)); | 2257 | len, (u_char*)buffer_ptr(cmd)); |
2249 | channel_request_start(id, "exec", 1); | 2258 | channel_request_start(ssh, id, "exec", 1); |
2250 | client_expect_confirm(id, "exec", CONFIRM_CLOSE); | 2259 | client_expect_confirm(ssh, id, "exec", CONFIRM_CLOSE); |
2251 | } | 2260 | } |
2252 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); | 2261 | packet_put_string(buffer_ptr(cmd), buffer_len(cmd)); |
2253 | packet_send(); | 2262 | packet_send(); |
2254 | } else { | 2263 | } else { |
2255 | channel_request_start(id, "shell", 1); | 2264 | channel_request_start(ssh, id, "shell", 1); |
2256 | client_expect_confirm(id, "shell", CONFIRM_CLOSE); | 2265 | client_expect_confirm(ssh, id, "shell", CONFIRM_CLOSE); |
2257 | packet_send(); | 2266 | packet_send(); |
2258 | } | 2267 | } |
2259 | } | 2268 | } |
diff --git a/clientloop.h b/clientloop.h index ae83aa8cf..a1975ccc8 100644 --- a/clientloop.h +++ b/clientloop.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: clientloop.h,v 1.33 2016/09/30 09:19:13 markus Exp $ */ | 1 | /* $OpenBSD: clientloop.h,v 1.34 2017/09/12 06:32:07 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -37,28 +37,31 @@ | |||
37 | 37 | ||
38 | #include <termios.h> | 38 | #include <termios.h> |
39 | 39 | ||
40 | struct ssh; | ||
41 | |||
40 | /* Client side main loop for the interactive session. */ | 42 | /* Client side main loop for the interactive session. */ |
41 | int client_loop(int, int, int); | 43 | int client_loop(struct ssh *, int, int, int); |
42 | int client_x11_get_proto(const char *, const char *, u_int, u_int, | 44 | int client_x11_get_proto(struct ssh *, const char *, const char *, |
43 | char **, char **); | 45 | u_int, u_int, char **, char **); |
44 | void client_global_request_reply_fwd(int, u_int32_t, void *); | 46 | void client_global_request_reply_fwd(int, u_int32_t, void *); |
45 | void client_session2_setup(int, int, int, const char *, struct termios *, | 47 | void client_session2_setup(struct ssh *, int, int, int, |
46 | int, Buffer *, char **); | 48 | const char *, struct termios *, int, Buffer *, char **); |
47 | int client_request_tun_fwd(int, int, int); | 49 | int client_request_tun_fwd(struct ssh *, int, int, int); |
48 | void client_stop_mux(void); | 50 | void client_stop_mux(void); |
49 | 51 | ||
50 | /* Escape filter for protocol 2 sessions */ | 52 | /* Escape filter for protocol 2 sessions */ |
51 | void *client_new_escape_filter_ctx(int); | 53 | void *client_new_escape_filter_ctx(int); |
52 | void client_filter_cleanup(int, void *); | 54 | void client_filter_cleanup(struct ssh *, int, void *); |
53 | int client_simple_escape_filter(Channel *, char *, int); | 55 | int client_simple_escape_filter(struct ssh *, Channel *, char *, int); |
54 | 56 | ||
55 | /* Global request confirmation callbacks */ | 57 | /* Global request confirmation callbacks */ |
56 | typedef void global_confirm_cb(int, u_int32_t seq, void *); | 58 | typedef void global_confirm_cb(struct ssh *, int, u_int32_t, void *); |
57 | void client_register_global_confirm(global_confirm_cb *, void *); | 59 | void client_register_global_confirm(global_confirm_cb *, void *); |
58 | 60 | ||
59 | /* Channel request confirmation callbacks */ | 61 | /* Channel request confirmation callbacks */ |
60 | enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY }; | 62 | enum confirm_action { CONFIRM_WARN = 0, CONFIRM_CLOSE, CONFIRM_TTY }; |
61 | void client_expect_confirm(int, const char *, enum confirm_action); | 63 | void client_expect_confirm(struct ssh *, int, const char *, |
64 | enum confirm_action); | ||
62 | 65 | ||
63 | /* Multiplexing protocol version */ | 66 | /* Multiplexing protocol version */ |
64 | #define SSHMUX_VER 4 | 67 | #define SSHMUX_VER 4 |
@@ -73,8 +76,8 @@ void client_expect_confirm(int, const char *, enum confirm_action); | |||
73 | #define SSHMUX_COMMAND_CANCEL_FWD 7 /* Cancel forwarding(s) */ | 76 | #define SSHMUX_COMMAND_CANCEL_FWD 7 /* Cancel forwarding(s) */ |
74 | #define SSHMUX_COMMAND_PROXY 8 /* Open new connection */ | 77 | #define SSHMUX_COMMAND_PROXY 8 /* Open new connection */ |
75 | 78 | ||
76 | void muxserver_listen(void); | 79 | void muxserver_listen(struct ssh *); |
77 | int muxclient(const char *); | 80 | int muxclient(const char *); |
78 | void mux_exit_message(Channel *, int); | 81 | void mux_exit_message(struct ssh *, Channel *, int); |
79 | void mux_tty_alloc_failed(Channel *); | 82 | void mux_tty_alloc_failed(struct ssh *ssh, Channel *); |
80 | 83 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.172 2017/06/24 06:34:38 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.173 2017/09/12 06:32:07 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -1519,13 +1519,14 @@ mm_answer_pty_cleanup(int sock, Buffer *m) | |||
1519 | int | 1519 | int |
1520 | mm_answer_term(int sock, Buffer *req) | 1520 | mm_answer_term(int sock, Buffer *req) |
1521 | { | 1521 | { |
1522 | struct ssh *ssh = active_state; /* XXX */ | ||
1522 | extern struct monitor *pmonitor; | 1523 | extern struct monitor *pmonitor; |
1523 | int res, status; | 1524 | int res, status; |
1524 | 1525 | ||
1525 | debug3("%s: tearing down sessions", __func__); | 1526 | debug3("%s: tearing down sessions", __func__); |
1526 | 1527 | ||
1527 | /* The child is terminating */ | 1528 | /* The child is terminating */ |
1528 | session_destroy_all(&mm_session_close); | 1529 | session_destroy_all(ssh, &mm_session_close); |
1529 | 1530 | ||
1530 | #ifdef USE_PAM | 1531 | #ifdef USE_PAM |
1531 | if (options.use_pam) | 1532 | if (options.use_pam) |
diff --git a/monitor_wrap.c b/monitor_wrap.c index 25f3e9678..287af0667 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor_wrap.c,v 1.92 2017/05/30 14:10:53 markus Exp $ */ | 1 | /* $OpenBSD: monitor_wrap.c,v 1.93 2017/09/12 06:32:07 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -242,6 +242,7 @@ mm_key_sign(struct sshkey *key, u_char **sigp, u_int *lenp, | |||
242 | struct passwd * | 242 | struct passwd * |
243 | mm_getpwnamallow(const char *username) | 243 | mm_getpwnamallow(const char *username) |
244 | { | 244 | { |
245 | struct ssh *ssh = active_state; /* XXX */ | ||
245 | Buffer m; | 246 | Buffer m; |
246 | struct passwd *pw; | 247 | struct passwd *pw; |
247 | u_int len, i; | 248 | u_int len, i; |
@@ -296,6 +297,7 @@ out: | |||
296 | 297 | ||
297 | copy_set_server_options(&options, newopts, 1); | 298 | copy_set_server_options(&options, newopts, 1); |
298 | log_change_level(options.log_level); | 299 | log_change_level(options.log_level); |
300 | process_permitopen(ssh, &options); | ||
299 | free(newopts); | 301 | free(newopts); |
300 | 302 | ||
301 | buffer_free(&m); | 303 | buffer_free(&m); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: mux.c,v 1.65 2017/06/09 06:47:13 djm Exp $ */ | 1 | /* $OpenBSD: mux.c,v 1.66 2017/09/12 06:32:07 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> | 3 | * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> |
4 | * | 4 | * |
@@ -161,22 +161,32 @@ struct mux_master_state { | |||
161 | #define MUX_FWD_REMOTE 2 | 161 | #define MUX_FWD_REMOTE 2 |
162 | #define MUX_FWD_DYNAMIC 3 | 162 | #define MUX_FWD_DYNAMIC 3 |
163 | 163 | ||
164 | static void mux_session_confirm(int, int, void *); | 164 | static void mux_session_confirm(struct ssh *, int, int, void *); |
165 | static void mux_stdio_confirm(int, int, void *); | 165 | static void mux_stdio_confirm(struct ssh *, int, int, void *); |
166 | 166 | ||
167 | static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); | 167 | static int process_mux_master_hello(struct ssh *, u_int, |
168 | static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); | 168 | Channel *, struct sshbuf *, struct sshbuf *); |
169 | static int process_mux_alive_check(u_int, Channel *, Buffer *, Buffer *); | 169 | static int process_mux_new_session(struct ssh *, u_int, |
170 | static int process_mux_terminate(u_int, Channel *, Buffer *, Buffer *); | 170 | Channel *, struct sshbuf *, struct sshbuf *); |
171 | static int process_mux_open_fwd(u_int, Channel *, Buffer *, Buffer *); | 171 | static int process_mux_alive_check(struct ssh *, u_int, |
172 | static int process_mux_close_fwd(u_int, Channel *, Buffer *, Buffer *); | 172 | Channel *, struct sshbuf *, struct sshbuf *); |
173 | static int process_mux_stdio_fwd(u_int, Channel *, Buffer *, Buffer *); | 173 | static int process_mux_terminate(struct ssh *, u_int, |
174 | static int process_mux_stop_listening(u_int, Channel *, Buffer *, Buffer *); | 174 | Channel *, struct sshbuf *, struct sshbuf *); |
175 | static int process_mux_proxy(u_int, Channel *, Buffer *, Buffer *); | 175 | static int process_mux_open_fwd(struct ssh *, u_int, |
176 | Channel *, struct sshbuf *, struct sshbuf *); | ||
177 | static int process_mux_close_fwd(struct ssh *, u_int, | ||
178 | Channel *, struct sshbuf *, struct sshbuf *); | ||
179 | static int process_mux_stdio_fwd(struct ssh *, u_int, | ||
180 | Channel *, struct sshbuf *, struct sshbuf *); | ||
181 | static int process_mux_stop_listening(struct ssh *, u_int, | ||
182 | Channel *, struct sshbuf *, struct sshbuf *); | ||
183 | static int process_mux_proxy(struct ssh *, u_int, | ||
184 | Channel *, struct sshbuf *, struct sshbuf *); | ||
176 | 185 | ||
177 | static const struct { | 186 | static const struct { |
178 | u_int type; | 187 | u_int type; |
179 | int (*handler)(u_int, Channel *, Buffer *, Buffer *); | 188 | int (*handler)(struct ssh *, u_int, Channel *, |
189 | struct sshbuf *, struct sshbuf *); | ||
180 | } mux_master_handlers[] = { | 190 | } mux_master_handlers[] = { |
181 | { MUX_MSG_HELLO, process_mux_master_hello }, | 191 | { MUX_MSG_HELLO, process_mux_master_hello }, |
182 | { MUX_C_NEW_SESSION, process_mux_new_session }, | 192 | { MUX_C_NEW_SESSION, process_mux_new_session }, |
@@ -193,36 +203,36 @@ static const struct { | |||
193 | /* Cleanup callback fired on closure of mux slave _session_ channel */ | 203 | /* Cleanup callback fired on closure of mux slave _session_ channel */ |
194 | /* ARGSUSED */ | 204 | /* ARGSUSED */ |
195 | static void | 205 | static void |
196 | mux_master_session_cleanup_cb(int cid, void *unused) | 206 | mux_master_session_cleanup_cb(struct ssh *ssh, int cid, void *unused) |
197 | { | 207 | { |
198 | Channel *cc, *c = channel_by_id(cid); | 208 | Channel *cc, *c = channel_by_id(ssh, cid); |
199 | 209 | ||
200 | debug3("%s: entering for channel %d", __func__, cid); | 210 | debug3("%s: entering for channel %d", __func__, cid); |
201 | if (c == NULL) | 211 | if (c == NULL) |
202 | fatal("%s: channel_by_id(%i) == NULL", __func__, cid); | 212 | fatal("%s: channel_by_id(%i) == NULL", __func__, cid); |
203 | if (c->ctl_chan != -1) { | 213 | if (c->ctl_chan != -1) { |
204 | if ((cc = channel_by_id(c->ctl_chan)) == NULL) | 214 | if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) |
205 | fatal("%s: channel %d missing control channel %d", | 215 | fatal("%s: channel %d missing control channel %d", |
206 | __func__, c->self, c->ctl_chan); | 216 | __func__, c->self, c->ctl_chan); |
207 | c->ctl_chan = -1; | 217 | c->ctl_chan = -1; |
208 | cc->remote_id = -1; | 218 | cc->remote_id = -1; |
209 | chan_rcvd_oclose(cc); | 219 | chan_rcvd_oclose(ssh, cc); |
210 | } | 220 | } |
211 | channel_cancel_cleanup(c->self); | 221 | channel_cancel_cleanup(ssh, c->self); |
212 | } | 222 | } |
213 | 223 | ||
214 | /* Cleanup callback fired on closure of mux slave _control_ channel */ | 224 | /* Cleanup callback fired on closure of mux slave _control_ channel */ |
215 | /* ARGSUSED */ | 225 | /* ARGSUSED */ |
216 | static void | 226 | static void |
217 | mux_master_control_cleanup_cb(int cid, void *unused) | 227 | mux_master_control_cleanup_cb(struct ssh *ssh, int cid, void *unused) |
218 | { | 228 | { |
219 | Channel *sc, *c = channel_by_id(cid); | 229 | Channel *sc, *c = channel_by_id(ssh, cid); |
220 | 230 | ||
221 | debug3("%s: entering for channel %d", __func__, cid); | 231 | debug3("%s: entering for channel %d", __func__, cid); |
222 | if (c == NULL) | 232 | if (c == NULL) |
223 | fatal("%s: channel_by_id(%i) == NULL", __func__, cid); | 233 | fatal("%s: channel_by_id(%i) == NULL", __func__, cid); |
224 | if (c->remote_id != -1) { | 234 | if (c->remote_id != -1) { |
225 | if ((sc = channel_by_id(c->remote_id)) == NULL) | 235 | if ((sc = channel_by_id(ssh, c->remote_id)) == NULL) |
226 | fatal("%s: channel %d missing session channel %d", | 236 | fatal("%s: channel %d missing session channel %d", |
227 | __func__, c->self, c->remote_id); | 237 | __func__, c->self, c->remote_id); |
228 | c->remote_id = -1; | 238 | c->remote_id = -1; |
@@ -230,15 +240,15 @@ mux_master_control_cleanup_cb(int cid, void *unused) | |||
230 | if (sc->type != SSH_CHANNEL_OPEN && | 240 | if (sc->type != SSH_CHANNEL_OPEN && |
231 | sc->type != SSH_CHANNEL_OPENING) { | 241 | sc->type != SSH_CHANNEL_OPENING) { |
232 | debug2("%s: channel %d: not open", __func__, sc->self); | 242 | debug2("%s: channel %d: not open", __func__, sc->self); |
233 | chan_mark_dead(sc); | 243 | chan_mark_dead(ssh, sc); |
234 | } else { | 244 | } else { |
235 | if (sc->istate == CHAN_INPUT_OPEN) | 245 | if (sc->istate == CHAN_INPUT_OPEN) |
236 | chan_read_failed(sc); | 246 | chan_read_failed(ssh, sc); |
237 | if (sc->ostate == CHAN_OUTPUT_OPEN) | 247 | if (sc->ostate == CHAN_OUTPUT_OPEN) |
238 | chan_write_failed(sc); | 248 | chan_write_failed(ssh, sc); |
239 | } | 249 | } |
240 | } | 250 | } |
241 | channel_cancel_cleanup(c->self); | 251 | channel_cancel_cleanup(ssh, c->self); |
242 | } | 252 | } |
243 | 253 | ||
244 | /* Check mux client environment variables before passing them to mux master. */ | 254 | /* Check mux client environment variables before passing them to mux master. */ |
@@ -266,7 +276,8 @@ env_permitted(char *env) | |||
266 | /* Mux master protocol message handlers */ | 276 | /* Mux master protocol message handlers */ |
267 | 277 | ||
268 | static int | 278 | static int |
269 | process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r) | 279 | process_mux_master_hello(struct ssh *ssh, u_int rid, |
280 | Channel *c, Buffer *m, Buffer *r) | ||
270 | { | 281 | { |
271 | u_int ver; | 282 | u_int ver; |
272 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; | 283 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; |
@@ -308,7 +319,8 @@ process_mux_master_hello(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
308 | } | 319 | } |
309 | 320 | ||
310 | static int | 321 | static int |
311 | process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) | 322 | process_mux_new_session(struct ssh *ssh, u_int rid, |
323 | Channel *c, Buffer *m, Buffer *r) | ||
312 | { | 324 | { |
313 | Channel *nc; | 325 | Channel *nc; |
314 | struct mux_session_confirm_ctx *cctx; | 326 | struct mux_session_confirm_ctx *cctx; |
@@ -453,7 +465,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
453 | packetmax >>= 1; | 465 | packetmax >>= 1; |
454 | } | 466 | } |
455 | 467 | ||
456 | nc = channel_new("session", SSH_CHANNEL_OPENING, | 468 | nc = channel_new(ssh, "session", SSH_CHANNEL_OPENING, |
457 | new_fd[0], new_fd[1], new_fd[2], window, packetmax, | 469 | new_fd[0], new_fd[1], new_fd[2], window, packetmax, |
458 | CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); | 470 | CHAN_EXTENDED_WRITE, "client-session", /*nonblock*/0); |
459 | 471 | ||
@@ -461,7 +473,7 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
461 | c->remote_id = nc->self; /* link control -> session channel */ | 473 | c->remote_id = nc->self; /* link control -> session channel */ |
462 | 474 | ||
463 | if (cctx->want_tty && escape_char != 0xffffffff) { | 475 | if (cctx->want_tty && escape_char != 0xffffffff) { |
464 | channel_register_filter(nc->self, | 476 | channel_register_filter(ssh, nc->self, |
465 | client_simple_escape_filter, NULL, | 477 | client_simple_escape_filter, NULL, |
466 | client_filter_cleanup, | 478 | client_filter_cleanup, |
467 | client_new_escape_filter_ctx((int)escape_char)); | 479 | client_new_escape_filter_ctx((int)escape_char)); |
@@ -470,17 +482,19 @@ process_mux_new_session(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
470 | debug2("%s: channel_new: %d linked to control channel %d", | 482 | debug2("%s: channel_new: %d linked to control channel %d", |
471 | __func__, nc->self, nc->ctl_chan); | 483 | __func__, nc->self, nc->ctl_chan); |
472 | 484 | ||
473 | channel_send_open(nc->self); | 485 | channel_send_open(ssh, nc->self); |
474 | channel_register_open_confirm(nc->self, mux_session_confirm, cctx); | 486 | channel_register_open_confirm(ssh, nc->self, mux_session_confirm, cctx); |
475 | c->mux_pause = 1; /* stop handling messages until open_confirm done */ | 487 | c->mux_pause = 1; /* stop handling messages until open_confirm done */ |
476 | channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); | 488 | channel_register_cleanup(ssh, nc->self, |
489 | mux_master_session_cleanup_cb, 1); | ||
477 | 490 | ||
478 | /* reply is deferred, sent by mux_session_confirm */ | 491 | /* reply is deferred, sent by mux_session_confirm */ |
479 | return 0; | 492 | return 0; |
480 | } | 493 | } |
481 | 494 | ||
482 | static int | 495 | static int |
483 | process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r) | 496 | process_mux_alive_check(struct ssh *ssh, u_int rid, |
497 | Channel *c, Buffer *m, Buffer *r) | ||
484 | { | 498 | { |
485 | debug2("%s: channel %d: alive check", __func__, c->self); | 499 | debug2("%s: channel %d: alive check", __func__, c->self); |
486 | 500 | ||
@@ -493,7 +507,8 @@ process_mux_alive_check(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
493 | } | 507 | } |
494 | 508 | ||
495 | static int | 509 | static int |
496 | process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r) | 510 | process_mux_terminate(struct ssh *ssh, u_int rid, |
511 | Channel *c, Buffer *m, Buffer *r) | ||
497 | { | 512 | { |
498 | debug2("%s: channel %d: terminate request", __func__, c->self); | 513 | debug2("%s: channel %d: terminate request", __func__, c->self); |
499 | 514 | ||
@@ -582,7 +597,7 @@ compare_forward(struct Forward *a, struct Forward *b) | |||
582 | } | 597 | } |
583 | 598 | ||
584 | static void | 599 | static void |
585 | mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | 600 | mux_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) |
586 | { | 601 | { |
587 | struct mux_channel_confirm_ctx *fctx = ctxt; | 602 | struct mux_channel_confirm_ctx *fctx = ctxt; |
588 | char *failmsg = NULL; | 603 | char *failmsg = NULL; |
@@ -590,7 +605,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
590 | Channel *c; | 605 | Channel *c; |
591 | Buffer out; | 606 | Buffer out; |
592 | 607 | ||
593 | if ((c = channel_by_id(fctx->cid)) == NULL) { | 608 | if ((c = channel_by_id(ssh, fctx->cid)) == NULL) { |
594 | /* no channel for reply */ | 609 | /* no channel for reply */ |
595 | error("%s: unknown channel", __func__); | 610 | error("%s: unknown channel", __func__); |
596 | return; | 611 | return; |
@@ -616,7 +631,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
616 | buffer_put_int(&out, MUX_S_REMOTE_PORT); | 631 | buffer_put_int(&out, MUX_S_REMOTE_PORT); |
617 | buffer_put_int(&out, fctx->rid); | 632 | buffer_put_int(&out, fctx->rid); |
618 | buffer_put_int(&out, rfwd->allocated_port); | 633 | buffer_put_int(&out, rfwd->allocated_port); |
619 | channel_update_permitted_opens(rfwd->handle, | 634 | channel_update_permitted_opens(ssh, rfwd->handle, |
620 | rfwd->allocated_port); | 635 | rfwd->allocated_port); |
621 | } else { | 636 | } else { |
622 | buffer_put_int(&out, MUX_S_OK); | 637 | buffer_put_int(&out, MUX_S_OK); |
@@ -625,7 +640,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
625 | goto out; | 640 | goto out; |
626 | } else { | 641 | } else { |
627 | if (rfwd->listen_port == 0) | 642 | if (rfwd->listen_port == 0) |
628 | channel_update_permitted_opens(rfwd->handle, -1); | 643 | channel_update_permitted_opens(ssh, rfwd->handle, -1); |
629 | if (rfwd->listen_path != NULL) | 644 | if (rfwd->listen_path != NULL) |
630 | xasprintf(&failmsg, "remote port forwarding failed for " | 645 | xasprintf(&failmsg, "remote port forwarding failed for " |
631 | "listen path %s", rfwd->listen_path); | 646 | "listen path %s", rfwd->listen_path); |
@@ -651,7 +666,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
651 | buffer_put_cstring(&out, failmsg); | 666 | buffer_put_cstring(&out, failmsg); |
652 | free(failmsg); | 667 | free(failmsg); |
653 | out: | 668 | out: |
654 | buffer_put_string(&c->output, buffer_ptr(&out), buffer_len(&out)); | 669 | buffer_put_string(c->output, buffer_ptr(&out), buffer_len(&out)); |
655 | buffer_free(&out); | 670 | buffer_free(&out); |
656 | if (c->mux_pause <= 0) | 671 | if (c->mux_pause <= 0) |
657 | fatal("%s: mux_pause %d", __func__, c->mux_pause); | 672 | fatal("%s: mux_pause %d", __func__, c->mux_pause); |
@@ -659,7 +674,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
659 | } | 674 | } |
660 | 675 | ||
661 | static int | 676 | static int |
662 | process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 677 | process_mux_open_fwd(struct ssh *ssh, u_int rid, |
678 | Channel *c, Buffer *m, Buffer *r) | ||
663 | { | 679 | { |
664 | struct Forward fwd; | 680 | struct Forward fwd; |
665 | char *fwd_desc = NULL; | 681 | char *fwd_desc = NULL; |
@@ -727,13 +743,16 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
727 | fwd.listen_port); | 743 | fwd.listen_port); |
728 | goto invalid; | 744 | goto invalid; |
729 | } | 745 | } |
730 | if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536) | 746 | if ((fwd.connect_port != PORT_STREAMLOCAL && |
731 | || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { | 747 | fwd.connect_port >= 65536) || |
748 | (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && | ||
749 | fwd.connect_port == 0)) { | ||
732 | logit("%s: invalid connect port %u", __func__, | 750 | logit("%s: invalid connect port %u", __func__, |
733 | fwd.connect_port); | 751 | fwd.connect_port); |
734 | goto invalid; | 752 | goto invalid; |
735 | } | 753 | } |
736 | if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) { | 754 | if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && |
755 | fwd.connect_path == NULL) { | ||
737 | logit("%s: missing connect host", __func__); | 756 | logit("%s: missing connect host", __func__); |
738 | goto invalid; | 757 | goto invalid; |
739 | } | 758 | } |
@@ -784,7 +803,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
784 | } | 803 | } |
785 | 804 | ||
786 | if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { | 805 | if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { |
787 | if (!channel_setup_local_fwd_listener(&fwd, | 806 | if (!channel_setup_local_fwd_listener(ssh, &fwd, |
788 | &options.fwd_opts)) { | 807 | &options.fwd_opts)) { |
789 | fail: | 808 | fail: |
790 | logit("slave-requested %s failed", fwd_desc); | 809 | logit("slave-requested %s failed", fwd_desc); |
@@ -798,7 +817,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
798 | } else { | 817 | } else { |
799 | struct mux_channel_confirm_ctx *fctx; | 818 | struct mux_channel_confirm_ctx *fctx; |
800 | 819 | ||
801 | fwd.handle = channel_request_remote_forwarding(&fwd); | 820 | fwd.handle = channel_request_remote_forwarding(ssh, &fwd); |
802 | if (fwd.handle < 0) | 821 | if (fwd.handle < 0) |
803 | goto fail; | 822 | goto fail; |
804 | add_remote_forward(&options, &fwd); | 823 | add_remote_forward(&options, &fwd); |
@@ -827,7 +846,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
827 | } | 846 | } |
828 | 847 | ||
829 | static int | 848 | static int |
830 | process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 849 | process_mux_close_fwd(struct ssh *ssh, u_int rid, |
850 | Channel *c, Buffer *m, Buffer *r) | ||
831 | { | 851 | { |
832 | struct Forward fwd, *found_fwd; | 852 | struct Forward fwd, *found_fwd; |
833 | char *fwd_desc = NULL; | 853 | char *fwd_desc = NULL; |
@@ -908,11 +928,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
908 | * However, for dynamic allocated listen ports we need | 928 | * However, for dynamic allocated listen ports we need |
909 | * to use the actual listen port. | 929 | * to use the actual listen port. |
910 | */ | 930 | */ |
911 | if (channel_request_rforward_cancel(found_fwd) == -1) | 931 | if (channel_request_rforward_cancel(ssh, found_fwd) == -1) |
912 | error_reason = "port not in permitted opens"; | 932 | error_reason = "port not in permitted opens"; |
913 | } else { /* local and dynamic forwards */ | 933 | } else { /* local and dynamic forwards */ |
914 | /* Ditto */ | 934 | /* Ditto */ |
915 | if (channel_cancel_lport_listener(&fwd, fwd.connect_port, | 935 | if (channel_cancel_lport_listener(ssh, &fwd, fwd.connect_port, |
916 | &options.fwd_opts) == -1) | 936 | &options.fwd_opts) == -1) |
917 | error_reason = "port not found"; | 937 | error_reason = "port not found"; |
918 | } | 938 | } |
@@ -942,7 +962,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
942 | } | 962 | } |
943 | 963 | ||
944 | static int | 964 | static int |
945 | process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | 965 | process_mux_stdio_fwd(struct ssh *ssh, u_int rid, |
966 | Channel *c, Buffer *m, Buffer *r) | ||
946 | { | 967 | { |
947 | Channel *nc; | 968 | Channel *nc; |
948 | char *reserved, *chost; | 969 | char *reserved, *chost; |
@@ -1018,7 +1039,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
1018 | if (!isatty(new_fd[1])) | 1039 | if (!isatty(new_fd[1])) |
1019 | set_nonblock(new_fd[1]); | 1040 | set_nonblock(new_fd[1]); |
1020 | 1041 | ||
1021 | nc = channel_connect_stdio_fwd(chost, cport, new_fd[0], new_fd[1]); | 1042 | nc = channel_connect_stdio_fwd(ssh, chost, cport, new_fd[0], new_fd[1]); |
1022 | 1043 | ||
1023 | nc->ctl_chan = c->self; /* link session -> control channel */ | 1044 | nc->ctl_chan = c->self; /* link session -> control channel */ |
1024 | c->remote_id = nc->self; /* link control -> session channel */ | 1045 | c->remote_id = nc->self; /* link control -> session channel */ |
@@ -1026,11 +1047,12 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
1026 | debug2("%s: channel_new: %d linked to control channel %d", | 1047 | debug2("%s: channel_new: %d linked to control channel %d", |
1027 | __func__, nc->self, nc->ctl_chan); | 1048 | __func__, nc->self, nc->ctl_chan); |
1028 | 1049 | ||
1029 | channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); | 1050 | channel_register_cleanup(ssh, nc->self, |
1051 | mux_master_session_cleanup_cb, 1); | ||
1030 | 1052 | ||
1031 | cctx = xcalloc(1, sizeof(*cctx)); | 1053 | cctx = xcalloc(1, sizeof(*cctx)); |
1032 | cctx->rid = rid; | 1054 | cctx->rid = rid; |
1033 | channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx); | 1055 | channel_register_open_confirm(ssh, nc->self, mux_stdio_confirm, cctx); |
1034 | c->mux_pause = 1; /* stop handling messages until open_confirm done */ | 1056 | c->mux_pause = 1; /* stop handling messages until open_confirm done */ |
1035 | 1057 | ||
1036 | /* reply is deferred, sent by mux_session_confirm */ | 1058 | /* reply is deferred, sent by mux_session_confirm */ |
@@ -1039,7 +1061,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
1039 | 1061 | ||
1040 | /* Callback on open confirmation in mux master for a mux stdio fwd session. */ | 1062 | /* Callback on open confirmation in mux master for a mux stdio fwd session. */ |
1041 | static void | 1063 | static void |
1042 | mux_stdio_confirm(int id, int success, void *arg) | 1064 | mux_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) |
1043 | { | 1065 | { |
1044 | struct mux_stdio_confirm_ctx *cctx = arg; | 1066 | struct mux_stdio_confirm_ctx *cctx = arg; |
1045 | Channel *c, *cc; | 1067 | Channel *c, *cc; |
@@ -1047,9 +1069,9 @@ mux_stdio_confirm(int id, int success, void *arg) | |||
1047 | 1069 | ||
1048 | if (cctx == NULL) | 1070 | if (cctx == NULL) |
1049 | fatal("%s: cctx == NULL", __func__); | 1071 | fatal("%s: cctx == NULL", __func__); |
1050 | if ((c = channel_by_id(id)) == NULL) | 1072 | if ((c = channel_by_id(ssh, id)) == NULL) |
1051 | fatal("%s: no channel for id %d", __func__, id); | 1073 | fatal("%s: no channel for id %d", __func__, id); |
1052 | if ((cc = channel_by_id(c->ctl_chan)) == NULL) | 1074 | if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) |
1053 | fatal("%s: channel %d lacks control channel %d", __func__, | 1075 | fatal("%s: channel %d lacks control channel %d", __func__, |
1054 | id, c->ctl_chan); | 1076 | id, c->ctl_chan); |
1055 | 1077 | ||
@@ -1072,7 +1094,7 @@ mux_stdio_confirm(int id, int success, void *arg) | |||
1072 | 1094 | ||
1073 | done: | 1095 | done: |
1074 | /* Send reply */ | 1096 | /* Send reply */ |
1075 | buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); | 1097 | buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply)); |
1076 | buffer_free(&reply); | 1098 | buffer_free(&reply); |
1077 | 1099 | ||
1078 | if (cc->mux_pause <= 0) | 1100 | if (cc->mux_pause <= 0) |
@@ -1083,7 +1105,8 @@ mux_stdio_confirm(int id, int success, void *arg) | |||
1083 | } | 1105 | } |
1084 | 1106 | ||
1085 | static int | 1107 | static int |
1086 | process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) | 1108 | process_mux_stop_listening(struct ssh *ssh, u_int rid, |
1109 | Channel *c, Buffer *m, Buffer *r) | ||
1087 | { | 1110 | { |
1088 | debug("%s: channel %d: stop listening", __func__, c->self); | 1111 | debug("%s: channel %d: stop listening", __func__, c->self); |
1089 | 1112 | ||
@@ -1100,7 +1123,7 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
1100 | } | 1123 | } |
1101 | 1124 | ||
1102 | if (mux_listener_channel != NULL) { | 1125 | if (mux_listener_channel != NULL) { |
1103 | channel_free(mux_listener_channel); | 1126 | channel_free(ssh, mux_listener_channel); |
1104 | client_stop_mux(); | 1127 | client_stop_mux(); |
1105 | free(options.control_path); | 1128 | free(options.control_path); |
1106 | options.control_path = NULL; | 1129 | options.control_path = NULL; |
@@ -1116,7 +1139,8 @@ process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
1116 | } | 1139 | } |
1117 | 1140 | ||
1118 | static int | 1141 | static int |
1119 | process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r) | 1142 | process_mux_proxy(struct ssh *ssh, u_int rid, |
1143 | Channel *c, Buffer *m, Buffer *r) | ||
1120 | { | 1144 | { |
1121 | debug("%s: channel %d: proxy request", __func__, c->self); | 1145 | debug("%s: channel %d: proxy request", __func__, c->self); |
1122 | 1146 | ||
@@ -1129,7 +1153,7 @@ process_mux_proxy(u_int rid, Channel *c, Buffer *m, Buffer *r) | |||
1129 | 1153 | ||
1130 | /* Channel callbacks fired on read/write from mux slave fd */ | 1154 | /* Channel callbacks fired on read/write from mux slave fd */ |
1131 | static int | 1155 | static int |
1132 | mux_master_read_cb(Channel *c) | 1156 | mux_master_read_cb(struct ssh *ssh, Channel *c) |
1133 | { | 1157 | { |
1134 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; | 1158 | struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; |
1135 | Buffer in, out; | 1159 | Buffer in, out; |
@@ -1141,7 +1165,7 @@ mux_master_read_cb(Channel *c) | |||
1141 | if (c->mux_ctx == NULL) { | 1165 | if (c->mux_ctx == NULL) { |
1142 | state = xcalloc(1, sizeof(*state)); | 1166 | state = xcalloc(1, sizeof(*state)); |
1143 | c->mux_ctx = state; | 1167 | c->mux_ctx = state; |
1144 | channel_register_cleanup(c->self, | 1168 | channel_register_cleanup(ssh, c->self, |
1145 | mux_master_control_cleanup_cb, 0); | 1169 | mux_master_control_cleanup_cb, 0); |
1146 | 1170 | ||
1147 | /* Send hello */ | 1171 | /* Send hello */ |
@@ -1149,7 +1173,7 @@ mux_master_read_cb(Channel *c) | |||
1149 | buffer_put_int(&out, MUX_MSG_HELLO); | 1173 | buffer_put_int(&out, MUX_MSG_HELLO); |
1150 | buffer_put_int(&out, SSHMUX_VER); | 1174 | buffer_put_int(&out, SSHMUX_VER); |
1151 | /* no extensions */ | 1175 | /* no extensions */ |
1152 | buffer_put_string(&c->output, buffer_ptr(&out), | 1176 | buffer_put_string(c->output, buffer_ptr(&out), |
1153 | buffer_len(&out)); | 1177 | buffer_len(&out)); |
1154 | buffer_free(&out); | 1178 | buffer_free(&out); |
1155 | debug3("%s: channel %d: hello sent", __func__, c->self); | 1179 | debug3("%s: channel %d: hello sent", __func__, c->self); |
@@ -1160,7 +1184,7 @@ mux_master_read_cb(Channel *c) | |||
1160 | buffer_init(&out); | 1184 | buffer_init(&out); |
1161 | 1185 | ||
1162 | /* Channel code ensures that we receive whole packets */ | 1186 | /* Channel code ensures that we receive whole packets */ |
1163 | if ((ptr = buffer_get_string_ptr_ret(&c->input, &have)) == NULL) { | 1187 | if ((ptr = buffer_get_string_ptr_ret(c->input, &have)) == NULL) { |
1164 | malf: | 1188 | malf: |
1165 | error("%s: malformed message", __func__); | 1189 | error("%s: malformed message", __func__); |
1166 | goto out; | 1190 | goto out; |
@@ -1186,7 +1210,8 @@ mux_master_read_cb(Channel *c) | |||
1186 | 1210 | ||
1187 | for (i = 0; mux_master_handlers[i].handler != NULL; i++) { | 1211 | for (i = 0; mux_master_handlers[i].handler != NULL; i++) { |
1188 | if (type == mux_master_handlers[i].type) { | 1212 | if (type == mux_master_handlers[i].type) { |
1189 | ret = mux_master_handlers[i].handler(rid, c, &in, &out); | 1213 | ret = mux_master_handlers[i].handler(ssh, rid, |
1214 | c, &in, &out); | ||
1190 | break; | 1215 | break; |
1191 | } | 1216 | } |
1192 | } | 1217 | } |
@@ -1199,7 +1224,7 @@ mux_master_read_cb(Channel *c) | |||
1199 | } | 1224 | } |
1200 | /* Enqueue reply packet */ | 1225 | /* Enqueue reply packet */ |
1201 | if (buffer_len(&out) != 0) { | 1226 | if (buffer_len(&out) != 0) { |
1202 | buffer_put_string(&c->output, buffer_ptr(&out), | 1227 | buffer_put_string(c->output, buffer_ptr(&out), |
1203 | buffer_len(&out)); | 1228 | buffer_len(&out)); |
1204 | } | 1229 | } |
1205 | out: | 1230 | out: |
@@ -1209,7 +1234,7 @@ mux_master_read_cb(Channel *c) | |||
1209 | } | 1234 | } |
1210 | 1235 | ||
1211 | void | 1236 | void |
1212 | mux_exit_message(Channel *c, int exitval) | 1237 | mux_exit_message(struct ssh *ssh, Channel *c, int exitval) |
1213 | { | 1238 | { |
1214 | Buffer m; | 1239 | Buffer m; |
1215 | Channel *mux_chan; | 1240 | Channel *mux_chan; |
@@ -1217,7 +1242,7 @@ mux_exit_message(Channel *c, int exitval) | |||
1217 | debug3("%s: channel %d: exit message, exitval %d", __func__, c->self, | 1242 | debug3("%s: channel %d: exit message, exitval %d", __func__, c->self, |
1218 | exitval); | 1243 | exitval); |
1219 | 1244 | ||
1220 | if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL) | 1245 | if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL) |
1221 | fatal("%s: channel %d missing mux channel %d", | 1246 | fatal("%s: channel %d missing mux channel %d", |
1222 | __func__, c->self, c->ctl_chan); | 1247 | __func__, c->self, c->ctl_chan); |
1223 | 1248 | ||
@@ -1227,19 +1252,19 @@ mux_exit_message(Channel *c, int exitval) | |||
1227 | buffer_put_int(&m, c->self); | 1252 | buffer_put_int(&m, c->self); |
1228 | buffer_put_int(&m, exitval); | 1253 | buffer_put_int(&m, exitval); |
1229 | 1254 | ||
1230 | buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m)); | 1255 | buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m)); |
1231 | buffer_free(&m); | 1256 | buffer_free(&m); |
1232 | } | 1257 | } |
1233 | 1258 | ||
1234 | void | 1259 | void |
1235 | mux_tty_alloc_failed(Channel *c) | 1260 | mux_tty_alloc_failed(struct ssh *ssh, Channel *c) |
1236 | { | 1261 | { |
1237 | Buffer m; | 1262 | Buffer m; |
1238 | Channel *mux_chan; | 1263 | Channel *mux_chan; |
1239 | 1264 | ||
1240 | debug3("%s: channel %d: TTY alloc failed", __func__, c->self); | 1265 | debug3("%s: channel %d: TTY alloc failed", __func__, c->self); |
1241 | 1266 | ||
1242 | if ((mux_chan = channel_by_id(c->ctl_chan)) == NULL) | 1267 | if ((mux_chan = channel_by_id(ssh, c->ctl_chan)) == NULL) |
1243 | fatal("%s: channel %d missing mux channel %d", | 1268 | fatal("%s: channel %d missing mux channel %d", |
1244 | __func__, c->self, c->ctl_chan); | 1269 | __func__, c->self, c->ctl_chan); |
1245 | 1270 | ||
@@ -1248,13 +1273,13 @@ mux_tty_alloc_failed(Channel *c) | |||
1248 | buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL); | 1273 | buffer_put_int(&m, MUX_S_TTY_ALLOC_FAIL); |
1249 | buffer_put_int(&m, c->self); | 1274 | buffer_put_int(&m, c->self); |
1250 | 1275 | ||
1251 | buffer_put_string(&mux_chan->output, buffer_ptr(&m), buffer_len(&m)); | 1276 | buffer_put_string(mux_chan->output, buffer_ptr(&m), buffer_len(&m)); |
1252 | buffer_free(&m); | 1277 | buffer_free(&m); |
1253 | } | 1278 | } |
1254 | 1279 | ||
1255 | /* Prepare a mux master to listen on a Unix domain socket. */ | 1280 | /* Prepare a mux master to listen on a Unix domain socket. */ |
1256 | void | 1281 | void |
1257 | muxserver_listen(void) | 1282 | muxserver_listen(struct ssh *ssh) |
1258 | { | 1283 | { |
1259 | mode_t old_umask; | 1284 | mode_t old_umask; |
1260 | char *orig_control_path = options.control_path; | 1285 | char *orig_control_path = options.control_path; |
@@ -1327,7 +1352,7 @@ muxserver_listen(void) | |||
1327 | 1352 | ||
1328 | set_nonblock(muxserver_sock); | 1353 | set_nonblock(muxserver_sock); |
1329 | 1354 | ||
1330 | mux_listener_channel = channel_new("mux listener", | 1355 | mux_listener_channel = channel_new(ssh, "mux listener", |
1331 | SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1, | 1356 | SSH_CHANNEL_MUX_LISTENER, muxserver_sock, muxserver_sock, -1, |
1332 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | 1357 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, |
1333 | 0, options.control_path, 1); | 1358 | 0, options.control_path, 1); |
@@ -1338,7 +1363,7 @@ muxserver_listen(void) | |||
1338 | 1363 | ||
1339 | /* Callback on open confirmation in mux master for a mux client session. */ | 1364 | /* Callback on open confirmation in mux master for a mux client session. */ |
1340 | static void | 1365 | static void |
1341 | mux_session_confirm(int id, int success, void *arg) | 1366 | mux_session_confirm(struct ssh *ssh, int id, int success, void *arg) |
1342 | { | 1367 | { |
1343 | struct mux_session_confirm_ctx *cctx = arg; | 1368 | struct mux_session_confirm_ctx *cctx = arg; |
1344 | const char *display; | 1369 | const char *display; |
@@ -1348,9 +1373,9 @@ mux_session_confirm(int id, int success, void *arg) | |||
1348 | 1373 | ||
1349 | if (cctx == NULL) | 1374 | if (cctx == NULL) |
1350 | fatal("%s: cctx == NULL", __func__); | 1375 | fatal("%s: cctx == NULL", __func__); |
1351 | if ((c = channel_by_id(id)) == NULL) | 1376 | if ((c = channel_by_id(ssh, id)) == NULL) |
1352 | fatal("%s: no channel for id %d", __func__, id); | 1377 | fatal("%s: no channel for id %d", __func__, id); |
1353 | if ((cc = channel_by_id(c->ctl_chan)) == NULL) | 1378 | if ((cc = channel_by_id(ssh, c->ctl_chan)) == NULL) |
1354 | fatal("%s: channel %d lacks control channel %d", __func__, | 1379 | fatal("%s: channel %d lacks control channel %d", __func__, |
1355 | id, c->ctl_chan); | 1380 | id, c->ctl_chan); |
1356 | 1381 | ||
@@ -1369,27 +1394,27 @@ mux_session_confirm(int id, int success, void *arg) | |||
1369 | char *proto, *data; | 1394 | char *proto, *data; |
1370 | 1395 | ||
1371 | /* Get reasonable local authentication information. */ | 1396 | /* Get reasonable local authentication information. */ |
1372 | if (client_x11_get_proto(display, options.xauth_location, | 1397 | if (client_x11_get_proto(ssh, display, options.xauth_location, |
1373 | options.forward_x11_trusted, options.forward_x11_timeout, | 1398 | options.forward_x11_trusted, options.forward_x11_timeout, |
1374 | &proto, &data) == 0) { | 1399 | &proto, &data) == 0) { |
1375 | /* Request forwarding with authentication spoofing. */ | 1400 | /* Request forwarding with authentication spoofing. */ |
1376 | debug("Requesting X11 forwarding with authentication " | 1401 | debug("Requesting X11 forwarding with authentication " |
1377 | "spoofing."); | 1402 | "spoofing."); |
1378 | x11_request_forwarding_with_spoofing(id, display, proto, | 1403 | x11_request_forwarding_with_spoofing(ssh, id, |
1379 | data, 1); | 1404 | display, proto, data, 1); |
1380 | /* XXX exit_on_forward_failure */ | 1405 | /* XXX exit_on_forward_failure */ |
1381 | client_expect_confirm(id, "X11 forwarding", | 1406 | client_expect_confirm(ssh, id, "X11 forwarding", |
1382 | CONFIRM_WARN); | 1407 | CONFIRM_WARN); |
1383 | } | 1408 | } |
1384 | } | 1409 | } |
1385 | 1410 | ||
1386 | if (cctx->want_agent_fwd && options.forward_agent) { | 1411 | if (cctx->want_agent_fwd && options.forward_agent) { |
1387 | debug("Requesting authentication agent forwarding."); | 1412 | debug("Requesting authentication agent forwarding."); |
1388 | channel_request_start(id, "auth-agent-req@openssh.com", 0); | 1413 | channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); |
1389 | packet_send(); | 1414 | packet_send(); |
1390 | } | 1415 | } |
1391 | 1416 | ||
1392 | client_session2_setup(id, cctx->want_tty, cctx->want_subsys, | 1417 | client_session2_setup(ssh, id, cctx->want_tty, cctx->want_subsys, |
1393 | cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); | 1418 | cctx->term, &cctx->tio, c->rfd, &cctx->cmd, cctx->env); |
1394 | 1419 | ||
1395 | debug3("%s: sending success reply", __func__); | 1420 | debug3("%s: sending success reply", __func__); |
@@ -1401,7 +1426,7 @@ mux_session_confirm(int id, int success, void *arg) | |||
1401 | 1426 | ||
1402 | done: | 1427 | done: |
1403 | /* Send reply */ | 1428 | /* Send reply */ |
1404 | buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply)); | 1429 | buffer_put_string(cc->output, buffer_ptr(&reply), buffer_len(&reply)); |
1405 | buffer_free(&reply); | 1430 | buffer_free(&reply); |
1406 | 1431 | ||
1407 | if (cc->mux_pause <= 0) | 1432 | if (cc->mux_pause <= 0) |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: nchan.c,v 1.65 2017/04/30 23:28:42 djm Exp $ */ | 1 | /* $OpenBSD: nchan.c,v 1.66 2017/09/12 06:32:07 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -34,7 +34,8 @@ | |||
34 | 34 | ||
35 | #include "openbsd-compat/sys-queue.h" | 35 | #include "openbsd-compat/sys-queue.h" |
36 | #include "ssh2.h" | 36 | #include "ssh2.h" |
37 | #include "buffer.h" | 37 | #include "sshbuf.h" |
38 | #include "ssherr.h" | ||
38 | #include "packet.h" | 39 | #include "packet.h" |
39 | #include "channels.h" | 40 | #include "channels.h" |
40 | #include "compat.h" | 41 | #include "compat.h" |
@@ -73,15 +74,15 @@ | |||
73 | /* | 74 | /* |
74 | * ACTIONS: should never update the channel states | 75 | * ACTIONS: should never update the channel states |
75 | */ | 76 | */ |
76 | static void chan_send_eof2(Channel *); | 77 | static void chan_send_eof2(struct ssh *, Channel *); |
77 | static void chan_send_eow2(Channel *); | 78 | static void chan_send_eow2(struct ssh *, Channel *); |
78 | 79 | ||
79 | /* helper */ | 80 | /* helper */ |
80 | static void chan_shutdown_write(Channel *); | 81 | static void chan_shutdown_write(struct ssh *, Channel *); |
81 | static void chan_shutdown_read(Channel *); | 82 | static void chan_shutdown_read(struct ssh *, Channel *); |
82 | 83 | ||
83 | static char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; | 84 | static const char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; |
84 | static char *istates[] = { "open", "drain", "wait_oclose", "closed" }; | 85 | static const char *istates[] = { "open", "drain", "wait_oclose", "closed" }; |
85 | 86 | ||
86 | static void | 87 | static void |
87 | chan_set_istate(Channel *c, u_int next) | 88 | chan_set_istate(Channel *c, u_int next) |
@@ -104,12 +105,12 @@ chan_set_ostate(Channel *c, u_int next) | |||
104 | } | 105 | } |
105 | 106 | ||
106 | void | 107 | void |
107 | chan_read_failed(Channel *c) | 108 | chan_read_failed(struct ssh *ssh, Channel *c) |
108 | { | 109 | { |
109 | debug2("channel %d: read failed", c->self); | 110 | debug2("channel %d: read failed", c->self); |
110 | switch (c->istate) { | 111 | switch (c->istate) { |
111 | case CHAN_INPUT_OPEN: | 112 | case CHAN_INPUT_OPEN: |
112 | chan_shutdown_read(c); | 113 | chan_shutdown_read(ssh, c); |
113 | chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); | 114 | chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); |
114 | break; | 115 | break; |
115 | default: | 116 | default: |
@@ -120,10 +121,10 @@ chan_read_failed(Channel *c) | |||
120 | } | 121 | } |
121 | 122 | ||
122 | void | 123 | void |
123 | chan_ibuf_empty(Channel *c) | 124 | chan_ibuf_empty(struct ssh *ssh, Channel *c) |
124 | { | 125 | { |
125 | debug2("channel %d: ibuf empty", c->self); | 126 | debug2("channel %d: ibuf empty", c->self); |
126 | if (buffer_len(&c->input)) { | 127 | if (sshbuf_len(c->input)) { |
127 | error("channel %d: chan_ibuf_empty for non empty buffer", | 128 | error("channel %d: chan_ibuf_empty for non empty buffer", |
128 | c->self); | 129 | c->self); |
129 | return; | 130 | return; |
@@ -131,7 +132,7 @@ chan_ibuf_empty(Channel *c) | |||
131 | switch (c->istate) { | 132 | switch (c->istate) { |
132 | case CHAN_INPUT_WAIT_DRAIN: | 133 | case CHAN_INPUT_WAIT_DRAIN: |
133 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) | 134 | if (!(c->flags & (CHAN_CLOSE_SENT|CHAN_LOCAL))) |
134 | chan_send_eof2(c); | 135 | chan_send_eof2(ssh, c); |
135 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 136 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
136 | break; | 137 | break; |
137 | default: | 138 | default: |
@@ -142,17 +143,17 @@ chan_ibuf_empty(Channel *c) | |||
142 | } | 143 | } |
143 | 144 | ||
144 | void | 145 | void |
145 | chan_obuf_empty(Channel *c) | 146 | chan_obuf_empty(struct ssh *ssh, Channel *c) |
146 | { | 147 | { |
147 | debug2("channel %d: obuf empty", c->self); | 148 | debug2("channel %d: obuf empty", c->self); |
148 | if (buffer_len(&c->output)) { | 149 | if (sshbuf_len(c->output)) { |
149 | error("channel %d: chan_obuf_empty for non empty buffer", | 150 | error("channel %d: chan_obuf_empty for non empty buffer", |
150 | c->self); | 151 | c->self); |
151 | return; | 152 | return; |
152 | } | 153 | } |
153 | switch (c->ostate) { | 154 | switch (c->ostate) { |
154 | case CHAN_OUTPUT_WAIT_DRAIN: | 155 | case CHAN_OUTPUT_WAIT_DRAIN: |
155 | chan_shutdown_write(c); | 156 | chan_shutdown_write(ssh, c); |
156 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | 157 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
157 | break; | 158 | break; |
158 | default: | 159 | default: |
@@ -163,26 +164,29 @@ chan_obuf_empty(Channel *c) | |||
163 | } | 164 | } |
164 | 165 | ||
165 | void | 166 | void |
166 | chan_rcvd_eow(Channel *c) | 167 | chan_rcvd_eow(struct ssh *ssh, Channel *c) |
167 | { | 168 | { |
168 | debug2("channel %d: rcvd eow", c->self); | 169 | debug2("channel %d: rcvd eow", c->self); |
169 | switch (c->istate) { | 170 | switch (c->istate) { |
170 | case CHAN_INPUT_OPEN: | 171 | case CHAN_INPUT_OPEN: |
171 | chan_shutdown_read(c); | 172 | chan_shutdown_read(ssh, c); |
172 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 173 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
173 | break; | 174 | break; |
174 | } | 175 | } |
175 | } | 176 | } |
176 | 177 | ||
177 | static void | 178 | static void |
178 | chan_send_eof2(Channel *c) | 179 | chan_send_eof2(struct ssh *ssh, Channel *c) |
179 | { | 180 | { |
181 | int r; | ||
182 | |||
180 | debug2("channel %d: send eof", c->self); | 183 | debug2("channel %d: send eof", c->self); |
181 | switch (c->istate) { | 184 | switch (c->istate) { |
182 | case CHAN_INPUT_WAIT_DRAIN: | 185 | case CHAN_INPUT_WAIT_DRAIN: |
183 | packet_start(SSH2_MSG_CHANNEL_EOF); | 186 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EOF)) != 0 || |
184 | packet_put_int(c->remote_id); | 187 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
185 | packet_send(); | 188 | (r = sshpkt_send(ssh)) != 0) |
189 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
186 | c->flags |= CHAN_EOF_SENT; | 190 | c->flags |= CHAN_EOF_SENT; |
187 | break; | 191 | break; |
188 | default: | 192 | default: |
@@ -193,8 +197,10 @@ chan_send_eof2(Channel *c) | |||
193 | } | 197 | } |
194 | 198 | ||
195 | static void | 199 | static void |
196 | chan_send_close2(Channel *c) | 200 | chan_send_close2(struct ssh *ssh, Channel *c) |
197 | { | 201 | { |
202 | int r; | ||
203 | |||
198 | debug2("channel %d: send close", c->self); | 204 | debug2("channel %d: send close", c->self); |
199 | if (c->ostate != CHAN_OUTPUT_CLOSED || | 205 | if (c->ostate != CHAN_OUTPUT_CLOSED || |
200 | c->istate != CHAN_INPUT_CLOSED) { | 206 | c->istate != CHAN_INPUT_CLOSED) { |
@@ -203,16 +209,19 @@ chan_send_close2(Channel *c) | |||
203 | } else if (c->flags & CHAN_CLOSE_SENT) { | 209 | } else if (c->flags & CHAN_CLOSE_SENT) { |
204 | error("channel %d: already sent close", c->self); | 210 | error("channel %d: already sent close", c->self); |
205 | } else { | 211 | } else { |
206 | packet_start(SSH2_MSG_CHANNEL_CLOSE); | 212 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_CLOSE)) != 0 || |
207 | packet_put_int(c->remote_id); | 213 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
208 | packet_send(); | 214 | (r = sshpkt_send(ssh)) != 0) |
215 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
209 | c->flags |= CHAN_CLOSE_SENT; | 216 | c->flags |= CHAN_CLOSE_SENT; |
210 | } | 217 | } |
211 | } | 218 | } |
212 | 219 | ||
213 | static void | 220 | static void |
214 | chan_send_eow2(Channel *c) | 221 | chan_send_eow2(struct ssh *ssh, Channel *c) |
215 | { | 222 | { |
223 | int r; | ||
224 | |||
216 | debug2("channel %d: send eow", c->self); | 225 | debug2("channel %d: send eow", c->self); |
217 | if (c->ostate == CHAN_OUTPUT_CLOSED) { | 226 | if (c->ostate == CHAN_OUTPUT_CLOSED) { |
218 | error("channel %d: must not sent eow on closed output", | 227 | error("channel %d: must not sent eow on closed output", |
@@ -221,30 +230,31 @@ chan_send_eow2(Channel *c) | |||
221 | } | 230 | } |
222 | if (!(datafellows & SSH_NEW_OPENSSH)) | 231 | if (!(datafellows & SSH_NEW_OPENSSH)) |
223 | return; | 232 | return; |
224 | packet_start(SSH2_MSG_CHANNEL_REQUEST); | 233 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 || |
225 | packet_put_int(c->remote_id); | 234 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
226 | packet_put_cstring("eow@openssh.com"); | 235 | (r = sshpkt_put_cstring(ssh, "eow@openssh.com")) != 0 || |
227 | packet_put_char(0); | 236 | (r = sshpkt_put_u8(ssh, 0)) != 0 || |
228 | packet_send(); | 237 | (r = sshpkt_send(ssh)) != 0) |
238 | fatal("%s: send CHANNEL_EOF: %s", __func__, ssh_err(r)); | ||
229 | } | 239 | } |
230 | 240 | ||
231 | /* shared */ | 241 | /* shared */ |
232 | 242 | ||
233 | void | 243 | void |
234 | chan_rcvd_ieof(Channel *c) | 244 | chan_rcvd_ieof(struct ssh *ssh, Channel *c) |
235 | { | 245 | { |
236 | debug2("channel %d: rcvd eof", c->self); | 246 | debug2("channel %d: rcvd eof", c->self); |
237 | c->flags |= CHAN_EOF_RCVD; | 247 | c->flags |= CHAN_EOF_RCVD; |
238 | if (c->ostate == CHAN_OUTPUT_OPEN) | 248 | if (c->ostate == CHAN_OUTPUT_OPEN) |
239 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); | 249 | chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); |
240 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && | 250 | if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN && |
241 | buffer_len(&c->output) == 0 && | 251 | sshbuf_len(c->output) == 0 && |
242 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) | 252 | !CHANNEL_EFD_OUTPUT_ACTIVE(c)) |
243 | chan_obuf_empty(c); | 253 | chan_obuf_empty(ssh, c); |
244 | } | 254 | } |
245 | 255 | ||
246 | void | 256 | void |
247 | chan_rcvd_oclose(Channel *c) | 257 | chan_rcvd_oclose(struct ssh *ssh, Channel *c) |
248 | { | 258 | { |
249 | debug2("channel %d: rcvd close", c->self); | 259 | debug2("channel %d: rcvd close", c->self); |
250 | if (!(c->flags & CHAN_LOCAL)) { | 260 | if (!(c->flags & CHAN_LOCAL)) { |
@@ -270,27 +280,27 @@ chan_rcvd_oclose(Channel *c) | |||
270 | } | 280 | } |
271 | switch (c->istate) { | 281 | switch (c->istate) { |
272 | case CHAN_INPUT_OPEN: | 282 | case CHAN_INPUT_OPEN: |
273 | chan_shutdown_read(c); | 283 | chan_shutdown_read(ssh, c); |
274 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 284 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
275 | break; | 285 | break; |
276 | case CHAN_INPUT_WAIT_DRAIN: | 286 | case CHAN_INPUT_WAIT_DRAIN: |
277 | if (!(c->flags & CHAN_LOCAL)) | 287 | if (!(c->flags & CHAN_LOCAL)) |
278 | chan_send_eof2(c); | 288 | chan_send_eof2(ssh, c); |
279 | chan_set_istate(c, CHAN_INPUT_CLOSED); | 289 | chan_set_istate(c, CHAN_INPUT_CLOSED); |
280 | break; | 290 | break; |
281 | } | 291 | } |
282 | } | 292 | } |
283 | 293 | ||
284 | void | 294 | void |
285 | chan_write_failed(Channel *c) | 295 | chan_write_failed(struct ssh *ssh, Channel *c) |
286 | { | 296 | { |
287 | debug2("channel %d: write failed", c->self); | 297 | debug2("channel %d: write failed", c->self); |
288 | switch (c->ostate) { | 298 | switch (c->ostate) { |
289 | case CHAN_OUTPUT_OPEN: | 299 | case CHAN_OUTPUT_OPEN: |
290 | case CHAN_OUTPUT_WAIT_DRAIN: | 300 | case CHAN_OUTPUT_WAIT_DRAIN: |
291 | chan_shutdown_write(c); | 301 | chan_shutdown_write(ssh, c); |
292 | if (strcmp(c->ctype, "session") == 0) | 302 | if (strcmp(c->ctype, "session") == 0) |
293 | chan_send_eow2(c); | 303 | chan_send_eow2(ssh, c); |
294 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); | 304 | chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
295 | break; | 305 | break; |
296 | default: | 306 | default: |
@@ -301,13 +311,13 @@ chan_write_failed(Channel *c) | |||
301 | } | 311 | } |
302 | 312 | ||
303 | void | 313 | void |
304 | chan_mark_dead(Channel *c) | 314 | chan_mark_dead(struct ssh *ssh, Channel *c) |
305 | { | 315 | { |
306 | c->type = SSH_CHANNEL_ZOMBIE; | 316 | c->type = SSH_CHANNEL_ZOMBIE; |
307 | } | 317 | } |
308 | 318 | ||
309 | int | 319 | int |
310 | chan_is_dead(Channel *c, int do_send) | 320 | chan_is_dead(struct ssh *ssh, Channel *c, int do_send) |
311 | { | 321 | { |
312 | if (c->type == SSH_CHANNEL_ZOMBIE) { | 322 | if (c->type == SSH_CHANNEL_ZOMBIE) { |
313 | debug2("channel %d: zombie", c->self); | 323 | debug2("channel %d: zombie", c->self); |
@@ -318,9 +328,9 @@ chan_is_dead(Channel *c, int do_send) | |||
318 | if ((datafellows & SSH_BUG_EXTEOF) && | 328 | if ((datafellows & SSH_BUG_EXTEOF) && |
319 | c->extended_usage == CHAN_EXTENDED_WRITE && | 329 | c->extended_usage == CHAN_EXTENDED_WRITE && |
320 | c->efd != -1 && | 330 | c->efd != -1 && |
321 | buffer_len(&c->extended) > 0) { | 331 | sshbuf_len(c->extended) > 0) { |
322 | debug2("channel %d: active efd: %d len %d", | 332 | debug2("channel %d: active efd: %d len %zu", |
323 | c->self, c->efd, buffer_len(&c->extended)); | 333 | c->self, c->efd, sshbuf_len(c->extended)); |
324 | return 0; | 334 | return 0; |
325 | } | 335 | } |
326 | if (c->flags & CHAN_LOCAL) { | 336 | if (c->flags & CHAN_LOCAL) { |
@@ -329,7 +339,7 @@ chan_is_dead(Channel *c, int do_send) | |||
329 | } | 339 | } |
330 | if (!(c->flags & CHAN_CLOSE_SENT)) { | 340 | if (!(c->flags & CHAN_CLOSE_SENT)) { |
331 | if (do_send) { | 341 | if (do_send) { |
332 | chan_send_close2(c); | 342 | chan_send_close2(ssh, c); |
333 | } else { | 343 | } else { |
334 | /* channel would be dead if we sent a close */ | 344 | /* channel would be dead if we sent a close */ |
335 | if (c->flags & CHAN_CLOSE_RCVD) { | 345 | if (c->flags & CHAN_CLOSE_RCVD) { |
@@ -349,9 +359,9 @@ chan_is_dead(Channel *c, int do_send) | |||
349 | 359 | ||
350 | /* helper */ | 360 | /* helper */ |
351 | static void | 361 | static void |
352 | chan_shutdown_write(Channel *c) | 362 | chan_shutdown_write(struct ssh *ssh, Channel *c) |
353 | { | 363 | { |
354 | buffer_clear(&c->output); | 364 | sshbuf_reset(c->output); |
355 | if (c->type == SSH_CHANNEL_LARVAL) | 365 | if (c->type == SSH_CHANNEL_LARVAL) |
356 | return; | 366 | return; |
357 | /* shutdown failure is allowed if write failed already */ | 367 | /* shutdown failure is allowed if write failed already */ |
@@ -362,7 +372,7 @@ chan_shutdown_write(Channel *c) | |||
362 | "shutdown() failed for fd %d: %.100s", | 372 | "shutdown() failed for fd %d: %.100s", |
363 | c->self, c->sock, strerror(errno)); | 373 | c->self, c->sock, strerror(errno)); |
364 | } else { | 374 | } else { |
365 | if (channel_close_fd(&c->wfd) < 0) | 375 | if (channel_close_fd(ssh, &c->wfd) < 0) |
366 | logit("channel %d: chan_shutdown_write: " | 376 | logit("channel %d: chan_shutdown_write: " |
367 | "close() failed for fd %d: %.100s", | 377 | "close() failed for fd %d: %.100s", |
368 | c->self, c->wfd, strerror(errno)); | 378 | c->self, c->wfd, strerror(errno)); |
@@ -370,7 +380,7 @@ chan_shutdown_write(Channel *c) | |||
370 | } | 380 | } |
371 | 381 | ||
372 | static void | 382 | static void |
373 | chan_shutdown_read(Channel *c) | 383 | chan_shutdown_read(struct ssh *ssh, Channel *c) |
374 | { | 384 | { |
375 | if (c->type == SSH_CHANNEL_LARVAL) | 385 | if (c->type == SSH_CHANNEL_LARVAL) |
376 | return; | 386 | return; |
@@ -388,7 +398,7 @@ chan_shutdown_read(Channel *c) | |||
388 | c->self, c->sock, c->istate, c->ostate, | 398 | c->self, c->sock, c->istate, c->ostate, |
389 | strerror(errno)); | 399 | strerror(errno)); |
390 | } else { | 400 | } else { |
391 | if (channel_close_fd(&c->rfd) < 0) | 401 | if (channel_close_fd(ssh, &c->rfd) < 0) |
392 | logit("channel %d: chan_shutdown_read: " | 402 | logit("channel %d: chan_shutdown_read: " |
393 | "close() failed for fd %d: %.100s", | 403 | "close() failed for fd %d: %.100s", |
394 | c->self, c->rfd, strerror(errno)); | 404 | c->self, c->rfd, strerror(errno)); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.c,v 1.263 2017/07/23 23:37:02 djm Exp $ */ | 1 | /* $OpenBSD: packet.c,v 1.264 2017/09/12 06:32:07 djm 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 |
@@ -2090,35 +2090,6 @@ ssh_packet_get_maxsize(struct ssh *ssh) | |||
2090 | return ssh->state->max_packet_size; | 2090 | return ssh->state->max_packet_size; |
2091 | } | 2091 | } |
2092 | 2092 | ||
2093 | /* | ||
2094 | * 9.2. Ignored Data Message | ||
2095 | * | ||
2096 | * byte SSH_MSG_IGNORE | ||
2097 | * string data | ||
2098 | * | ||
2099 | * All implementations MUST understand (and ignore) this message at any | ||
2100 | * time (after receiving the protocol version). No implementation is | ||
2101 | * required to send them. This message can be used as an additional | ||
2102 | * protection measure against advanced traffic analysis techniques. | ||
2103 | */ | ||
2104 | void | ||
2105 | ssh_packet_send_ignore(struct ssh *ssh, int nbytes) | ||
2106 | { | ||
2107 | u_int32_t rnd = 0; | ||
2108 | int r, i; | ||
2109 | |||
2110 | if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || | ||
2111 | (r = sshpkt_put_u32(ssh, nbytes)) != 0) | ||
2112 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2113 | for (i = 0; i < nbytes; i++) { | ||
2114 | if (i % 4 == 0) | ||
2115 | rnd = arc4random(); | ||
2116 | if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) | ||
2117 | fatal("%s: %s", __func__, ssh_err(r)); | ||
2118 | rnd >>= 8; | ||
2119 | } | ||
2120 | } | ||
2121 | |||
2122 | void | 2093 | void |
2123 | ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds) | 2094 | ssh_packet_set_rekey_limits(struct ssh *ssh, u_int64_t bytes, u_int32_t seconds) |
2124 | { | 2095 | { |
@@ -2539,6 +2510,12 @@ sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) | |||
2539 | } | 2510 | } |
2540 | 2511 | ||
2541 | int | 2512 | int |
2513 | sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp) | ||
2514 | { | ||
2515 | return sshbuf_peek_string_direct(ssh->state->incoming_packet, valp, lenp); | ||
2516 | } | ||
2517 | |||
2518 | int | ||
2542 | sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) | 2519 | sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp) |
2543 | { | 2520 | { |
2544 | return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp); | 2521 | return sshbuf_get_cstring(ssh->state->incoming_packet, valp, lenp); |
@@ -2621,6 +2598,37 @@ ssh_packet_send_mux(struct ssh *ssh) | |||
2621 | return 0; | 2598 | return 0; |
2622 | } | 2599 | } |
2623 | 2600 | ||
2601 | /* | ||
2602 | * 9.2. Ignored Data Message | ||
2603 | * | ||
2604 | * byte SSH_MSG_IGNORE | ||
2605 | * string data | ||
2606 | * | ||
2607 | * All implementations MUST understand (and ignore) this message at any | ||
2608 | * time (after receiving the protocol version). No implementation is | ||
2609 | * required to send them. This message can be used as an additional | ||
2610 | * protection measure against advanced traffic analysis techniques. | ||
2611 | */ | ||
2612 | int | ||
2613 | sshpkt_msg_ignore(struct ssh *ssh, u_int nbytes) | ||
2614 | { | ||
2615 | u_int32_t rnd = 0; | ||
2616 | int r; | ||
2617 | u_int i; | ||
2618 | |||
2619 | if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || | ||
2620 | (r = sshpkt_put_u32(ssh, nbytes)) != 0) | ||
2621 | return r; | ||
2622 | for (i = 0; i < nbytes; i++) { | ||
2623 | if (i % 4 == 0) | ||
2624 | rnd = arc4random(); | ||
2625 | if ((r = sshpkt_put_u8(ssh, (u_char)rnd & 0xff)) != 0) | ||
2626 | return r; | ||
2627 | rnd >>= 8; | ||
2628 | } | ||
2629 | return 0; | ||
2630 | } | ||
2631 | |||
2624 | /* send it */ | 2632 | /* send it */ |
2625 | 2633 | ||
2626 | int | 2634 | int |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: packet.h,v 1.81 2017/05/31 08:09:45 markus Exp $ */ | 1 | /* $OpenBSD: packet.h,v 1.82 2017/09/12 06:32:07 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -80,6 +80,9 @@ struct ssh { | |||
80 | /* Client/Server authentication context */ | 80 | /* Client/Server authentication context */ |
81 | void *authctxt; | 81 | void *authctxt; |
82 | 82 | ||
83 | /* Channels context */ | ||
84 | struct ssh_channels *chanctxt; | ||
85 | |||
83 | /* APP data */ | 86 | /* APP data */ |
84 | void *app_data; | 87 | void *app_data; |
85 | }; | 88 | }; |
@@ -143,7 +146,6 @@ int ssh_packet_not_very_much_data_to_write(struct ssh *); | |||
143 | 146 | ||
144 | int ssh_packet_connection_is_on_socket(struct ssh *); | 147 | int ssh_packet_connection_is_on_socket(struct ssh *); |
145 | int ssh_packet_remaining(struct ssh *); | 148 | int ssh_packet_remaining(struct ssh *); |
146 | void ssh_packet_send_ignore(struct ssh *, int); | ||
147 | 149 | ||
148 | void tty_make_modes(int, struct termios *); | 150 | void tty_make_modes(int, struct termios *); |
149 | void tty_parse_modes(int, int *); | 151 | void tty_parse_modes(int, int *); |
@@ -174,6 +176,7 @@ int sshpkt_disconnect(struct ssh *, const char *fmt, ...) | |||
174 | __attribute__((format(printf, 2, 3))); | 176 | __attribute__((format(printf, 2, 3))); |
175 | int sshpkt_add_padding(struct ssh *, u_char); | 177 | int sshpkt_add_padding(struct ssh *, u_char); |
176 | void sshpkt_fatal(struct ssh *ssh, const char *tag, int r); | 178 | void sshpkt_fatal(struct ssh *ssh, const char *tag, int r); |
179 | int sshpkt_msg_ignore(struct ssh *, u_int); | ||
177 | 180 | ||
178 | int sshpkt_put(struct ssh *ssh, const void *v, size_t len); | 181 | int sshpkt_put(struct ssh *ssh, const void *v, size_t len); |
179 | int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b); | 182 | int sshpkt_putb(struct ssh *ssh, const struct sshbuf *b); |
@@ -192,6 +195,7 @@ int sshpkt_get_u32(struct ssh *ssh, u_int32_t *valp); | |||
192 | int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp); | 195 | int sshpkt_get_u64(struct ssh *ssh, u_int64_t *valp); |
193 | int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp); | 196 | int sshpkt_get_string(struct ssh *ssh, u_char **valp, size_t *lenp); |
194 | int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); | 197 | int sshpkt_get_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); |
198 | int sshpkt_peek_string_direct(struct ssh *ssh, const u_char **valp, size_t *lenp); | ||
195 | int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp); | 199 | int sshpkt_get_cstring(struct ssh *ssh, char **valp, size_t *lenp); |
196 | int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g); | 200 | int sshpkt_get_ec(struct ssh *ssh, EC_POINT *v, const EC_GROUP *g); |
197 | int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v); | 201 | int sshpkt_get_bignum2(struct ssh *ssh, BIGNUM *v); |
diff --git a/servconf.c b/servconf.c index ed1fc71cf..e0e43c3dd 100644 --- a/servconf.c +++ b/servconf.c | |||
@@ -1,5 +1,5 @@ | |||
1 | 1 | ||
2 | /* $OpenBSD: servconf.c,v 1.309 2017/06/24 06:34:38 djm Exp $ */ | 2 | /* $OpenBSD: servconf.c,v 1.310 2017/09/12 06:32:07 djm Exp $ */ |
3 | /* | 3 | /* |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
5 | * All rights reserved | 5 | * All rights reserved |
@@ -149,7 +149,7 @@ initialize_server_options(ServerOptions *options) | |||
149 | options->num_authkeys_files = 0; | 149 | options->num_authkeys_files = 0; |
150 | options->num_accept_env = 0; | 150 | options->num_accept_env = 0; |
151 | options->permit_tun = -1; | 151 | options->permit_tun = -1; |
152 | options->num_permitted_opens = -1; | 152 | options->permitted_opens = NULL; |
153 | options->adm_forced_command = NULL; | 153 | options->adm_forced_command = NULL; |
154 | options->chroot_directory = NULL; | 154 | options->chroot_directory = NULL; |
155 | options->authorized_keys_command = NULL; | 155 | options->authorized_keys_command = NULL; |
@@ -697,6 +697,44 @@ process_queued_listen_addrs(ServerOptions *options) | |||
697 | options->num_queued_listens = 0; | 697 | options->num_queued_listens = 0; |
698 | } | 698 | } |
699 | 699 | ||
700 | /* | ||
701 | * Inform channels layer of permitopen options from configuration. | ||
702 | */ | ||
703 | void | ||
704 | process_permitopen(struct ssh *ssh, ServerOptions *options) | ||
705 | { | ||
706 | u_int i; | ||
707 | int port; | ||
708 | char *host, *arg, *oarg; | ||
709 | |||
710 | channel_clear_adm_permitted_opens(ssh); | ||
711 | if (options->num_permitted_opens == 0) | ||
712 | return; /* permit any */ | ||
713 | |||
714 | /* handle keywords: "any" / "none" */ | ||
715 | if (options->num_permitted_opens == 1 && | ||
716 | strcmp(options->permitted_opens[0], "any") == 0) | ||
717 | return; | ||
718 | if (options->num_permitted_opens == 1 && | ||
719 | strcmp(options->permitted_opens[0], "none") == 0) { | ||
720 | channel_disable_adm_local_opens(ssh); | ||
721 | return; | ||
722 | } | ||
723 | /* Otherwise treat it as a list of permitted host:port */ | ||
724 | for (i = 0; i < options->num_permitted_opens; i++) { | ||
725 | oarg = arg = xstrdup(options->permitted_opens[i]); | ||
726 | host = hpdelim(&arg); | ||
727 | if (host == NULL) | ||
728 | fatal("%s: missing host in PermitOpen", __func__); | ||
729 | host = cleanhostname(host); | ||
730 | if (arg == NULL || ((port = permitopen_port(arg)) < 0)) | ||
731 | fatal("%s: bad port number in PermitOpen", __func__); | ||
732 | /* Send it to channels layer */ | ||
733 | channel_add_adm_permitted_opens(ssh, host, port); | ||
734 | free(oarg); | ||
735 | } | ||
736 | } | ||
737 | |||
700 | struct connection_info * | 738 | struct connection_info * |
701 | get_connection_info(int populate, int use_dns) | 739 | get_connection_info(int populate, int use_dns) |
702 | { | 740 | { |
@@ -954,7 +992,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
954 | const char *filename, int linenum, int *activep, | 992 | const char *filename, int linenum, int *activep, |
955 | struct connection_info *connectinfo) | 993 | struct connection_info *connectinfo) |
956 | { | 994 | { |
957 | char *cp, **charptr, *arg, *p; | 995 | char *cp, **charptr, *arg, *arg2, *p; |
958 | int cmdline = 0, *intptr, value, value2, n, port; | 996 | int cmdline = 0, *intptr, value, value2, n, port; |
959 | SyslogFacility *log_facility_ptr; | 997 | SyslogFacility *log_facility_ptr; |
960 | LogLevel *log_level_ptr; | 998 | LogLevel *log_level_ptr; |
@@ -1625,24 +1663,17 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1625 | if (!arg || *arg == '\0') | 1663 | if (!arg || *arg == '\0') |
1626 | fatal("%s line %d: missing PermitOpen specification", | 1664 | fatal("%s line %d: missing PermitOpen specification", |
1627 | filename, linenum); | 1665 | filename, linenum); |
1628 | n = options->num_permitted_opens; /* modified later */ | 1666 | i = options->num_permitted_opens; /* modified later */ |
1629 | if (strcmp(arg, "any") == 0) { | 1667 | if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { |
1630 | if (*activep && n == -1) { | 1668 | if (*activep && i == 0) |
1631 | channel_clear_adm_permitted_opens(); | ||
1632 | options->num_permitted_opens = 0; | ||
1633 | } | ||
1634 | break; | ||
1635 | } | ||
1636 | if (strcmp(arg, "none") == 0) { | ||
1637 | if (*activep && n == -1) { | ||
1638 | options->num_permitted_opens = 1; | 1669 | options->num_permitted_opens = 1; |
1639 | channel_disable_adm_local_opens(); | 1670 | options->permitted_opens = xcalloc(1, |
1640 | } | 1671 | sizeof(*options->permitted_opens)); |
1672 | options->permitted_opens[0] = xstrdup(arg); | ||
1641 | break; | 1673 | break; |
1642 | } | 1674 | } |
1643 | if (*activep && n == -1) | ||
1644 | channel_clear_adm_permitted_opens(); | ||
1645 | for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { | 1675 | for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { |
1676 | arg2 = xstrdup(arg); | ||
1646 | p = hpdelim(&arg); | 1677 | p = hpdelim(&arg); |
1647 | if (p == NULL) | 1678 | if (p == NULL) |
1648 | fatal("%s line %d: missing host in PermitOpen", | 1679 | fatal("%s line %d: missing host in PermitOpen", |
@@ -1651,9 +1682,16 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1651 | if (arg == NULL || ((port = permitopen_port(arg)) < 0)) | 1682 | if (arg == NULL || ((port = permitopen_port(arg)) < 0)) |
1652 | fatal("%s line %d: bad port number in " | 1683 | fatal("%s line %d: bad port number in " |
1653 | "PermitOpen", filename, linenum); | 1684 | "PermitOpen", filename, linenum); |
1654 | if (*activep && n == -1) | 1685 | if (*activep && i == 0) { |
1655 | options->num_permitted_opens = | 1686 | options->permitted_opens = xrecallocarray( |
1656 | channel_add_adm_permitted_opens(p, port); | 1687 | options->permitted_opens, |
1688 | options->num_permitted_opens, | ||
1689 | options->num_permitted_opens + 1, | ||
1690 | sizeof(*options->permitted_opens)); | ||
1691 | i = options->num_permitted_opens++; | ||
1692 | options->permitted_opens[i] = arg2; | ||
1693 | } else | ||
1694 | free(arg2); | ||
1657 | } | 1695 | } |
1658 | break; | 1696 | break; |
1659 | 1697 | ||
@@ -2352,5 +2390,12 @@ dump_config(ServerOptions *o) | |||
2352 | printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, | 2390 | printf("rekeylimit %llu %d\n", (unsigned long long)o->rekey_limit, |
2353 | o->rekey_interval); | 2391 | o->rekey_interval); |
2354 | 2392 | ||
2355 | channel_print_adm_permitted_opens(); | 2393 | printf("permitopen"); |
2394 | if (o->num_permitted_opens == 0) | ||
2395 | printf(" any"); | ||
2396 | else { | ||
2397 | for (i = 0; i < o->num_permitted_opens; i++) | ||
2398 | printf(" %s", o->permitted_opens[i]); | ||
2399 | } | ||
2400 | printf("\n"); | ||
2356 | } | 2401 | } |
diff --git a/servconf.h b/servconf.h index c2848a765..ffcbc3319 100644 --- a/servconf.h +++ b/servconf.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: servconf.h,v 1.124 2017/06/24 06:34:38 djm Exp $ */ | 1 | /* $OpenBSD: servconf.h,v 1.125 2017/09/12 06:32:07 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -48,12 +48,19 @@ | |||
48 | #define FORWARD_LOCAL (1<<1) | 48 | #define FORWARD_LOCAL (1<<1) |
49 | #define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL) | 49 | #define FORWARD_ALLOW (FORWARD_REMOTE|FORWARD_LOCAL) |
50 | 50 | ||
51 | /* PermitOpen */ | ||
52 | #define PERMITOPEN_ANY 0 | ||
53 | #define PERMITOPEN_NONE -2 | ||
54 | |||
51 | #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ | 55 | #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ |
52 | #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ | 56 | #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ |
53 | 57 | ||
54 | /* Magic name for internal sftp-server */ | 58 | /* Magic name for internal sftp-server */ |
55 | #define INTERNAL_SFTP_NAME "internal-sftp" | 59 | #define INTERNAL_SFTP_NAME "internal-sftp" |
56 | 60 | ||
61 | struct ssh; | ||
62 | struct fwd_perm_list; | ||
63 | |||
57 | typedef struct { | 64 | typedef struct { |
58 | u_int num_ports; | 65 | u_int num_ports; |
59 | u_int ports_from_cmdline; | 66 | u_int ports_from_cmdline; |
@@ -169,7 +176,8 @@ typedef struct { | |||
169 | 176 | ||
170 | int permit_tun; | 177 | int permit_tun; |
171 | 178 | ||
172 | int num_permitted_opens; | 179 | char **permitted_opens; |
180 | u_int num_permitted_opens; /* May also be one of PERMITOPEN_* */ | ||
173 | 181 | ||
174 | char *chroot_directory; | 182 | char *chroot_directory; |
175 | char *revoked_keys_file; | 183 | char *revoked_keys_file; |
@@ -229,6 +237,7 @@ struct connection_info { | |||
229 | M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \ | 237 | M_CP_STRARRAYOPT(deny_groups, num_deny_groups); \ |
230 | M_CP_STRARRAYOPT(accept_env, num_accept_env); \ | 238 | M_CP_STRARRAYOPT(accept_env, num_accept_env); \ |
231 | M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ | 239 | M_CP_STRARRAYOPT(auth_methods, num_auth_methods); \ |
240 | M_CP_STRARRAYOPT(permitted_opens, num_permitted_opens); \ | ||
232 | } while (0) | 241 | } while (0) |
233 | 242 | ||
234 | struct connection_info *get_connection_info(int, int); | 243 | struct connection_info *get_connection_info(int, int); |
@@ -236,6 +245,7 @@ void initialize_server_options(ServerOptions *); | |||
236 | void fill_default_server_options(ServerOptions *); | 245 | void fill_default_server_options(ServerOptions *); |
237 | int process_server_config_line(ServerOptions *, char *, const char *, int, | 246 | int process_server_config_line(ServerOptions *, char *, const char *, int, |
238 | int *, struct connection_info *); | 247 | int *, struct connection_info *); |
248 | void process_permitopen(struct ssh *ssh, ServerOptions *options); | ||
239 | void load_server_config(const char *, Buffer *); | 249 | void load_server_config(const char *, Buffer *); |
240 | void parse_server_config(ServerOptions *, const char *, Buffer *, | 250 | void parse_server_config(ServerOptions *, const char *, Buffer *, |
241 | struct connection_info *); | 251 | struct connection_info *); |
diff --git a/serverloop.c b/serverloop.c index bc56709b1..567159410 100644 --- a/serverloop.c +++ b/serverloop.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: serverloop.c,v 1.196 2017/08/30 03:59:08 djm Exp $ */ | 1 | /* $OpenBSD: serverloop.c,v 1.197 2017/09/12 06:32:07 djm 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 |
@@ -165,7 +165,7 @@ sigterm_handler(int sig) | |||
165 | } | 165 | } |
166 | 166 | ||
167 | static void | 167 | static void |
168 | client_alive_check(void) | 168 | client_alive_check(struct ssh *ssh) |
169 | { | 169 | { |
170 | int channel_id; | 170 | int channel_id; |
171 | 171 | ||
@@ -179,12 +179,13 @@ client_alive_check(void) | |||
179 | * send a bogus global/channel request with "wantreply", | 179 | * send a bogus global/channel request with "wantreply", |
180 | * we should get back a failure | 180 | * we should get back a failure |
181 | */ | 181 | */ |
182 | if ((channel_id = channel_find_open()) == -1) { | 182 | if ((channel_id = channel_find_open(ssh)) == -1) { |
183 | packet_start(SSH2_MSG_GLOBAL_REQUEST); | 183 | packet_start(SSH2_MSG_GLOBAL_REQUEST); |
184 | packet_put_cstring("keepalive@openssh.com"); | 184 | packet_put_cstring("keepalive@openssh.com"); |
185 | packet_put_char(1); /* boolean: want reply */ | 185 | packet_put_char(1); /* boolean: want reply */ |
186 | } else { | 186 | } else { |
187 | channel_request_start(channel_id, "keepalive@openssh.com", 1); | 187 | channel_request_start(ssh, channel_id, |
188 | "keepalive@openssh.com", 1); | ||
188 | } | 189 | } |
189 | packet_send(); | 190 | packet_send(); |
190 | } | 191 | } |
@@ -196,7 +197,8 @@ client_alive_check(void) | |||
196 | * for the duration of the wait (0 = infinite). | 197 | * for the duration of the wait (0 = infinite). |
197 | */ | 198 | */ |
198 | static void | 199 | static void |
199 | wait_until_can_do_something(int connection_in, int connection_out, | 200 | wait_until_can_do_something(struct ssh *ssh, |
201 | int connection_in, int connection_out, | ||
200 | fd_set **readsetp, fd_set **writesetp, int *maxfdp, | 202 | fd_set **readsetp, fd_set **writesetp, int *maxfdp, |
201 | u_int *nallocp, u_int64_t max_time_ms) | 203 | u_int *nallocp, u_int64_t max_time_ms) |
202 | { | 204 | { |
@@ -207,7 +209,7 @@ wait_until_can_do_something(int connection_in, int connection_out, | |||
207 | static time_t last_client_time; | 209 | static time_t last_client_time; |
208 | 210 | ||
209 | /* Allocate and update select() masks for channel descriptors. */ | 211 | /* Allocate and update select() masks for channel descriptors. */ |
210 | channel_prepare_select(active_state, readsetp, writesetp, maxfdp, | 212 | channel_prepare_select(ssh, readsetp, writesetp, maxfdp, |
211 | nallocp, &minwait_secs); | 213 | nallocp, &minwait_secs); |
212 | 214 | ||
213 | /* XXX need proper deadline system for rekey/client alive */ | 215 | /* XXX need proper deadline system for rekey/client alive */ |
@@ -273,12 +275,12 @@ wait_until_can_do_something(int connection_in, int connection_out, | |||
273 | time_t now = monotime(); | 275 | time_t now = monotime(); |
274 | 276 | ||
275 | if (ret == 0) { /* timeout */ | 277 | if (ret == 0) { /* timeout */ |
276 | client_alive_check(); | 278 | client_alive_check(ssh); |
277 | } else if (FD_ISSET(connection_in, *readsetp)) { | 279 | } else if (FD_ISSET(connection_in, *readsetp)) { |
278 | last_client_time = now; | 280 | last_client_time = now; |
279 | } else if (last_client_time != 0 && last_client_time + | 281 | } else if (last_client_time != 0 && last_client_time + |
280 | options.client_alive_interval <= now) { | 282 | options.client_alive_interval <= now) { |
281 | client_alive_check(); | 283 | client_alive_check(ssh); |
282 | last_client_time = now; | 284 | last_client_time = now; |
283 | } | 285 | } |
284 | } | 286 | } |
@@ -291,9 +293,8 @@ wait_until_can_do_something(int connection_in, int connection_out, | |||
291 | * in buffers and processed later. | 293 | * in buffers and processed later. |
292 | */ | 294 | */ |
293 | static int | 295 | static int |
294 | process_input(fd_set *readset, int connection_in) | 296 | process_input(struct ssh *ssh, fd_set *readset, int connection_in) |
295 | { | 297 | { |
296 | struct ssh *ssh = active_state; /* XXX */ | ||
297 | int len; | 298 | int len; |
298 | char buf[16384]; | 299 | char buf[16384]; |
299 | 300 | ||
@@ -333,13 +334,13 @@ process_output(fd_set *writeset, int connection_out) | |||
333 | } | 334 | } |
334 | 335 | ||
335 | static void | 336 | static void |
336 | process_buffered_input_packets(void) | 337 | process_buffered_input_packets(struct ssh *ssh) |
337 | { | 338 | { |
338 | ssh_dispatch_run_fatal(active_state, DISPATCH_NONBLOCK, NULL); | 339 | ssh_dispatch_run_fatal(ssh, DISPATCH_NONBLOCK, NULL); |
339 | } | 340 | } |
340 | 341 | ||
341 | static void | 342 | static void |
342 | collect_children(void) | 343 | collect_children(struct ssh *ssh) |
343 | { | 344 | { |
344 | pid_t pid; | 345 | pid_t pid; |
345 | sigset_t oset, nset; | 346 | sigset_t oset, nset; |
@@ -354,14 +355,14 @@ collect_children(void) | |||
354 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || | 355 | while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || |
355 | (pid < 0 && errno == EINTR)) | 356 | (pid < 0 && errno == EINTR)) |
356 | if (pid > 0) | 357 | if (pid > 0) |
357 | session_close_by_pid(pid, status); | 358 | session_close_by_pid(ssh, pid, status); |
358 | child_terminated = 0; | 359 | child_terminated = 0; |
359 | } | 360 | } |
360 | sigprocmask(SIG_SETMASK, &oset, NULL); | 361 | sigprocmask(SIG_SETMASK, &oset, NULL); |
361 | } | 362 | } |
362 | 363 | ||
363 | void | 364 | void |
364 | server_loop2(Authctxt *authctxt) | 365 | server_loop2(struct ssh *ssh, Authctxt *authctxt) |
365 | { | 366 | { |
366 | fd_set *readset = NULL, *writeset = NULL; | 367 | fd_set *readset = NULL, *writeset = NULL; |
367 | int max_fd; | 368 | int max_fd; |
@@ -389,18 +390,17 @@ server_loop2(Authctxt *authctxt) | |||
389 | server_init_dispatch(); | 390 | server_init_dispatch(); |
390 | 391 | ||
391 | for (;;) { | 392 | for (;;) { |
392 | process_buffered_input_packets(); | 393 | process_buffered_input_packets(ssh); |
393 | 394 | ||
394 | if (!ssh_packet_is_rekeying(active_state) && | 395 | if (!ssh_packet_is_rekeying(ssh) && |
395 | packet_not_very_much_data_to_write()) | 396 | packet_not_very_much_data_to_write()) |
396 | channel_output_poll(); | 397 | channel_output_poll(ssh); |
397 | if (options.rekey_interval > 0 && | 398 | if (options.rekey_interval > 0 && !ssh_packet_is_rekeying(ssh)) |
398 | !ssh_packet_is_rekeying(active_state)) | ||
399 | rekey_timeout_ms = packet_get_rekey_timeout() * 1000; | 399 | rekey_timeout_ms = packet_get_rekey_timeout() * 1000; |
400 | else | 400 | else |
401 | rekey_timeout_ms = 0; | 401 | rekey_timeout_ms = 0; |
402 | 402 | ||
403 | wait_until_can_do_something(connection_in, connection_out, | 403 | wait_until_can_do_something(ssh, connection_in, connection_out, |
404 | &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); | 404 | &readset, &writeset, &max_fd, &nalloc, rekey_timeout_ms); |
405 | 405 | ||
406 | if (received_sigterm) { | 406 | if (received_sigterm) { |
@@ -409,23 +409,23 @@ server_loop2(Authctxt *authctxt) | |||
409 | cleanup_exit(255); | 409 | cleanup_exit(255); |
410 | } | 410 | } |
411 | 411 | ||
412 | collect_children(); | 412 | collect_children(ssh); |
413 | if (!ssh_packet_is_rekeying(active_state)) | 413 | if (!ssh_packet_is_rekeying(ssh)) |
414 | channel_after_select(active_state, readset, writeset); | 414 | channel_after_select(ssh, readset, writeset); |
415 | if (process_input(readset, connection_in) < 0) | 415 | if (process_input(ssh, readset, connection_in) < 0) |
416 | break; | 416 | break; |
417 | process_output(writeset, connection_out); | 417 | process_output(writeset, connection_out); |
418 | } | 418 | } |
419 | collect_children(); | 419 | collect_children(ssh); |
420 | 420 | ||
421 | free(readset); | 421 | free(readset); |
422 | free(writeset); | 422 | free(writeset); |
423 | 423 | ||
424 | /* free all channels, no more reads and writes */ | 424 | /* free all channels, no more reads and writes */ |
425 | channel_free_all(); | 425 | channel_free_all(ssh); |
426 | 426 | ||
427 | /* free remaining sessions, e.g. remove wtmp entries */ | 427 | /* free remaining sessions, e.g. remove wtmp entries */ |
428 | session_destroy_all(NULL); | 428 | session_destroy_all(ssh, NULL); |
429 | } | 429 | } |
430 | 430 | ||
431 | static int | 431 | static int |
@@ -442,7 +442,7 @@ server_input_keep_alive(int type, u_int32_t seq, struct ssh *ssh) | |||
442 | } | 442 | } |
443 | 443 | ||
444 | static Channel * | 444 | static Channel * |
445 | server_request_direct_tcpip(int *reason, const char **errmsg) | 445 | server_request_direct_tcpip(struct ssh *ssh, int *reason, const char **errmsg) |
446 | { | 446 | { |
447 | Channel *c = NULL; | 447 | Channel *c = NULL; |
448 | char *target, *originator; | 448 | char *target, *originator; |
@@ -460,7 +460,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg) | |||
460 | /* XXX fine grained permissions */ | 460 | /* XXX fine grained permissions */ |
461 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && | 461 | if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && |
462 | !no_port_forwarding_flag && !options.disable_forwarding) { | 462 | !no_port_forwarding_flag && !options.disable_forwarding) { |
463 | c = channel_connect_to_port(target, target_port, | 463 | c = channel_connect_to_port(ssh, target, target_port, |
464 | "direct-tcpip", "direct-tcpip", reason, errmsg); | 464 | "direct-tcpip", "direct-tcpip", reason, errmsg); |
465 | } else { | 465 | } else { |
466 | logit("refused local port forward: " | 466 | logit("refused local port forward: " |
@@ -477,7 +477,7 @@ server_request_direct_tcpip(int *reason, const char **errmsg) | |||
477 | } | 477 | } |
478 | 478 | ||
479 | static Channel * | 479 | static Channel * |
480 | server_request_direct_streamlocal(void) | 480 | server_request_direct_streamlocal(struct ssh *ssh) |
481 | { | 481 | { |
482 | Channel *c = NULL; | 482 | Channel *c = NULL; |
483 | char *target, *originator; | 483 | char *target, *originator; |
@@ -499,7 +499,7 @@ server_request_direct_streamlocal(void) | |||
499 | if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && | 499 | if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 && |
500 | !no_port_forwarding_flag && !options.disable_forwarding && | 500 | !no_port_forwarding_flag && !options.disable_forwarding && |
501 | (pw->pw_uid == 0 || use_privsep)) { | 501 | (pw->pw_uid == 0 || use_privsep)) { |
502 | c = channel_connect_to_path(target, | 502 | c = channel_connect_to_path(ssh, target, |
503 | "direct-streamlocal@openssh.com", "direct-streamlocal"); | 503 | "direct-streamlocal@openssh.com", "direct-streamlocal"); |
504 | } else { | 504 | } else { |
505 | logit("refused streamlocal port forward: " | 505 | logit("refused streamlocal port forward: " |
@@ -514,7 +514,7 @@ server_request_direct_streamlocal(void) | |||
514 | } | 514 | } |
515 | 515 | ||
516 | static Channel * | 516 | static Channel * |
517 | server_request_tun(void) | 517 | server_request_tun(struct ssh *ssh) |
518 | { | 518 | { |
519 | Channel *c = NULL; | 519 | Channel *c = NULL; |
520 | int mode, tun; | 520 | int mode, tun; |
@@ -544,7 +544,7 @@ server_request_tun(void) | |||
544 | sock = tun_open(tun, mode); | 544 | sock = tun_open(tun, mode); |
545 | if (sock < 0) | 545 | if (sock < 0) |
546 | goto done; | 546 | goto done; |
547 | c = channel_new("tun", SSH_CHANNEL_OPEN, sock, sock, -1, | 547 | c = channel_new(ssh, "tun", SSH_CHANNEL_OPEN, sock, sock, -1, |
548 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); | 548 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, "tun", 1); |
549 | c->datagram = 1; | 549 | c->datagram = 1; |
550 | #if defined(SSH_TUN_FILTER) | 550 | #if defined(SSH_TUN_FILTER) |
@@ -560,7 +560,7 @@ server_request_tun(void) | |||
560 | } | 560 | } |
561 | 561 | ||
562 | static Channel * | 562 | static Channel * |
563 | server_request_session(void) | 563 | server_request_session(struct ssh *ssh) |
564 | { | 564 | { |
565 | Channel *c; | 565 | Channel *c; |
566 | 566 | ||
@@ -578,15 +578,15 @@ server_request_session(void) | |||
578 | * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all | 578 | * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all |
579 | * CHANNEL_REQUEST messages is registered. | 579 | * CHANNEL_REQUEST messages is registered. |
580 | */ | 580 | */ |
581 | c = channel_new("session", SSH_CHANNEL_LARVAL, | 581 | c = channel_new(ssh, "session", SSH_CHANNEL_LARVAL, |
582 | -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, | 582 | -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, |
583 | 0, "server-session", 1); | 583 | 0, "server-session", 1); |
584 | if (session_open(the_authctxt, c->self) != 1) { | 584 | if (session_open(the_authctxt, c->self) != 1) { |
585 | debug("session open failed, free channel %d", c->self); | 585 | debug("session open failed, free channel %d", c->self); |
586 | channel_free(c); | 586 | channel_free(ssh, c); |
587 | return NULL; | 587 | return NULL; |
588 | } | 588 | } |
589 | channel_register_cleanup(c->self, session_close_by_channel, 0); | 589 | channel_register_cleanup(ssh, c->self, session_close_by_channel, 0); |
590 | return c; | 590 | return c; |
591 | } | 591 | } |
592 | 592 | ||
@@ -608,13 +608,13 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) | |||
608 | ctype, rchan, rwindow, rmaxpack); | 608 | ctype, rchan, rwindow, rmaxpack); |
609 | 609 | ||
610 | if (strcmp(ctype, "session") == 0) { | 610 | if (strcmp(ctype, "session") == 0) { |
611 | c = server_request_session(); | 611 | c = server_request_session(ssh); |
612 | } else if (strcmp(ctype, "direct-tcpip") == 0) { | 612 | } else if (strcmp(ctype, "direct-tcpip") == 0) { |
613 | c = server_request_direct_tcpip(&reason, &errmsg); | 613 | c = server_request_direct_tcpip(ssh, &reason, &errmsg); |
614 | } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { | 614 | } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) { |
615 | c = server_request_direct_streamlocal(); | 615 | c = server_request_direct_streamlocal(ssh); |
616 | } else if (strcmp(ctype, "tun@openssh.com") == 0) { | 616 | } else if (strcmp(ctype, "tun@openssh.com") == 0) { |
617 | c = server_request_tun(); | 617 | c = server_request_tun(ssh); |
618 | } | 618 | } |
619 | if (c != NULL) { | 619 | if (c != NULL) { |
620 | debug("server_input_channel_open: confirm %s", ctype); | 620 | debug("server_input_channel_open: confirm %s", ctype); |
@@ -645,9 +645,8 @@ server_input_channel_open(int type, u_int32_t seq, struct ssh *ssh) | |||
645 | } | 645 | } |
646 | 646 | ||
647 | static int | 647 | static int |
648 | server_input_hostkeys_prove(struct sshbuf **respp) | 648 | server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) |
649 | { | 649 | { |
650 | struct ssh *ssh = active_state; /* XXX */ | ||
651 | struct sshbuf *resp = NULL; | 650 | struct sshbuf *resp = NULL; |
652 | struct sshbuf *sigbuf = NULL; | 651 | struct sshbuf *sigbuf = NULL; |
653 | struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; | 652 | struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; |
@@ -750,7 +749,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | |||
750 | packet_send_debug("Server has disabled port forwarding."); | 749 | packet_send_debug("Server has disabled port forwarding."); |
751 | } else { | 750 | } else { |
752 | /* Start listening on the port */ | 751 | /* Start listening on the port */ |
753 | success = channel_setup_remote_fwd_listener(&fwd, | 752 | success = channel_setup_remote_fwd_listener(ssh, &fwd, |
754 | &allocated_listen_port, &options.fwd_opts); | 753 | &allocated_listen_port, &options.fwd_opts); |
755 | } | 754 | } |
756 | free(fwd.listen_host); | 755 | free(fwd.listen_host); |
@@ -768,7 +767,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | |||
768 | debug("%s: cancel-tcpip-forward addr %s port %d", __func__, | 767 | debug("%s: cancel-tcpip-forward addr %s port %d", __func__, |
769 | fwd.listen_host, fwd.listen_port); | 768 | fwd.listen_host, fwd.listen_port); |
770 | 769 | ||
771 | success = channel_cancel_rport_listener(&fwd); | 770 | success = channel_cancel_rport_listener(ssh, &fwd); |
772 | free(fwd.listen_host); | 771 | free(fwd.listen_host); |
773 | } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { | 772 | } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) { |
774 | struct Forward fwd; | 773 | struct Forward fwd; |
@@ -787,7 +786,7 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | |||
787 | "streamlocal forwarding."); | 786 | "streamlocal forwarding."); |
788 | } else { | 787 | } else { |
789 | /* Start listening on the socket */ | 788 | /* Start listening on the socket */ |
790 | success = channel_setup_remote_fwd_listener( | 789 | success = channel_setup_remote_fwd_listener(ssh, |
791 | &fwd, NULL, &options.fwd_opts); | 790 | &fwd, NULL, &options.fwd_opts); |
792 | } | 791 | } |
793 | free(fwd.listen_path); | 792 | free(fwd.listen_path); |
@@ -799,19 +798,19 @@ server_input_global_request(int type, u_int32_t seq, struct ssh *ssh) | |||
799 | debug("%s: cancel-streamlocal-forward path %s", __func__, | 798 | debug("%s: cancel-streamlocal-forward path %s", __func__, |
800 | fwd.listen_path); | 799 | fwd.listen_path); |
801 | 800 | ||
802 | success = channel_cancel_rport_listener(&fwd); | 801 | success = channel_cancel_rport_listener(ssh, &fwd); |
803 | free(fwd.listen_path); | 802 | free(fwd.listen_path); |
804 | } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { | 803 | } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { |
805 | no_more_sessions = 1; | 804 | no_more_sessions = 1; |
806 | success = 1; | 805 | success = 1; |
807 | } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) { | 806 | } else if (strcmp(rtype, "hostkeys-prove-00@openssh.com") == 0) { |
808 | success = server_input_hostkeys_prove(&resp); | 807 | success = server_input_hostkeys_prove(ssh, &resp); |
809 | } | 808 | } |
810 | if (want_reply) { | 809 | if (want_reply) { |
811 | packet_start(success ? | 810 | packet_start(success ? |
812 | SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); | 811 | SSH2_MSG_REQUEST_SUCCESS : SSH2_MSG_REQUEST_FAILURE); |
813 | if (success && resp != NULL) | 812 | if (success && resp != NULL) |
814 | ssh_packet_put_raw(active_state, sshbuf_ptr(resp), | 813 | ssh_packet_put_raw(ssh, sshbuf_ptr(resp), |
815 | sshbuf_len(resp)); | 814 | sshbuf_len(resp)); |
816 | packet_send(); | 815 | packet_send(); |
817 | packet_write_wait(); | 816 | packet_write_wait(); |
@@ -835,15 +834,15 @@ server_input_channel_req(int type, u_int32_t seq, struct ssh *ssh) | |||
835 | debug("server_input_channel_req: channel %d request %s reply %d", | 834 | debug("server_input_channel_req: channel %d request %s reply %d", |
836 | id, rtype, reply); | 835 | id, rtype, reply); |
837 | 836 | ||
838 | if ((c = channel_lookup(id)) == NULL) | 837 | if ((c = channel_lookup(ssh, id)) == NULL) |
839 | packet_disconnect("server_input_channel_req: " | 838 | packet_disconnect("server_input_channel_req: " |
840 | "unknown channel %d", id); | 839 | "unknown channel %d", id); |
841 | if (!strcmp(rtype, "eow@openssh.com")) { | 840 | if (!strcmp(rtype, "eow@openssh.com")) { |
842 | packet_check_eom(); | 841 | packet_check_eom(); |
843 | chan_rcvd_eow(c); | 842 | chan_rcvd_eow(ssh, c); |
844 | } else if ((c->type == SSH_CHANNEL_LARVAL || | 843 | } else if ((c->type == SSH_CHANNEL_LARVAL || |
845 | c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) | 844 | c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) |
846 | success = session_input_channel_req(c, rtype); | 845 | success = session_input_channel_req(ssh, c, rtype); |
847 | if (reply && !(c->flags & CHAN_CLOSE_SENT)) { | 846 | if (reply && !(c->flags & CHAN_CLOSE_SENT)) { |
848 | packet_start(success ? | 847 | packet_start(success ? |
849 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); | 848 | SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); |
diff --git a/serverloop.h b/serverloop.h index d5fbda16f..fd2cf63f7 100644 --- a/serverloop.h +++ b/serverloop.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: serverloop.h,v 1.7 2016/08/13 17:47:41 markus Exp $ */ | 1 | /* $OpenBSD: serverloop.h,v 1.8 2017/09/12 06:32:07 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -21,6 +21,8 @@ | |||
21 | #ifndef SERVERLOOP_H | 21 | #ifndef SERVERLOOP_H |
22 | #define SERVERLOOP_H | 22 | #define SERVERLOOP_H |
23 | 23 | ||
24 | void server_loop2(Authctxt *); | 24 | struct ssh; |
25 | |||
26 | void server_loop2(struct ssh *, Authctxt *); | ||
25 | 27 | ||
26 | #endif | 28 | #endif |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: session.c,v 1.291 2017/08/18 05:36:45 djm Exp $ */ | 1 | /* $OpenBSD: session.c,v 1.292 2017/09/12 06:32:07 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 4 | * All rights reserved |
@@ -113,24 +113,24 @@ | |||
113 | /* func */ | 113 | /* func */ |
114 | 114 | ||
115 | Session *session_new(void); | 115 | Session *session_new(void); |
116 | void session_set_fds(Session *, int, int, int, int, int); | 116 | void session_set_fds(struct ssh *, Session *, int, int, int, int, int); |
117 | void session_pty_cleanup(Session *); | 117 | void session_pty_cleanup(Session *); |
118 | void session_proctitle(Session *); | 118 | void session_proctitle(Session *); |
119 | int session_setup_x11fwd(Session *); | 119 | int session_setup_x11fwd(struct ssh *, Session *); |
120 | int do_exec_pty(Session *, const char *); | 120 | int do_exec_pty(struct ssh *, Session *, const char *); |
121 | int do_exec_no_pty(Session *, const char *); | 121 | int do_exec_no_pty(struct ssh *, Session *, const char *); |
122 | int do_exec(Session *, const char *); | 122 | int do_exec(struct ssh *, Session *, const char *); |
123 | void do_login(Session *, const char *); | 123 | void do_login(struct ssh *, Session *, const char *); |
124 | void do_child(struct ssh *, Session *, const char *); | ||
124 | #ifdef LOGIN_NEEDS_UTMPX | 125 | #ifdef LOGIN_NEEDS_UTMPX |
125 | static void do_pre_login(Session *s); | 126 | static void do_pre_login(Session *s); |
126 | #endif | 127 | #endif |
127 | void do_child(Session *, const char *); | ||
128 | void do_motd(void); | 128 | void do_motd(void); |
129 | int check_quietlogin(Session *, const char *); | 129 | int check_quietlogin(Session *, const char *); |
130 | 130 | ||
131 | static void do_authenticated2(Authctxt *); | 131 | static void do_authenticated2(struct ssh *, Authctxt *); |
132 | 132 | ||
133 | static int session_pty_req(Session *); | 133 | static int session_pty_req(struct ssh *, Session *); |
134 | 134 | ||
135 | /* import */ | 135 | /* import */ |
136 | extern ServerOptions options; | 136 | extern ServerOptions options; |
@@ -183,7 +183,7 @@ auth_sock_cleanup_proc(struct passwd *pw) | |||
183 | } | 183 | } |
184 | 184 | ||
185 | static int | 185 | static int |
186 | auth_input_request_forwarding(struct passwd * pw) | 186 | auth_input_request_forwarding(struct ssh *ssh, struct passwd * pw) |
187 | { | 187 | { |
188 | Channel *nc; | 188 | Channel *nc; |
189 | int sock = -1; | 189 | int sock = -1; |
@@ -223,7 +223,7 @@ auth_input_request_forwarding(struct passwd * pw) | |||
223 | goto authsock_err; | 223 | goto authsock_err; |
224 | 224 | ||
225 | /* Allocate a channel for the authentication agent socket. */ | 225 | /* Allocate a channel for the authentication agent socket. */ |
226 | nc = channel_new("auth socket", | 226 | nc = channel_new(ssh, "auth socket", |
227 | SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, | 227 | SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, |
228 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, | 228 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, |
229 | 0, "auth socket", 1); | 229 | 0, "auth socket", 1); |
@@ -288,7 +288,7 @@ prepare_auth_info_file(struct passwd *pw, struct sshbuf *info) | |||
288 | } | 288 | } |
289 | 289 | ||
290 | void | 290 | void |
291 | do_authenticated(Authctxt *authctxt) | 291 | do_authenticated(struct ssh *ssh, Authctxt *authctxt) |
292 | { | 292 | { |
293 | setproctitle("%s", authctxt->pw->pw_name); | 293 | setproctitle("%s", authctxt->pw->pw_name); |
294 | 294 | ||
@@ -296,17 +296,17 @@ do_authenticated(Authctxt *authctxt) | |||
296 | /* XXX - streamlocal? */ | 296 | /* XXX - streamlocal? */ |
297 | if (no_port_forwarding_flag || options.disable_forwarding || | 297 | if (no_port_forwarding_flag || options.disable_forwarding || |
298 | (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) | 298 | (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) |
299 | channel_disable_adm_local_opens(); | 299 | channel_disable_adm_local_opens(ssh); |
300 | else | 300 | else |
301 | channel_permit_all_opens(); | 301 | channel_permit_all_opens(ssh); |
302 | 302 | ||
303 | auth_debug_send(); | 303 | auth_debug_send(); |
304 | 304 | ||
305 | prepare_auth_info_file(authctxt->pw, authctxt->session_info); | 305 | prepare_auth_info_file(authctxt->pw, authctxt->session_info); |
306 | 306 | ||
307 | do_authenticated2(authctxt); | 307 | do_authenticated2(ssh, authctxt); |
308 | 308 | ||
309 | do_cleanup(authctxt); | 309 | do_cleanup(ssh, authctxt); |
310 | } | 310 | } |
311 | 311 | ||
312 | /* Check untrusted xauth strings for metacharacters */ | 312 | /* Check untrusted xauth strings for metacharacters */ |
@@ -331,7 +331,7 @@ xauth_valid_string(const char *s) | |||
331 | * setting up file descriptors and such. | 331 | * setting up file descriptors and such. |
332 | */ | 332 | */ |
333 | int | 333 | int |
334 | do_exec_no_pty(Session *s, const char *command) | 334 | do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) |
335 | { | 335 | { |
336 | pid_t pid; | 336 | pid_t pid; |
337 | 337 | ||
@@ -456,7 +456,7 @@ do_exec_no_pty(Session *s, const char *command) | |||
456 | #endif | 456 | #endif |
457 | 457 | ||
458 | /* Do processing for the child (exec command etc). */ | 458 | /* Do processing for the child (exec command etc). */ |
459 | do_child(s, command); | 459 | do_child(ssh, s, command); |
460 | /* NOTREACHED */ | 460 | /* NOTREACHED */ |
461 | default: | 461 | default: |
462 | break; | 462 | break; |
@@ -487,7 +487,7 @@ do_exec_no_pty(Session *s, const char *command) | |||
487 | close(pout[1]); | 487 | close(pout[1]); |
488 | close(perr[1]); | 488 | close(perr[1]); |
489 | 489 | ||
490 | session_set_fds(s, pin[1], pout[0], perr[0], | 490 | session_set_fds(ssh, s, pin[1], pout[0], perr[0], |
491 | s->is_subsystem, 0); | 491 | s->is_subsystem, 0); |
492 | #else | 492 | #else |
493 | /* We are the parent. Close the child sides of the socket pairs. */ | 493 | /* We are the parent. Close the child sides of the socket pairs. */ |
@@ -511,7 +511,7 @@ do_exec_no_pty(Session *s, const char *command) | |||
511 | * lastlog, and other such operations. | 511 | * lastlog, and other such operations. |
512 | */ | 512 | */ |
513 | int | 513 | int |
514 | do_exec_pty(Session *s, const char *command) | 514 | do_exec_pty(struct ssh *ssh, Session *s, const char *command) |
515 | { | 515 | { |
516 | int fdout, ptyfd, ttyfd, ptymaster; | 516 | int fdout, ptyfd, ttyfd, ptymaster; |
517 | pid_t pid; | 517 | pid_t pid; |
@@ -580,13 +580,13 @@ do_exec_pty(Session *s, const char *command) | |||
580 | cray_init_job(s->pw); /* set up cray jid and tmpdir */ | 580 | cray_init_job(s->pw); /* set up cray jid and tmpdir */ |
581 | #endif /* _UNICOS */ | 581 | #endif /* _UNICOS */ |
582 | #ifndef HAVE_OSF_SIA | 582 | #ifndef HAVE_OSF_SIA |
583 | do_login(s, command); | 583 | do_login(ssh, s, command); |
584 | #endif | 584 | #endif |
585 | /* | 585 | /* |
586 | * Do common processing for the child, such as execing | 586 | * Do common processing for the child, such as execing |
587 | * the command. | 587 | * the command. |
588 | */ | 588 | */ |
589 | do_child(s, command); | 589 | do_child(ssh, s, command); |
590 | /* NOTREACHED */ | 590 | /* NOTREACHED */ |
591 | default: | 591 | default: |
592 | break; | 592 | break; |
@@ -608,7 +608,7 @@ do_exec_pty(Session *s, const char *command) | |||
608 | s->ptymaster = ptymaster; | 608 | s->ptymaster = ptymaster; |
609 | packet_set_interactive(1, | 609 | packet_set_interactive(1, |
610 | options.ip_qos_interactive, options.ip_qos_bulk); | 610 | options.ip_qos_interactive, options.ip_qos_bulk); |
611 | session_set_fds(s, ptyfd, fdout, -1, 1, 1); | 611 | session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1); |
612 | return 0; | 612 | return 0; |
613 | } | 613 | } |
614 | 614 | ||
@@ -646,9 +646,8 @@ do_pre_login(Session *s) | |||
646 | * to be forced, execute that instead. | 646 | * to be forced, execute that instead. |
647 | */ | 647 | */ |
648 | int | 648 | int |
649 | do_exec(Session *s, const char *command) | 649 | do_exec(struct ssh *ssh, Session *s, const char *command) |
650 | { | 650 | { |
651 | struct ssh *ssh = active_state; /* XXX */ | ||
652 | int ret; | 651 | int ret; |
653 | const char *forced = NULL, *tty = NULL; | 652 | const char *forced = NULL, *tty = NULL; |
654 | char session_type[1024]; | 653 | char session_type[1024]; |
@@ -707,9 +706,9 @@ do_exec(Session *s, const char *command) | |||
707 | } | 706 | } |
708 | #endif | 707 | #endif |
709 | if (s->ttyfd != -1) | 708 | if (s->ttyfd != -1) |
710 | ret = do_exec_pty(s, command); | 709 | ret = do_exec_pty(ssh, s, command); |
711 | else | 710 | else |
712 | ret = do_exec_no_pty(s, command); | 711 | ret = do_exec_no_pty(ssh, s, command); |
713 | 712 | ||
714 | original_command = NULL; | 713 | original_command = NULL; |
715 | 714 | ||
@@ -725,9 +724,8 @@ do_exec(Session *s, const char *command) | |||
725 | 724 | ||
726 | /* administrative, login(1)-like work */ | 725 | /* administrative, login(1)-like work */ |
727 | void | 726 | void |
728 | do_login(Session *s, const char *command) | 727 | do_login(struct ssh *ssh, Session *s, const char *command) |
729 | { | 728 | { |
730 | struct ssh *ssh = active_state; /* XXX */ | ||
731 | socklen_t fromlen; | 729 | socklen_t fromlen; |
732 | struct sockaddr_storage from; | 730 | struct sockaddr_storage from; |
733 | struct passwd * pw = s->pw; | 731 | struct passwd * pw = s->pw; |
@@ -960,9 +958,8 @@ copy_environment(char **source, char ***env, u_int *envsize) | |||
960 | } | 958 | } |
961 | 959 | ||
962 | static char ** | 960 | static char ** |
963 | do_setup_env(Session *s, const char *shell) | 961 | do_setup_env(struct ssh *ssh, Session *s, const char *shell) |
964 | { | 962 | { |
965 | struct ssh *ssh = active_state; /* XXX */ | ||
966 | char buf[256]; | 963 | char buf[256]; |
967 | u_int i, envsize; | 964 | u_int i, envsize; |
968 | char **env, *laddr; | 965 | char **env, *laddr; |
@@ -1421,7 +1418,7 @@ do_pwchange(Session *s) | |||
1421 | } | 1418 | } |
1422 | 1419 | ||
1423 | static void | 1420 | static void |
1424 | child_close_fds(void) | 1421 | child_close_fds(struct ssh *ssh) |
1425 | { | 1422 | { |
1426 | extern int auth_sock; | 1423 | extern int auth_sock; |
1427 | 1424 | ||
@@ -1441,7 +1438,7 @@ child_close_fds(void) | |||
1441 | * open in the parent. | 1438 | * open in the parent. |
1442 | */ | 1439 | */ |
1443 | /* XXX better use close-on-exec? -markus */ | 1440 | /* XXX better use close-on-exec? -markus */ |
1444 | channel_close_all(); | 1441 | channel_close_all(ssh); |
1445 | 1442 | ||
1446 | /* | 1443 | /* |
1447 | * Close any extra file descriptors. Note that there may still be | 1444 | * Close any extra file descriptors. Note that there may still be |
@@ -1465,7 +1462,7 @@ child_close_fds(void) | |||
1465 | */ | 1462 | */ |
1466 | #define ARGV_MAX 10 | 1463 | #define ARGV_MAX 10 |
1467 | void | 1464 | void |
1468 | do_child(Session *s, const char *command) | 1465 | do_child(struct ssh *ssh, Session *s, const char *command) |
1469 | { | 1466 | { |
1470 | extern char **environ; | 1467 | extern char **environ; |
1471 | char **env; | 1468 | char **env; |
@@ -1481,7 +1478,7 @@ do_child(Session *s, const char *command) | |||
1481 | /* Force a password change */ | 1478 | /* Force a password change */ |
1482 | if (s->authctxt->force_pwchange) { | 1479 | if (s->authctxt->force_pwchange) { |
1483 | do_setusercontext(pw); | 1480 | do_setusercontext(pw); |
1484 | child_close_fds(); | 1481 | child_close_fds(ssh); |
1485 | do_pwchange(s); | 1482 | do_pwchange(s); |
1486 | exit(1); | 1483 | exit(1); |
1487 | } | 1484 | } |
@@ -1530,7 +1527,7 @@ do_child(Session *s, const char *command) | |||
1530 | * Make sure $SHELL points to the shell from the password file, | 1527 | * Make sure $SHELL points to the shell from the password file, |
1531 | * even if shell is overridden from login.conf | 1528 | * even if shell is overridden from login.conf |
1532 | */ | 1529 | */ |
1533 | env = do_setup_env(s, shell); | 1530 | env = do_setup_env(ssh, s, shell); |
1534 | 1531 | ||
1535 | #ifdef HAVE_LOGIN_CAP | 1532 | #ifdef HAVE_LOGIN_CAP |
1536 | shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); | 1533 | shell = login_getcapstr(lc, "shell", (char *)shell, (char *)shell); |
@@ -1543,7 +1540,7 @@ do_child(Session *s, const char *command) | |||
1543 | * closed before building the environment, as we call | 1540 | * closed before building the environment, as we call |
1544 | * ssh_remote_ipaddr there. | 1541 | * ssh_remote_ipaddr there. |
1545 | */ | 1542 | */ |
1546 | child_close_fds(); | 1543 | child_close_fds(ssh); |
1547 | 1544 | ||
1548 | /* | 1545 | /* |
1549 | * Must take new environment into use so that .ssh/rc, | 1546 | * Must take new environment into use so that .ssh/rc, |
@@ -1840,7 +1837,7 @@ session_by_pid(pid_t pid) | |||
1840 | } | 1837 | } |
1841 | 1838 | ||
1842 | static int | 1839 | static int |
1843 | session_window_change_req(Session *s) | 1840 | session_window_change_req(struct ssh *ssh, Session *s) |
1844 | { | 1841 | { |
1845 | s->col = packet_get_int(); | 1842 | s->col = packet_get_int(); |
1846 | s->row = packet_get_int(); | 1843 | s->row = packet_get_int(); |
@@ -1852,7 +1849,7 @@ session_window_change_req(Session *s) | |||
1852 | } | 1849 | } |
1853 | 1850 | ||
1854 | static int | 1851 | static int |
1855 | session_pty_req(Session *s) | 1852 | session_pty_req(struct ssh *ssh, Session *s) |
1856 | { | 1853 | { |
1857 | u_int len; | 1854 | u_int len; |
1858 | int n_bytes; | 1855 | int n_bytes; |
@@ -1905,7 +1902,7 @@ session_pty_req(Session *s) | |||
1905 | } | 1902 | } |
1906 | 1903 | ||
1907 | static int | 1904 | static int |
1908 | session_subsystem_req(Session *s) | 1905 | session_subsystem_req(struct ssh *ssh, Session *s) |
1909 | { | 1906 | { |
1910 | struct stat st; | 1907 | struct stat st; |
1911 | u_int len; | 1908 | u_int len; |
@@ -1932,7 +1929,7 @@ session_subsystem_req(Session *s) | |||
1932 | s->is_subsystem = SUBSYSTEM_EXT; | 1929 | s->is_subsystem = SUBSYSTEM_EXT; |
1933 | debug("subsystem: exec() %s", cmd); | 1930 | debug("subsystem: exec() %s", cmd); |
1934 | } | 1931 | } |
1935 | success = do_exec(s, cmd) == 0; | 1932 | success = do_exec(ssh, s, cmd) == 0; |
1936 | break; | 1933 | break; |
1937 | } | 1934 | } |
1938 | } | 1935 | } |
@@ -1945,7 +1942,7 @@ session_subsystem_req(Session *s) | |||
1945 | } | 1942 | } |
1946 | 1943 | ||
1947 | static int | 1944 | static int |
1948 | session_x11_req(Session *s) | 1945 | session_x11_req(struct ssh *ssh, Session *s) |
1949 | { | 1946 | { |
1950 | int success; | 1947 | int success; |
1951 | 1948 | ||
@@ -1962,7 +1959,7 @@ session_x11_req(Session *s) | |||
1962 | 1959 | ||
1963 | if (xauth_valid_string(s->auth_proto) && | 1960 | if (xauth_valid_string(s->auth_proto) && |
1964 | xauth_valid_string(s->auth_data)) | 1961 | xauth_valid_string(s->auth_data)) |
1965 | success = session_setup_x11fwd(s); | 1962 | success = session_setup_x11fwd(ssh, s); |
1966 | else { | 1963 | else { |
1967 | success = 0; | 1964 | success = 0; |
1968 | error("Invalid X11 forwarding data"); | 1965 | error("Invalid X11 forwarding data"); |
@@ -1977,26 +1974,26 @@ session_x11_req(Session *s) | |||
1977 | } | 1974 | } |
1978 | 1975 | ||
1979 | static int | 1976 | static int |
1980 | session_shell_req(Session *s) | 1977 | session_shell_req(struct ssh *ssh, Session *s) |
1981 | { | 1978 | { |
1982 | packet_check_eom(); | 1979 | packet_check_eom(); |
1983 | return do_exec(s, NULL) == 0; | 1980 | return do_exec(ssh, s, NULL) == 0; |
1984 | } | 1981 | } |
1985 | 1982 | ||
1986 | static int | 1983 | static int |
1987 | session_exec_req(Session *s) | 1984 | session_exec_req(struct ssh *ssh, Session *s) |
1988 | { | 1985 | { |
1989 | u_int len, success; | 1986 | u_int len, success; |
1990 | 1987 | ||
1991 | char *command = packet_get_string(&len); | 1988 | char *command = packet_get_string(&len); |
1992 | packet_check_eom(); | 1989 | packet_check_eom(); |
1993 | success = do_exec(s, command) == 0; | 1990 | success = do_exec(ssh, s, command) == 0; |
1994 | free(command); | 1991 | free(command); |
1995 | return success; | 1992 | return success; |
1996 | } | 1993 | } |
1997 | 1994 | ||
1998 | static int | 1995 | static int |
1999 | session_break_req(Session *s) | 1996 | session_break_req(struct ssh *ssh, Session *s) |
2000 | { | 1997 | { |
2001 | 1998 | ||
2002 | packet_get_int(); /* ignored */ | 1999 | packet_get_int(); /* ignored */ |
@@ -2008,7 +2005,7 @@ session_break_req(Session *s) | |||
2008 | } | 2005 | } |
2009 | 2006 | ||
2010 | static int | 2007 | static int |
2011 | session_env_req(Session *s) | 2008 | session_env_req(struct ssh *ssh, Session *s) |
2012 | { | 2009 | { |
2013 | char *name, *val; | 2010 | char *name, *val; |
2014 | u_int name_len, val_len, i; | 2011 | u_int name_len, val_len, i; |
@@ -2043,7 +2040,7 @@ session_env_req(Session *s) | |||
2043 | } | 2040 | } |
2044 | 2041 | ||
2045 | static int | 2042 | static int |
2046 | session_auth_agent_req(Session *s) | 2043 | session_auth_agent_req(struct ssh *ssh, Session *s) |
2047 | { | 2044 | { |
2048 | static int called = 0; | 2045 | static int called = 0; |
2049 | packet_check_eom(); | 2046 | packet_check_eom(); |
@@ -2055,22 +2052,21 @@ session_auth_agent_req(Session *s) | |||
2055 | return 0; | 2052 | return 0; |
2056 | } else { | 2053 | } else { |
2057 | called = 1; | 2054 | called = 1; |
2058 | return auth_input_request_forwarding(s->pw); | 2055 | return auth_input_request_forwarding(ssh, s->pw); |
2059 | } | 2056 | } |
2060 | } | 2057 | } |
2061 | 2058 | ||
2062 | int | 2059 | int |
2063 | session_input_channel_req(Channel *c, const char *rtype) | 2060 | session_input_channel_req(struct ssh *ssh, Channel *c, const char *rtype) |
2064 | { | 2061 | { |
2065 | int success = 0; | 2062 | int success = 0; |
2066 | Session *s; | 2063 | Session *s; |
2067 | 2064 | ||
2068 | if ((s = session_by_channel(c->self)) == NULL) { | 2065 | if ((s = session_by_channel(c->self)) == NULL) { |
2069 | logit("session_input_channel_req: no session %d req %.100s", | 2066 | logit("%s: no session %d req %.100s", __func__, c->self, rtype); |
2070 | c->self, rtype); | ||
2071 | return 0; | 2067 | return 0; |
2072 | } | 2068 | } |
2073 | debug("session_input_channel_req: session %d req %s", s->self, rtype); | 2069 | debug("%s: session %d req %s", __func__, s->self, rtype); |
2074 | 2070 | ||
2075 | /* | 2071 | /* |
2076 | * a session is in LARVAL state until a shell, a command | 2072 | * a session is in LARVAL state until a shell, a command |
@@ -2078,33 +2074,33 @@ session_input_channel_req(Channel *c, const char *rtype) | |||
2078 | */ | 2074 | */ |
2079 | if (c->type == SSH_CHANNEL_LARVAL) { | 2075 | if (c->type == SSH_CHANNEL_LARVAL) { |
2080 | if (strcmp(rtype, "shell") == 0) { | 2076 | if (strcmp(rtype, "shell") == 0) { |
2081 | success = session_shell_req(s); | 2077 | success = session_shell_req(ssh, s); |
2082 | } else if (strcmp(rtype, "exec") == 0) { | 2078 | } else if (strcmp(rtype, "exec") == 0) { |
2083 | success = session_exec_req(s); | 2079 | success = session_exec_req(ssh, s); |
2084 | } else if (strcmp(rtype, "pty-req") == 0) { | 2080 | } else if (strcmp(rtype, "pty-req") == 0) { |
2085 | success = session_pty_req(s); | 2081 | success = session_pty_req(ssh, s); |
2086 | } else if (strcmp(rtype, "x11-req") == 0) { | 2082 | } else if (strcmp(rtype, "x11-req") == 0) { |
2087 | success = session_x11_req(s); | 2083 | success = session_x11_req(ssh, s); |
2088 | } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { | 2084 | } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { |
2089 | success = session_auth_agent_req(s); | 2085 | success = session_auth_agent_req(ssh, s); |
2090 | } else if (strcmp(rtype, "subsystem") == 0) { | 2086 | } else if (strcmp(rtype, "subsystem") == 0) { |
2091 | success = session_subsystem_req(s); | 2087 | success = session_subsystem_req(ssh, s); |
2092 | } else if (strcmp(rtype, "env") == 0) { | 2088 | } else if (strcmp(rtype, "env") == 0) { |
2093 | success = session_env_req(s); | 2089 | success = session_env_req(ssh, s); |
2094 | } | 2090 | } |
2095 | } | 2091 | } |
2096 | if (strcmp(rtype, "window-change") == 0) { | 2092 | if (strcmp(rtype, "window-change") == 0) { |
2097 | success = session_window_change_req(s); | 2093 | success = session_window_change_req(ssh, s); |
2098 | } else if (strcmp(rtype, "break") == 0) { | 2094 | } else if (strcmp(rtype, "break") == 0) { |
2099 | success = session_break_req(s); | 2095 | success = session_break_req(ssh, s); |
2100 | } | 2096 | } |
2101 | 2097 | ||
2102 | return success; | 2098 | return success; |
2103 | } | 2099 | } |
2104 | 2100 | ||
2105 | void | 2101 | void |
2106 | session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr, | 2102 | session_set_fds(struct ssh *ssh, Session *s, |
2107 | int is_tty) | 2103 | int fdin, int fdout, int fderr, int ignore_fderr, int is_tty) |
2108 | { | 2104 | { |
2109 | /* | 2105 | /* |
2110 | * now that have a child and a pipe to the child, | 2106 | * now that have a child and a pipe to the child, |
@@ -2112,7 +2108,7 @@ session_set_fds(Session *s, int fdin, int fdout, int fderr, int ignore_fderr, | |||
2112 | */ | 2108 | */ |
2113 | if (s->chanid == -1) | 2109 | if (s->chanid == -1) |
2114 | fatal("no channel for session %d", s->self); | 2110 | fatal("no channel for session %d", s->self); |
2115 | channel_set_fds(s->chanid, | 2111 | channel_set_fds(ssh, s->chanid, |
2116 | fdout, fdin, fderr, | 2112 | fdout, fdin, fderr, |
2117 | ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, | 2113 | ignore_fderr ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, |
2118 | 1, is_tty, CHAN_SES_WINDOW_DEFAULT); | 2114 | 1, is_tty, CHAN_SES_WINDOW_DEFAULT); |
@@ -2183,40 +2179,40 @@ sig2name(int sig) | |||
2183 | } | 2179 | } |
2184 | 2180 | ||
2185 | static void | 2181 | static void |
2186 | session_close_x11(int id) | 2182 | session_close_x11(struct ssh *ssh, int id) |
2187 | { | 2183 | { |
2188 | Channel *c; | 2184 | Channel *c; |
2189 | 2185 | ||
2190 | if ((c = channel_by_id(id)) == NULL) { | 2186 | if ((c = channel_by_id(ssh, id)) == NULL) { |
2191 | debug("session_close_x11: x11 channel %d missing", id); | 2187 | debug("%s: x11 channel %d missing", __func__, id); |
2192 | } else { | 2188 | } else { |
2193 | /* Detach X11 listener */ | 2189 | /* Detach X11 listener */ |
2194 | debug("session_close_x11: detach x11 channel %d", id); | 2190 | debug("%s: detach x11 channel %d", __func__, id); |
2195 | channel_cancel_cleanup(id); | 2191 | channel_cancel_cleanup(ssh, id); |
2196 | if (c->ostate != CHAN_OUTPUT_CLOSED) | 2192 | if (c->ostate != CHAN_OUTPUT_CLOSED) |
2197 | chan_mark_dead(c); | 2193 | chan_mark_dead(ssh, c); |
2198 | } | 2194 | } |
2199 | } | 2195 | } |
2200 | 2196 | ||
2201 | static void | 2197 | static void |
2202 | session_close_single_x11(int id, void *arg) | 2198 | session_close_single_x11(struct ssh *ssh, int id, void *arg) |
2203 | { | 2199 | { |
2204 | Session *s; | 2200 | Session *s; |
2205 | u_int i; | 2201 | u_int i; |
2206 | 2202 | ||
2207 | debug3("session_close_single_x11: channel %d", id); | 2203 | debug3("%s: channel %d", __func__, id); |
2208 | channel_cancel_cleanup(id); | 2204 | channel_cancel_cleanup(ssh, id); |
2209 | if ((s = session_by_x11_channel(id)) == NULL) | 2205 | if ((s = session_by_x11_channel(id)) == NULL) |
2210 | fatal("session_close_single_x11: no x11 channel %d", id); | 2206 | fatal("%s: no x11 channel %d", __func__, id); |
2211 | for (i = 0; s->x11_chanids[i] != -1; i++) { | 2207 | for (i = 0; s->x11_chanids[i] != -1; i++) { |
2212 | debug("session_close_single_x11: session %d: " | 2208 | debug("%s: session %d: closing channel %d", |
2213 | "closing channel %d", s->self, s->x11_chanids[i]); | 2209 | __func__, s->self, s->x11_chanids[i]); |
2214 | /* | 2210 | /* |
2215 | * The channel "id" is already closing, but make sure we | 2211 | * The channel "id" is already closing, but make sure we |
2216 | * close all of its siblings. | 2212 | * close all of its siblings. |
2217 | */ | 2213 | */ |
2218 | if (s->x11_chanids[i] != id) | 2214 | if (s->x11_chanids[i] != id) |
2219 | session_close_x11(s->x11_chanids[i]); | 2215 | session_close_x11(ssh, s->x11_chanids[i]); |
2220 | } | 2216 | } |
2221 | free(s->x11_chanids); | 2217 | free(s->x11_chanids); |
2222 | s->x11_chanids = NULL; | 2218 | s->x11_chanids = NULL; |
@@ -2231,22 +2227,22 @@ session_close_single_x11(int id, void *arg) | |||
2231 | } | 2227 | } |
2232 | 2228 | ||
2233 | static void | 2229 | static void |
2234 | session_exit_message(Session *s, int status) | 2230 | session_exit_message(struct ssh *ssh, Session *s, int status) |
2235 | { | 2231 | { |
2236 | Channel *c; | 2232 | Channel *c; |
2237 | 2233 | ||
2238 | if ((c = channel_lookup(s->chanid)) == NULL) | 2234 | if ((c = channel_lookup(ssh, s->chanid)) == NULL) |
2239 | fatal("session_exit_message: session %d: no channel %d", | 2235 | fatal("%s: session %d: no channel %d", |
2240 | s->self, s->chanid); | 2236 | __func__, s->self, s->chanid); |
2241 | debug("session_exit_message: session %d channel %d pid %ld", | 2237 | debug("%s: session %d channel %d pid %ld", |
2242 | s->self, s->chanid, (long)s->pid); | 2238 | __func__, s->self, s->chanid, (long)s->pid); |
2243 | 2239 | ||
2244 | if (WIFEXITED(status)) { | 2240 | if (WIFEXITED(status)) { |
2245 | channel_request_start(s->chanid, "exit-status", 0); | 2241 | channel_request_start(ssh, s->chanid, "exit-status", 0); |
2246 | packet_put_int(WEXITSTATUS(status)); | 2242 | packet_put_int(WEXITSTATUS(status)); |
2247 | packet_send(); | 2243 | packet_send(); |
2248 | } else if (WIFSIGNALED(status)) { | 2244 | } else if (WIFSIGNALED(status)) { |
2249 | channel_request_start(s->chanid, "exit-signal", 0); | 2245 | channel_request_start(ssh, s->chanid, "exit-signal", 0); |
2250 | packet_put_cstring(sig2name(WTERMSIG(status))); | 2246 | packet_put_cstring(sig2name(WTERMSIG(status))); |
2251 | #ifdef WCOREDUMP | 2247 | #ifdef WCOREDUMP |
2252 | packet_put_char(WCOREDUMP(status)? 1 : 0); | 2248 | packet_put_char(WCOREDUMP(status)? 1 : 0); |
@@ -2262,14 +2258,14 @@ session_exit_message(Session *s, int status) | |||
2262 | } | 2258 | } |
2263 | 2259 | ||
2264 | /* disconnect channel */ | 2260 | /* disconnect channel */ |
2265 | debug("session_exit_message: release channel %d", s->chanid); | 2261 | debug("%s: release channel %d", __func__, s->chanid); |
2266 | 2262 | ||
2267 | /* | 2263 | /* |
2268 | * Adjust cleanup callback attachment to send close messages when | 2264 | * Adjust cleanup callback attachment to send close messages when |
2269 | * the channel gets EOF. The session will be then be closed | 2265 | * the channel gets EOF. The session will be then be closed |
2270 | * by session_close_by_channel when the childs close their fds. | 2266 | * by session_close_by_channel when the childs close their fds. |
2271 | */ | 2267 | */ |
2272 | channel_register_cleanup(c->self, session_close_by_channel, 1); | 2268 | channel_register_cleanup(ssh, c->self, session_close_by_channel, 1); |
2273 | 2269 | ||
2274 | /* | 2270 | /* |
2275 | * emulate a write failure with 'chan_write_failed', nobody will be | 2271 | * emulate a write failure with 'chan_write_failed', nobody will be |
@@ -2278,13 +2274,12 @@ session_exit_message(Session *s, int status) | |||
2278 | * be some more data waiting in the pipe. | 2274 | * be some more data waiting in the pipe. |
2279 | */ | 2275 | */ |
2280 | if (c->ostate != CHAN_OUTPUT_CLOSED) | 2276 | if (c->ostate != CHAN_OUTPUT_CLOSED) |
2281 | chan_write_failed(c); | 2277 | chan_write_failed(ssh, c); |
2282 | } | 2278 | } |
2283 | 2279 | ||
2284 | void | 2280 | void |
2285 | session_close(Session *s) | 2281 | session_close(struct ssh *ssh, Session *s) |
2286 | { | 2282 | { |
2287 | struct ssh *ssh = active_state; /* XXX */ | ||
2288 | u_int i; | 2283 | u_int i; |
2289 | 2284 | ||
2290 | verbose("Close session: user %s from %.200s port %d id %d", | 2285 | verbose("Close session: user %s from %.200s port %d id %d", |
@@ -2314,16 +2309,15 @@ session_close(Session *s) | |||
2314 | } | 2309 | } |
2315 | 2310 | ||
2316 | void | 2311 | void |
2317 | session_close_by_pid(pid_t pid, int status) | 2312 | session_close_by_pid(struct ssh *ssh, pid_t pid, int status) |
2318 | { | 2313 | { |
2319 | Session *s = session_by_pid(pid); | 2314 | Session *s = session_by_pid(pid); |
2320 | if (s == NULL) { | 2315 | if (s == NULL) { |
2321 | debug("session_close_by_pid: no session for pid %ld", | 2316 | debug("%s: no session for pid %ld", __func__, (long)pid); |
2322 | (long)pid); | ||
2323 | return; | 2317 | return; |
2324 | } | 2318 | } |
2325 | if (s->chanid != -1) | 2319 | if (s->chanid != -1) |
2326 | session_exit_message(s, status); | 2320 | session_exit_message(ssh, s, status); |
2327 | if (s->ttyfd != -1) | 2321 | if (s->ttyfd != -1) |
2328 | session_pty_cleanup(s); | 2322 | session_pty_cleanup(s); |
2329 | s->pid = 0; | 2323 | s->pid = 0; |
@@ -2334,19 +2328,18 @@ session_close_by_pid(pid_t pid, int status) | |||
2334 | * the session 'child' itself dies | 2328 | * the session 'child' itself dies |
2335 | */ | 2329 | */ |
2336 | void | 2330 | void |
2337 | session_close_by_channel(int id, void *arg) | 2331 | session_close_by_channel(struct ssh *ssh, int id, void *arg) |
2338 | { | 2332 | { |
2339 | Session *s = session_by_channel(id); | 2333 | Session *s = session_by_channel(id); |
2340 | u_int i; | 2334 | u_int i; |
2341 | 2335 | ||
2342 | if (s == NULL) { | 2336 | if (s == NULL) { |
2343 | debug("session_close_by_channel: no session for id %d", id); | 2337 | debug("%s: no session for id %d", __func__, id); |
2344 | return; | 2338 | return; |
2345 | } | 2339 | } |
2346 | debug("session_close_by_channel: channel %d child %ld", | 2340 | debug("%s: channel %d child %ld", __func__, id, (long)s->pid); |
2347 | id, (long)s->pid); | ||
2348 | if (s->pid != 0) { | 2341 | if (s->pid != 0) { |
2349 | debug("session_close_by_channel: channel %d: has child", id); | 2342 | debug("%s: channel %d: has child", __func__, id); |
2350 | /* | 2343 | /* |
2351 | * delay detach of session, but release pty, since | 2344 | * delay detach of session, but release pty, since |
2352 | * the fd's to the child are already closed | 2345 | * the fd's to the child are already closed |
@@ -2356,22 +2349,22 @@ session_close_by_channel(int id, void *arg) | |||
2356 | return; | 2349 | return; |
2357 | } | 2350 | } |
2358 | /* detach by removing callback */ | 2351 | /* detach by removing callback */ |
2359 | channel_cancel_cleanup(s->chanid); | 2352 | channel_cancel_cleanup(ssh, s->chanid); |
2360 | 2353 | ||
2361 | /* Close any X11 listeners associated with this session */ | 2354 | /* Close any X11 listeners associated with this session */ |
2362 | if (s->x11_chanids != NULL) { | 2355 | if (s->x11_chanids != NULL) { |
2363 | for (i = 0; s->x11_chanids[i] != -1; i++) { | 2356 | for (i = 0; s->x11_chanids[i] != -1; i++) { |
2364 | session_close_x11(s->x11_chanids[i]); | 2357 | session_close_x11(ssh, s->x11_chanids[i]); |
2365 | s->x11_chanids[i] = -1; | 2358 | s->x11_chanids[i] = -1; |
2366 | } | 2359 | } |
2367 | } | 2360 | } |
2368 | 2361 | ||
2369 | s->chanid = -1; | 2362 | s->chanid = -1; |
2370 | session_close(s); | 2363 | session_close(ssh, s); |
2371 | } | 2364 | } |
2372 | 2365 | ||
2373 | void | 2366 | void |
2374 | session_destroy_all(void (*closefunc)(Session *)) | 2367 | session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *)) |
2375 | { | 2368 | { |
2376 | int i; | 2369 | int i; |
2377 | for (i = 0; i < sessions_nalloc; i++) { | 2370 | for (i = 0; i < sessions_nalloc; i++) { |
@@ -2380,7 +2373,7 @@ session_destroy_all(void (*closefunc)(Session *)) | |||
2380 | if (closefunc != NULL) | 2373 | if (closefunc != NULL) |
2381 | closefunc(s); | 2374 | closefunc(s); |
2382 | else | 2375 | else |
2383 | session_close(s); | 2376 | session_close(ssh, s); |
2384 | } | 2377 | } |
2385 | } | 2378 | } |
2386 | } | 2379 | } |
@@ -2423,7 +2416,7 @@ session_proctitle(Session *s) | |||
2423 | } | 2416 | } |
2424 | 2417 | ||
2425 | int | 2418 | int |
2426 | session_setup_x11fwd(Session *s) | 2419 | session_setup_x11fwd(struct ssh *ssh, Session *s) |
2427 | { | 2420 | { |
2428 | struct stat st; | 2421 | struct stat st; |
2429 | char display[512], auth_display[512]; | 2422 | char display[512], auth_display[512]; |
@@ -2447,14 +2440,14 @@ session_setup_x11fwd(Session *s) | |||
2447 | debug("X11 display already set."); | 2440 | debug("X11 display already set."); |
2448 | return 0; | 2441 | return 0; |
2449 | } | 2442 | } |
2450 | if (x11_create_display_inet(options.x11_display_offset, | 2443 | if (x11_create_display_inet(ssh, options.x11_display_offset, |
2451 | options.x11_use_localhost, s->single_connection, | 2444 | options.x11_use_localhost, s->single_connection, |
2452 | &s->display_number, &s->x11_chanids) == -1) { | 2445 | &s->display_number, &s->x11_chanids) == -1) { |
2453 | debug("x11_create_display_inet failed."); | 2446 | debug("x11_create_display_inet failed."); |
2454 | return 0; | 2447 | return 0; |
2455 | } | 2448 | } |
2456 | for (i = 0; s->x11_chanids[i] != -1; i++) { | 2449 | for (i = 0; s->x11_chanids[i] != -1; i++) { |
2457 | channel_register_cleanup(s->x11_chanids[i], | 2450 | channel_register_cleanup(ssh, s->x11_chanids[i], |
2458 | session_close_single_x11, 0); | 2451 | session_close_single_x11, 0); |
2459 | } | 2452 | } |
2460 | 2453 | ||
@@ -2499,13 +2492,13 @@ session_setup_x11fwd(Session *s) | |||
2499 | } | 2492 | } |
2500 | 2493 | ||
2501 | static void | 2494 | static void |
2502 | do_authenticated2(Authctxt *authctxt) | 2495 | do_authenticated2(struct ssh *ssh, Authctxt *authctxt) |
2503 | { | 2496 | { |
2504 | server_loop2(authctxt); | 2497 | server_loop2(ssh, authctxt); |
2505 | } | 2498 | } |
2506 | 2499 | ||
2507 | void | 2500 | void |
2508 | do_cleanup(Authctxt *authctxt) | 2501 | do_cleanup(struct ssh *ssh, Authctxt *authctxt) |
2509 | { | 2502 | { |
2510 | static int called = 0; | 2503 | static int called = 0; |
2511 | 2504 | ||
@@ -2561,7 +2554,7 @@ do_cleanup(Authctxt *authctxt) | |||
2561 | * or if running in monitor. | 2554 | * or if running in monitor. |
2562 | */ | 2555 | */ |
2563 | if (!use_privsep || mm_is_monitor()) | 2556 | if (!use_privsep || mm_is_monitor()) |
2564 | session_destroy_all(session_pty_cleanup2); | 2557 | session_destroy_all(ssh, session_pty_cleanup2); |
2565 | } | 2558 | } |
2566 | 2559 | ||
2567 | /* Return a name for the remote host that fits inside utmp_size */ | 2560 | /* Return a name for the remote host that fits inside utmp_size */ |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: session.h,v 1.34 2017/08/18 05:36:45 djm Exp $ */ | 1 | /* $OpenBSD: session.h,v 1.35 2017/09/12 06:32:07 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. |
@@ -62,20 +62,20 @@ struct Session { | |||
62 | } *env; | 62 | } *env; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | void do_authenticated(Authctxt *); | 65 | void do_authenticated(struct ssh *, Authctxt *); |
66 | void do_cleanup(Authctxt *); | 66 | void do_cleanup(struct ssh *, Authctxt *); |
67 | 67 | ||
68 | int session_open(Authctxt *, int); | 68 | int session_open(Authctxt *, int); |
69 | void session_unused(int); | 69 | void session_unused(int); |
70 | int session_input_channel_req(Channel *, const char *); | 70 | int session_input_channel_req(struct ssh *, Channel *, const char *); |
71 | void session_close_by_pid(pid_t, int); | 71 | void session_close_by_pid(struct ssh *ssh, pid_t, int); |
72 | void session_close_by_channel(int, void *); | 72 | void session_close_by_channel(struct ssh *, int, void *); |
73 | void session_destroy_all(void (*)(Session *)); | 73 | void session_destroy_all(struct ssh *, void (*)(Session *)); |
74 | void session_pty_cleanup2(Session *); | 74 | void session_pty_cleanup2(Session *); |
75 | 75 | ||
76 | Session *session_new(void); | 76 | Session *session_new(void); |
77 | Session *session_by_tty(char *); | 77 | Session *session_by_tty(char *); |
78 | void session_close(Session *); | 78 | void session_close(struct ssh *, Session *); |
79 | void do_setusercontext(struct passwd *); | 79 | void do_setusercontext(struct passwd *); |
80 | 80 | ||
81 | const char *session_get_remote_name_or_ip(struct ssh *, u_int, int); | 81 | const char *session_get_remote_name_or_ip(struct ssh *, u_int, int); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh.c,v 1.462 2017/08/12 06:46:01 djm Exp $ */ | 1 | /* $OpenBSD: ssh.c,v 1.463 2017/09/12 06:32:07 djm 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 |
@@ -208,7 +208,7 @@ usage(void) | |||
208 | exit(255); | 208 | exit(255); |
209 | } | 209 | } |
210 | 210 | ||
211 | static int ssh_session2(void); | 211 | static int ssh_session2(struct ssh *); |
212 | static void load_public_identity_files(void); | 212 | static void load_public_identity_files(void); |
213 | static void main_sigchld_handler(int); | 213 | static void main_sigchld_handler(int); |
214 | 214 | ||
@@ -596,6 +596,14 @@ main(int ac, char **av) | |||
596 | */ | 596 | */ |
597 | initialize_options(&options); | 597 | initialize_options(&options); |
598 | 598 | ||
599 | /* | ||
600 | * Prepare main ssh transport/connection structures | ||
601 | */ | ||
602 | if ((ssh = ssh_alloc_session_state()) == NULL) | ||
603 | fatal("Couldn't allocate session state"); | ||
604 | channel_init_channels(ssh); | ||
605 | active_state = ssh; /* XXX legacy API compat */ | ||
606 | |||
599 | /* Parse command-line arguments. */ | 607 | /* Parse command-line arguments. */ |
600 | host = NULL; | 608 | host = NULL; |
601 | use_syslog = 0; | 609 | use_syslog = 0; |
@@ -1108,7 +1116,7 @@ main(int ac, char **av) | |||
1108 | 1116 | ||
1109 | if (options.port == 0) | 1117 | if (options.port == 0) |
1110 | options.port = default_ssh_port(); | 1118 | options.port = default_ssh_port(); |
1111 | channel_set_af(options.address_family); | 1119 | channel_set_af(ssh, options.address_family); |
1112 | 1120 | ||
1113 | /* Tidy and check options */ | 1121 | /* Tidy and check options */ |
1114 | if (options.host_key_alias != NULL) | 1122 | if (options.host_key_alias != NULL) |
@@ -1253,8 +1261,7 @@ main(int ac, char **av) | |||
1253 | if (options.control_path != NULL) { | 1261 | if (options.control_path != NULL) { |
1254 | int sock; | 1262 | int sock; |
1255 | if ((sock = muxclient(options.control_path)) >= 0) { | 1263 | if ((sock = muxclient(options.control_path)) >= 0) { |
1256 | packet_set_connection(sock, sock); | 1264 | ssh_packet_set_connection(ssh, sock, sock); |
1257 | ssh = active_state; /* XXX */ | ||
1258 | packet_set_mux(); | 1265 | packet_set_mux(); |
1259 | goto skip_connect; | 1266 | goto skip_connect; |
1260 | } | 1267 | } |
@@ -1274,7 +1281,7 @@ main(int ac, char **av) | |||
1274 | timeout_ms = options.connection_timeout * 1000; | 1281 | timeout_ms = options.connection_timeout * 1000; |
1275 | 1282 | ||
1276 | /* Open a connection to the remote host. */ | 1283 | /* Open a connection to the remote host. */ |
1277 | if (ssh_connect(host, addrs, &hostaddr, options.port, | 1284 | if (ssh_connect(ssh, host, addrs, &hostaddr, options.port, |
1278 | options.address_family, options.connection_attempts, | 1285 | options.address_family, options.connection_attempts, |
1279 | &timeout_ms, options.tcp_keep_alive, | 1286 | &timeout_ms, options.tcp_keep_alive, |
1280 | options.use_privileged_port) != 0) | 1287 | options.use_privileged_port) != 0) |
@@ -1457,7 +1464,7 @@ main(int ac, char **av) | |||
1457 | } | 1464 | } |
1458 | 1465 | ||
1459 | skip_connect: | 1466 | skip_connect: |
1460 | exit_status = ssh_session2(); | 1467 | exit_status = ssh_session2(ssh); |
1461 | packet_close(); | 1468 | packet_close(); |
1462 | 1469 | ||
1463 | if (options.control_path != NULL && muxserver_sock != -1) | 1470 | if (options.control_path != NULL && muxserver_sock != -1) |
@@ -1530,7 +1537,7 @@ fork_postauth(void) | |||
1530 | 1537 | ||
1531 | /* Callback for remote forward global requests */ | 1538 | /* Callback for remote forward global requests */ |
1532 | static void | 1539 | static void |
1533 | ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | 1540 | ssh_confirm_remote_forward(struct ssh *ssh, int type, u_int32_t seq, void *ctxt) |
1534 | { | 1541 | { |
1535 | struct Forward *rfwd = (struct Forward *)ctxt; | 1542 | struct Forward *rfwd = (struct Forward *)ctxt; |
1536 | 1543 | ||
@@ -1548,10 +1555,10 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
1548 | logit("Allocated port %u for remote forward to %s:%d", | 1555 | logit("Allocated port %u for remote forward to %s:%d", |
1549 | rfwd->allocated_port, | 1556 | rfwd->allocated_port, |
1550 | rfwd->connect_host, rfwd->connect_port); | 1557 | rfwd->connect_host, rfwd->connect_port); |
1551 | channel_update_permitted_opens(rfwd->handle, | 1558 | channel_update_permitted_opens(ssh, |
1552 | rfwd->allocated_port); | 1559 | rfwd->handle, rfwd->allocated_port); |
1553 | } else { | 1560 | } else { |
1554 | channel_update_permitted_opens(rfwd->handle, -1); | 1561 | channel_update_permitted_opens(ssh, rfwd->handle, -1); |
1555 | } | 1562 | } |
1556 | } | 1563 | } |
1557 | 1564 | ||
@@ -1580,21 +1587,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) | |||
1580 | } | 1587 | } |
1581 | 1588 | ||
1582 | static void | 1589 | static void |
1583 | client_cleanup_stdio_fwd(int id, void *arg) | 1590 | client_cleanup_stdio_fwd(struct ssh *ssh, int id, void *arg) |
1584 | { | 1591 | { |
1585 | debug("stdio forwarding: done"); | 1592 | debug("stdio forwarding: done"); |
1586 | cleanup_exit(0); | 1593 | cleanup_exit(0); |
1587 | } | 1594 | } |
1588 | 1595 | ||
1589 | static void | 1596 | static void |
1590 | ssh_stdio_confirm(int id, int success, void *arg) | 1597 | ssh_stdio_confirm(struct ssh *ssh, int id, int success, void *arg) |
1591 | { | 1598 | { |
1592 | if (!success) | 1599 | if (!success) |
1593 | fatal("stdio forwarding failed"); | 1600 | fatal("stdio forwarding failed"); |
1594 | } | 1601 | } |
1595 | 1602 | ||
1596 | static void | 1603 | static void |
1597 | ssh_init_stdio_forwarding(void) | 1604 | ssh_init_stdio_forwarding(struct ssh *ssh) |
1598 | { | 1605 | { |
1599 | Channel *c; | 1606 | Channel *c; |
1600 | int in, out; | 1607 | int in, out; |
@@ -1608,15 +1615,15 @@ ssh_init_stdio_forwarding(void) | |||
1608 | if ((in = dup(STDIN_FILENO)) < 0 || | 1615 | if ((in = dup(STDIN_FILENO)) < 0 || |
1609 | (out = dup(STDOUT_FILENO)) < 0) | 1616 | (out = dup(STDOUT_FILENO)) < 0) |
1610 | fatal("channel_connect_stdio_fwd: dup() in/out failed"); | 1617 | fatal("channel_connect_stdio_fwd: dup() in/out failed"); |
1611 | if ((c = channel_connect_stdio_fwd(options.stdio_forward_host, | 1618 | if ((c = channel_connect_stdio_fwd(ssh, options.stdio_forward_host, |
1612 | options.stdio_forward_port, in, out)) == NULL) | 1619 | options.stdio_forward_port, in, out)) == NULL) |
1613 | fatal("%s: channel_connect_stdio_fwd failed", __func__); | 1620 | fatal("%s: channel_connect_stdio_fwd failed", __func__); |
1614 | channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); | 1621 | channel_register_cleanup(ssh, c->self, client_cleanup_stdio_fwd, 0); |
1615 | channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL); | 1622 | channel_register_open_confirm(ssh, c->self, ssh_stdio_confirm, NULL); |
1616 | } | 1623 | } |
1617 | 1624 | ||
1618 | static void | 1625 | static void |
1619 | ssh_init_forwarding(void) | 1626 | ssh_init_forwarding(struct ssh *ssh) |
1620 | { | 1627 | { |
1621 | int success = 0; | 1628 | int success = 0; |
1622 | int i; | 1629 | int i; |
@@ -1635,7 +1642,7 @@ ssh_init_forwarding(void) | |||
1635 | options.local_forwards[i].connect_path : | 1642 | options.local_forwards[i].connect_path : |
1636 | options.local_forwards[i].connect_host, | 1643 | options.local_forwards[i].connect_host, |
1637 | options.local_forwards[i].connect_port); | 1644 | options.local_forwards[i].connect_port); |
1638 | success += channel_setup_local_fwd_listener( | 1645 | success += channel_setup_local_fwd_listener(ssh, |
1639 | &options.local_forwards[i], &options.fwd_opts); | 1646 | &options.local_forwards[i], &options.fwd_opts); |
1640 | } | 1647 | } |
1641 | if (i > 0 && success != i && options.exit_on_forward_failure) | 1648 | if (i > 0 && success != i && options.exit_on_forward_failure) |
@@ -1657,7 +1664,7 @@ ssh_init_forwarding(void) | |||
1657 | options.remote_forwards[i].connect_host, | 1664 | options.remote_forwards[i].connect_host, |
1658 | options.remote_forwards[i].connect_port); | 1665 | options.remote_forwards[i].connect_port); |
1659 | options.remote_forwards[i].handle = | 1666 | options.remote_forwards[i].handle = |
1660 | channel_request_remote_forwarding( | 1667 | channel_request_remote_forwarding(ssh, |
1661 | &options.remote_forwards[i]); | 1668 | &options.remote_forwards[i]); |
1662 | if (options.remote_forwards[i].handle < 0) { | 1669 | if (options.remote_forwards[i].handle < 0) { |
1663 | if (options.exit_on_forward_failure) | 1670 | if (options.exit_on_forward_failure) |
@@ -1666,14 +1673,15 @@ ssh_init_forwarding(void) | |||
1666 | logit("Warning: Could not request remote " | 1673 | logit("Warning: Could not request remote " |
1667 | "forwarding."); | 1674 | "forwarding."); |
1668 | } else { | 1675 | } else { |
1669 | client_register_global_confirm(ssh_confirm_remote_forward, | 1676 | client_register_global_confirm( |
1677 | ssh_confirm_remote_forward, | ||
1670 | &options.remote_forwards[i]); | 1678 | &options.remote_forwards[i]); |
1671 | } | 1679 | } |
1672 | } | 1680 | } |
1673 | 1681 | ||
1674 | /* Initiate tunnel forwarding. */ | 1682 | /* Initiate tunnel forwarding. */ |
1675 | if (options.tun_open != SSH_TUNMODE_NO) { | 1683 | if (options.tun_open != SSH_TUNMODE_NO) { |
1676 | if (client_request_tun_fwd(options.tun_open, | 1684 | if (client_request_tun_fwd(ssh, options.tun_open, |
1677 | options.tun_local, options.tun_remote) == -1) { | 1685 | options.tun_local, options.tun_remote) == -1) { |
1678 | if (options.exit_on_forward_failure) | 1686 | if (options.exit_on_forward_failure) |
1679 | fatal("Could not request tunnel forwarding."); | 1687 | fatal("Could not request tunnel forwarding."); |
@@ -1700,7 +1708,7 @@ check_agent_present(void) | |||
1700 | } | 1708 | } |
1701 | 1709 | ||
1702 | static void | 1710 | static void |
1703 | ssh_session2_setup(int id, int success, void *arg) | 1711 | ssh_session2_setup(struct ssh *ssh, int id, int success, void *arg) |
1704 | { | 1712 | { |
1705 | extern char **environ; | 1713 | extern char **environ; |
1706 | const char *display; | 1714 | const char *display; |
@@ -1713,15 +1721,15 @@ ssh_session2_setup(int id, int success, void *arg) | |||
1713 | display = getenv("DISPLAY"); | 1721 | display = getenv("DISPLAY"); |
1714 | if (display == NULL && options.forward_x11) | 1722 | if (display == NULL && options.forward_x11) |
1715 | debug("X11 forwarding requested but DISPLAY not set"); | 1723 | debug("X11 forwarding requested but DISPLAY not set"); |
1716 | if (options.forward_x11 && client_x11_get_proto(display, | 1724 | if (options.forward_x11 && client_x11_get_proto(ssh, display, |
1717 | options.xauth_location, options.forward_x11_trusted, | 1725 | options.xauth_location, options.forward_x11_trusted, |
1718 | options.forward_x11_timeout, &proto, &data) == 0) { | 1726 | options.forward_x11_timeout, &proto, &data) == 0) { |
1719 | /* Request forwarding with authentication spoofing. */ | 1727 | /* Request forwarding with authentication spoofing. */ |
1720 | debug("Requesting X11 forwarding with authentication " | 1728 | debug("Requesting X11 forwarding with authentication " |
1721 | "spoofing."); | 1729 | "spoofing."); |
1722 | x11_request_forwarding_with_spoofing(id, display, proto, | 1730 | x11_request_forwarding_with_spoofing(ssh, id, display, proto, |
1723 | data, 1); | 1731 | data, 1); |
1724 | client_expect_confirm(id, "X11 forwarding", CONFIRM_WARN); | 1732 | client_expect_confirm(ssh, id, "X11 forwarding", CONFIRM_WARN); |
1725 | /* XXX exit_on_forward_failure */ | 1733 | /* XXX exit_on_forward_failure */ |
1726 | interactive = 1; | 1734 | interactive = 1; |
1727 | } | 1735 | } |
@@ -1729,7 +1737,7 @@ ssh_session2_setup(int id, int success, void *arg) | |||
1729 | check_agent_present(); | 1737 | check_agent_present(); |
1730 | if (options.forward_agent) { | 1738 | if (options.forward_agent) { |
1731 | debug("Requesting authentication agent forwarding."); | 1739 | debug("Requesting authentication agent forwarding."); |
1732 | channel_request_start(id, "auth-agent-req@openssh.com", 0); | 1740 | channel_request_start(ssh, id, "auth-agent-req@openssh.com", 0); |
1733 | packet_send(); | 1741 | packet_send(); |
1734 | } | 1742 | } |
1735 | 1743 | ||
@@ -1737,13 +1745,13 @@ ssh_session2_setup(int id, int success, void *arg) | |||
1737 | packet_set_interactive(interactive, | 1745 | packet_set_interactive(interactive, |
1738 | options.ip_qos_interactive, options.ip_qos_bulk); | 1746 | options.ip_qos_interactive, options.ip_qos_bulk); |
1739 | 1747 | ||
1740 | client_session2_setup(id, tty_flag, subsystem_flag, getenv("TERM"), | 1748 | client_session2_setup(ssh, id, tty_flag, subsystem_flag, getenv("TERM"), |
1741 | NULL, fileno(stdin), &command, environ); | 1749 | NULL, fileno(stdin), &command, environ); |
1742 | } | 1750 | } |
1743 | 1751 | ||
1744 | /* open new channel for a session */ | 1752 | /* open new channel for a session */ |
1745 | static int | 1753 | static int |
1746 | ssh_session2_open(void) | 1754 | ssh_session2_open(struct ssh *ssh) |
1747 | { | 1755 | { |
1748 | Channel *c; | 1756 | Channel *c; |
1749 | int window, packetmax, in, out, err; | 1757 | int window, packetmax, in, out, err; |
@@ -1773,34 +1781,34 @@ ssh_session2_open(void) | |||
1773 | window >>= 1; | 1781 | window >>= 1; |
1774 | packetmax >>= 1; | 1782 | packetmax >>= 1; |
1775 | } | 1783 | } |
1776 | c = channel_new( | 1784 | c = channel_new(ssh, |
1777 | "session", SSH_CHANNEL_OPENING, in, out, err, | 1785 | "session", SSH_CHANNEL_OPENING, in, out, err, |
1778 | window, packetmax, CHAN_EXTENDED_WRITE, | 1786 | window, packetmax, CHAN_EXTENDED_WRITE, |
1779 | "client-session", /*nonblock*/0); | 1787 | "client-session", /*nonblock*/0); |
1780 | 1788 | ||
1781 | debug3("ssh_session2_open: channel_new: %d", c->self); | 1789 | debug3("%s: channel_new: %d", __func__, c->self); |
1782 | 1790 | ||
1783 | channel_send_open(c->self); | 1791 | channel_send_open(ssh, c->self); |
1784 | if (!no_shell_flag) | 1792 | if (!no_shell_flag) |
1785 | channel_register_open_confirm(c->self, | 1793 | channel_register_open_confirm(ssh, c->self, |
1786 | ssh_session2_setup, NULL); | 1794 | ssh_session2_setup, NULL); |
1787 | 1795 | ||
1788 | return c->self; | 1796 | return c->self; |
1789 | } | 1797 | } |
1790 | 1798 | ||
1791 | static int | 1799 | static int |
1792 | ssh_session2(void) | 1800 | ssh_session2(struct ssh *ssh) |
1793 | { | 1801 | { |
1794 | int id = -1; | 1802 | int id = -1; |
1795 | 1803 | ||
1796 | /* XXX should be pre-session */ | 1804 | /* XXX should be pre-session */ |
1797 | if (!options.control_persist) | 1805 | if (!options.control_persist) |
1798 | ssh_init_stdio_forwarding(); | 1806 | ssh_init_stdio_forwarding(ssh); |
1799 | ssh_init_forwarding(); | 1807 | ssh_init_forwarding(ssh); |
1800 | 1808 | ||
1801 | /* Start listening for multiplex clients */ | 1809 | /* Start listening for multiplex clients */ |
1802 | if (!packet_get_mux()) | 1810 | if (!packet_get_mux()) |
1803 | muxserver_listen(); | 1811 | muxserver_listen(ssh); |
1804 | 1812 | ||
1805 | /* | 1813 | /* |
1806 | * If we are in control persist mode and have a working mux listen | 1814 | * If we are in control persist mode and have a working mux listen |
@@ -1828,10 +1836,10 @@ ssh_session2(void) | |||
1828 | * stdio forward setup that we skipped earlier. | 1836 | * stdio forward setup that we skipped earlier. |
1829 | */ | 1837 | */ |
1830 | if (options.control_persist && muxserver_sock == -1) | 1838 | if (options.control_persist && muxserver_sock == -1) |
1831 | ssh_init_stdio_forwarding(); | 1839 | ssh_init_stdio_forwarding(ssh); |
1832 | 1840 | ||
1833 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) | 1841 | if (!no_shell_flag || (datafellows & SSH_BUG_DUMMYCHAN)) |
1834 | id = ssh_session2_open(); | 1842 | id = ssh_session2_open(ssh); |
1835 | else { | 1843 | else { |
1836 | packet_set_interactive( | 1844 | packet_set_interactive( |
1837 | options.control_master == SSHCTL_MASTER_NO, | 1845 | options.control_master == SSHCTL_MASTER_NO, |
@@ -1866,7 +1874,7 @@ ssh_session2(void) | |||
1866 | fork_postauth(); | 1874 | fork_postauth(); |
1867 | } | 1875 | } |
1868 | 1876 | ||
1869 | return client_loop(tty_flag, tty_flag ? | 1877 | return client_loop(ssh, tty_flag, tty_flag ? |
1870 | options.escape_char : SSH_ESCAPECHAR_NONE, id); | 1878 | options.escape_char : SSH_ESCAPECHAR_NONE, id); |
1871 | } | 1879 | } |
1872 | 1880 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshbuf.h,v 1.8 2016/11/25 23:22:04 djm Exp $ */ | 1 | /* $OpenBSD: sshbuf.h,v 1.9 2017/09/12 06:32:07 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2011 Damien Miller | 3 | * Copyright (c) 2011 Damien Miller |
4 | * | 4 | * |
@@ -211,6 +211,7 @@ int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, | |||
211 | /* Another variant: "peeks" into the buffer without modifying it */ | 211 | /* Another variant: "peeks" into the buffer without modifying it */ |
212 | int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, | 212 | int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, |
213 | size_t *lenp); | 213 | size_t *lenp); |
214 | /* XXX peek_u8 / peek_u32 */ | ||
214 | 215 | ||
215 | /* | 216 | /* |
216 | * Functions to extract or store SSH wire encoded bignums and elliptic | 217 | * Functions to extract or store SSH wire encoded bignums and elliptic |
diff --git a/sshconnect.c b/sshconnect.c index 2842d9e59..608566207 100644 --- a/sshconnect.c +++ b/sshconnect.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect.c,v 1.285 2017/09/03 23:33:13 djm Exp $ */ | 1 | /* $OpenBSD: sshconnect.c,v 1.286 2017/09/12 06:32:07 djm 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 |
@@ -105,7 +105,7 @@ expand_proxy_command(const char *proxy_command, const char *user, | |||
105 | * a connected fd back to us. | 105 | * a connected fd back to us. |
106 | */ | 106 | */ |
107 | static int | 107 | static int |
108 | ssh_proxy_fdpass_connect(const char *host, u_short port, | 108 | ssh_proxy_fdpass_connect(struct ssh *ssh, const char *host, u_short port, |
109 | const char *proxy_command) | 109 | const char *proxy_command) |
110 | { | 110 | { |
111 | char *command_string; | 111 | char *command_string; |
@@ -176,7 +176,8 @@ ssh_proxy_fdpass_connect(const char *host, u_short port, | |||
176 | fatal("Couldn't wait for child: %s", strerror(errno)); | 176 | fatal("Couldn't wait for child: %s", strerror(errno)); |
177 | 177 | ||
178 | /* Set the connection file descriptors. */ | 178 | /* Set the connection file descriptors. */ |
179 | packet_set_connection(sock, sock); | 179 | if (ssh_packet_set_connection(ssh, sock, sock) == NULL) |
180 | return -1; /* ssh_packet_set_connection logs error */ | ||
180 | 181 | ||
181 | return 0; | 182 | return 0; |
182 | } | 183 | } |
@@ -185,7 +186,8 @@ ssh_proxy_fdpass_connect(const char *host, u_short port, | |||
185 | * Connect to the given ssh server using a proxy command. | 186 | * Connect to the given ssh server using a proxy command. |
186 | */ | 187 | */ |
187 | static int | 188 | static int |
188 | ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) | 189 | ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port, |
190 | const char *proxy_command) | ||
189 | { | 191 | { |
190 | char *command_string; | 192 | char *command_string; |
191 | int pin[2], pout[2]; | 193 | int pin[2], pout[2]; |
@@ -252,9 +254,9 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) | |||
252 | free(command_string); | 254 | free(command_string); |
253 | 255 | ||
254 | /* Set the connection file descriptors. */ | 256 | /* Set the connection file descriptors. */ |
255 | packet_set_connection(pout[0], pin[1]); | 257 | if (ssh_packet_set_connection(ssh, pout[0], pin[1]) == NULL) |
258 | return -1; /* ssh_packet_set_connection logs error */ | ||
256 | 259 | ||
257 | /* Indicate OK return */ | ||
258 | return 0; | 260 | return 0; |
259 | } | 261 | } |
260 | 262 | ||
@@ -410,7 +412,7 @@ timeout_connect(int sockfd, const struct sockaddr *serv_addr, | |||
410 | * the daemon. | 412 | * the daemon. |
411 | */ | 413 | */ |
412 | static int | 414 | static int |
413 | ssh_connect_direct(const char *host, struct addrinfo *aitop, | 415 | ssh_connect_direct(struct ssh *ssh, const char *host, struct addrinfo *aitop, |
414 | struct sockaddr_storage *hostaddr, u_short port, int family, | 416 | struct sockaddr_storage *hostaddr, u_short port, int family, |
415 | int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv) | 417 | int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv) |
416 | { | 418 | { |
@@ -484,27 +486,31 @@ ssh_connect_direct(const char *host, struct addrinfo *aitop, | |||
484 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); | 486 | error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno)); |
485 | 487 | ||
486 | /* Set the connection. */ | 488 | /* Set the connection. */ |
487 | packet_set_connection(sock, sock); | 489 | if (ssh_packet_set_connection(ssh, sock, sock) == NULL) |
490 | return -1; /* ssh_packet_set_connection logs error */ | ||
488 | 491 | ||
489 | return 0; | 492 | return 0; |
490 | } | 493 | } |
491 | 494 | ||
492 | int | 495 | int |
493 | ssh_connect(const char *host, struct addrinfo *addrs, | 496 | ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs, |
494 | struct sockaddr_storage *hostaddr, u_short port, int family, | 497 | struct sockaddr_storage *hostaddr, u_short port, int family, |
495 | int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv) | 498 | int connection_attempts, int *timeout_ms, int want_keepalive, int needpriv) |
496 | { | 499 | { |
497 | if (options.proxy_command == NULL) { | 500 | if (options.proxy_command == NULL) { |
498 | return ssh_connect_direct(host, addrs, hostaddr, port, family, | 501 | return ssh_connect_direct(ssh, host, addrs, hostaddr, port, |
499 | connection_attempts, timeout_ms, want_keepalive, needpriv); | 502 | family, connection_attempts, timeout_ms, want_keepalive, |
503 | needpriv); | ||
500 | } else if (strcmp(options.proxy_command, "-") == 0) { | 504 | } else if (strcmp(options.proxy_command, "-") == 0) { |
501 | packet_set_connection(STDIN_FILENO, STDOUT_FILENO); | 505 | if ((ssh_packet_set_connection(ssh, |
502 | return 0; /* Always succeeds */ | 506 | STDIN_FILENO, STDOUT_FILENO)) == NULL) |
507 | return -1; /* ssh_packet_set_connection logs error */ | ||
508 | return 0; | ||
503 | } else if (options.proxy_use_fdpass) { | 509 | } else if (options.proxy_use_fdpass) { |
504 | return ssh_proxy_fdpass_connect(host, port, | 510 | return ssh_proxy_fdpass_connect(ssh, host, port, |
505 | options.proxy_command); | 511 | options.proxy_command); |
506 | } | 512 | } |
507 | return ssh_proxy_connect(host, port, options.proxy_command); | 513 | return ssh_proxy_connect(ssh, host, port, options.proxy_command); |
508 | } | 514 | } |
509 | 515 | ||
510 | static void | 516 | static void |
diff --git a/sshconnect.h b/sshconnect.h index f4e73f7b1..b5029e234 100644 --- a/sshconnect.h +++ b/sshconnect.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect.h,v 1.30 2017/05/30 08:52:19 markus Exp $ */ | 1 | /* $OpenBSD: sshconnect.h,v 1.31 2017/09/12 06:32:07 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 4 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
@@ -32,8 +32,10 @@ struct Sensitive { | |||
32 | }; | 32 | }; |
33 | 33 | ||
34 | struct addrinfo; | 34 | struct addrinfo; |
35 | int ssh_connect(const char *, struct addrinfo *, struct sockaddr_storage *, | 35 | struct ssh; |
36 | u_short, int, int, int *, int, int); | 36 | |
37 | int ssh_connect(struct ssh *, const char *, struct addrinfo *, | ||
38 | struct sockaddr_storage *, u_short, int, int, int *, int, int); | ||
37 | void ssh_kill_proxy_command(void); | 39 | void ssh_kill_proxy_command(void); |
38 | 40 | ||
39 | void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, | 41 | void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshd.c,v 1.491 2017/07/01 13:50:45 djm Exp $ */ | 1 | /* $OpenBSD: sshd.c,v 1.492 2017/09/12 06:32:07 djm 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 |
@@ -1621,9 +1621,6 @@ main(int ac, char **av) | |||
1621 | "enabled authentication methods"); | 1621 | "enabled authentication methods"); |
1622 | } | 1622 | } |
1623 | 1623 | ||
1624 | /* set default channel AF */ | ||
1625 | channel_set_af(options.address_family); | ||
1626 | |||
1627 | /* Check that there are no remaining arguments. */ | 1624 | /* Check that there are no remaining arguments. */ |
1628 | if (optind < ac) { | 1625 | if (optind < ac) { |
1629 | fprintf(stderr, "Extra argument %s.\n", av[optind]); | 1626 | fprintf(stderr, "Extra argument %s.\n", av[optind]); |
@@ -1955,8 +1952,14 @@ main(int ac, char **av) | |||
1955 | packet_set_connection(sock_in, sock_out); | 1952 | packet_set_connection(sock_in, sock_out); |
1956 | packet_set_server(); | 1953 | packet_set_server(); |
1957 | ssh = active_state; /* XXX */ | 1954 | ssh = active_state; /* XXX */ |
1955 | |||
1958 | check_ip_options(ssh); | 1956 | check_ip_options(ssh); |
1959 | 1957 | ||
1958 | /* Prepare the channels layer */ | ||
1959 | channel_init_channels(ssh); | ||
1960 | channel_set_af(ssh, options.address_family); | ||
1961 | process_permitopen(ssh, &options); | ||
1962 | |||
1960 | /* Set SO_KEEPALIVE if requested. */ | 1963 | /* Set SO_KEEPALIVE if requested. */ |
1961 | if (options.tcp_keep_alive && packet_connection_is_on_socket() && | 1964 | if (options.tcp_keep_alive && packet_connection_is_on_socket() && |
1962 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) | 1965 | setsockopt(sock_in, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) |
@@ -2080,10 +2083,10 @@ main(int ac, char **av) | |||
2080 | options.client_alive_count_max); | 2083 | options.client_alive_count_max); |
2081 | 2084 | ||
2082 | /* Try to send all our hostkeys to the client */ | 2085 | /* Try to send all our hostkeys to the client */ |
2083 | notify_hostkeys(active_state); | 2086 | notify_hostkeys(ssh); |
2084 | 2087 | ||
2085 | /* Start session. */ | 2088 | /* Start session. */ |
2086 | do_authenticated(authctxt); | 2089 | do_authenticated(ssh, authctxt); |
2087 | 2090 | ||
2088 | /* The connection has been terminated. */ | 2091 | /* The connection has been terminated. */ |
2089 | packet_get_bytes(&ibytes, &obytes); | 2092 | packet_get_bytes(&ibytes, &obytes); |
@@ -2211,8 +2214,10 @@ do_ssh2_kex(void) | |||
2211 | void | 2214 | void |
2212 | cleanup_exit(int i) | 2215 | cleanup_exit(int i) |
2213 | { | 2216 | { |
2217 | struct ssh *ssh = active_state; /* XXX */ | ||
2218 | |||
2214 | if (the_authctxt) { | 2219 | if (the_authctxt) { |
2215 | do_cleanup(the_authctxt); | 2220 | do_cleanup(ssh, the_authctxt); |
2216 | if (use_privsep && privsep_is_preauth && | 2221 | if (use_privsep && privsep_is_preauth && |
2217 | pmonitor != NULL && pmonitor->m_pid > 1) { | 2222 | pmonitor != NULL && pmonitor->m_pid > 1) { |
2218 | debug("Killing privsep child %d", pmonitor->m_pid); | 2223 | debug("Killing privsep child %d", pmonitor->m_pid); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssherr.c,v 1.6 2017/05/07 23:15:59 djm Exp $ */ | 1 | /* $OpenBSD: ssherr.c,v 1.7 2017/09/12 06:32:08 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2011 Damien Miller | 3 | * Copyright (c) 2011 Damien Miller |
4 | * | 4 | * |
@@ -137,6 +137,8 @@ ssh_err(int n) | |||
137 | return "Protocol error"; | 137 | return "Protocol error"; |
138 | case SSH_ERR_KEY_LENGTH: | 138 | case SSH_ERR_KEY_LENGTH: |
139 | return "Invalid key length"; | 139 | return "Invalid key length"; |
140 | case SSH_ERR_NUMBER_TOO_LARGE: | ||
141 | return "number is too large"; | ||
140 | default: | 142 | default: |
141 | return "unknown error"; | 143 | return "unknown error"; |
142 | } | 144 | } |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssherr.h,v 1.4 2017/05/07 23:15:59 djm Exp $ */ | 1 | /* $OpenBSD: ssherr.h,v 1.5 2017/09/12 06:32:08 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2011 Damien Miller | 3 | * Copyright (c) 2011 Damien Miller |
4 | * | 4 | * |
@@ -78,6 +78,7 @@ | |||
78 | #define SSH_ERR_CONN_CORRUPT -54 | 78 | #define SSH_ERR_CONN_CORRUPT -54 |
79 | #define SSH_ERR_PROTOCOL_ERROR -55 | 79 | #define SSH_ERR_PROTOCOL_ERROR -55 |
80 | #define SSH_ERR_KEY_LENGTH -56 | 80 | #define SSH_ERR_KEY_LENGTH -56 |
81 | #define SSH_ERR_NUMBER_TOO_LARGE -57 | ||
81 | 82 | ||
82 | /* Translate a numeric error code to a human-readable error string */ | 83 | /* Translate a numeric error code to a human-readable error string */ |
83 | const char *ssh_err(int n); | 84 | const char *ssh_err(int n); |