diff options
-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); |