Line | Source | Count |
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | | - |
8 | | - |
9 | | - |
10 | | - |
11 | | - |
12 | | - |
13 | | - |
14 | | - |
15 | | - |
16 | | - |
17 | | - |
18 | | - |
19 | | - |
20 | | - |
21 | | - |
22 | | - |
23 | | - |
24 | | - |
25 | | - |
26 | | - |
27 | | - |
28 | | - |
29 | | - |
30 | | - |
31 | | - |
32 | | - |
33 | | - |
34 | | - |
35 | | - |
36 | | - |
37 | | - |
38 | | - |
39 | | - |
40 | | - |
41 | | - |
42 | #include "includes.h" | - |
43 | | - |
44 | #include <sys/types.h> | - |
45 | #include <sys/stat.h> | - |
46 | #include <sys/ioctl.h> | - |
47 | #include <sys/un.h> | - |
48 | #include <sys/socket.h> | - |
49 | #ifdef HAVE_SYS_TIME_H | - |
50 | # include <sys/time.h> | - |
51 | #endif | - |
52 | | - |
53 | #include <netinet/in.h> | - |
54 | #include <arpa/inet.h> | - |
55 | | - |
56 | #include <errno.h> | - |
57 | #include <fcntl.h> | - |
58 | #include <limits.h> | - |
59 | #include <netdb.h> | - |
60 | #include <stdarg.h> | - |
61 | #ifdef HAVE_STDINT_H | - |
62 | #include <stdint.h> | - |
63 | #endif | - |
64 | #include <stdio.h> | - |
65 | #include <stdlib.h> | - |
66 | #include <string.h> | - |
67 | #include <termios.h> | - |
68 | #include <unistd.h> | - |
69 | | - |
70 | #include "openbsd-compat/sys-queue.h" | - |
71 | #include "xmalloc.h" | - |
72 | #include "ssh.h" | - |
73 | #include "ssh2.h" | - |
74 | #include "ssherr.h" | - |
75 | #include "sshbuf.h" | - |
76 | #include "packet.h" | - |
77 | #include "log.h" | - |
78 | #include "misc.h" | - |
79 | #include "channels.h" | - |
80 | #include "compat.h" | - |
81 | #include "canohost.h" | - |
82 | #include "sshkey.h" | - |
83 | #include "authfd.h" | - |
84 | #include "pathnames.h" | - |
85 | #include "match.h" | - |
86 | | - |
87 | | - |
88 | #define NUM_SOCKS 10 | - |
89 | | - |
90 | | - |
91 | | - |
92 | #define FWD_PERMIT_ANY_PORT 0 | - |
93 | | - |
94 | | - |
95 | #define FWD_PERMIT_ANY_HOST "*" | - |
96 | | - |
97 | | - |
98 | | - |
99 | #define MAX_DISPLAYS 1000 | - |
100 | | - |
101 | | - |
102 | typedef void chan_fn(struct ssh *, Channel *c, | - |
103 | fd_set *readset, fd_set *writeset); | - |
104 | | - |
105 | | - |
106 | | - |
107 | | - |
108 | | - |
109 | | - |
110 | | - |
111 | | - |
112 | | - |
113 | | - |
114 | struct permission { | - |
115 | char *host_to_connect; | - |
116 | int port_to_connect; | - |
117 | char *listen_host; | - |
118 | char *listen_path; | - |
119 | int listen_port; | - |
120 | Channel *downstream; | - |
121 | }; | - |
122 | | - |
123 | | - |
124 | | - |
125 | | - |
126 | | - |
127 | struct permission_set { | - |
128 | | - |
129 | | - |
130 | | - |
131 | | - |
132 | u_int num_permitted_user; | - |
133 | struct permission *permitted_user; | - |
134 | | - |
135 | | - |
136 | | - |
137 | | - |
138 | u_int num_permitted_admin; | - |
139 | struct permission *permitted_admin; | - |
140 | | - |
141 | | - |
142 | | - |
143 | | - |
144 | | - |
145 | | - |
146 | int all_permitted; | - |
147 | }; | - |
148 | | - |
149 | | - |
150 | struct ssh_channels { | - |
151 | | - |
152 | | - |
153 | | - |
154 | | - |
155 | Channel **channels; | - |
156 | | - |
157 | | - |
158 | | - |
159 | | - |
160 | | - |
161 | u_int channels_alloc; | - |
162 | | - |
163 | | - |
164 | | - |
165 | | - |
166 | | - |
167 | int channel_max_fd; | - |
168 | | - |
169 | | - |
170 | | - |
171 | | - |
172 | | - |
173 | | - |
174 | | - |
175 | | - |
176 | chan_fn **channel_pre; | - |
177 | chan_fn **channel_post; | - |
178 | | - |
179 | | - |
180 | struct permission_set local_perms; | - |
181 | struct permission_set remote_perms; | - |
182 | | - |
183 | | - |
184 | | - |
185 | | - |
186 | char *x11_saved_display; | - |
187 | | - |
188 | | - |
189 | char *x11_saved_proto; | - |
190 | | - |
191 | | - |
192 | char *x11_saved_data; | - |
193 | u_int x11_saved_data_len; | - |
194 | | - |
195 | | - |
196 | u_int x11_refuse_time; | - |
197 | | - |
198 | | - |
199 | | - |
200 | | - |
201 | | - |
202 | | - |
203 | u_char *x11_fake_data; | - |
204 | u_int x11_fake_data_len; | - |
205 | | - |
206 | | - |
207 | int IPv4or6; | - |
208 | }; | - |
209 | | - |
210 | | - |
211 | static void port_open_helper(struct ssh *ssh, Channel *c, char *rtype); | - |
212 | static const char *channel_rfwd_bind_host(const char *listen_host); | - |
213 | | - |
214 | | - |
215 | static int connect_next(struct channel_connect *); | - |
216 | static void channel_connect_ctx_free(struct channel_connect *); | - |
217 | static Channel *rdynamic_connect_prepare(struct ssh *, char *, char *); | - |
218 | static int rdynamic_connect_finish(struct ssh *, Channel *); | - |
219 | | - |
220 | | - |
221 | static void channel_handler_init(struct ssh_channels *sc); | - |
222 | | - |
223 | | - |
224 | | - |
225 | void | - |
226 | channel_init_channels(struct ssh *ssh) | - |
227 | { | - |
228 | struct ssh_channels *sc; | - |
229 | | - |
230 | if ((sc = calloc(1, sizeof(*sc))) == NULL ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
231 | (sc->channel_pre = calloc(SSH_CHANNEL_MAX_TYPE,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
232 | sizeof(*sc->channel_pre))) == NULL ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
233 | (sc->channel_post = calloc(SSH_CHANNEL_MAX_TYPE,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
234 | sizeof(*sc->channel_post))) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
235 | fatal("%s: allocation failed", __func__); never executed: fatal("%s: allocation failed", __func__); | 0 |
236 | sc->channels_alloc = 10; | - |
237 | sc->channels = xcalloc(sc->channels_alloc, sizeof(*sc->channels)); | - |
238 | sc->IPv4or6 = AF_UNSPEC; | - |
239 | channel_handler_init(sc); | - |
240 | | - |
241 | ssh->chanctxt = sc; | - |
242 | } never executed: end of block | 0 |
243 | | - |
244 | Channel * | - |
245 | channel_by_id(struct ssh *ssh, int id) | - |
246 | { | - |
247 | Channel *c; | - |
248 | | - |
249 | if (id < 0 || (u_int)id >= ssh->chanctxt->channels_alloc) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
250 | logit("%s: %d: bad id", __func__, id); | - |
251 | return NULL; never executed: return ((void *)0) ; | 0 |
252 | } | - |
253 | c = ssh->chanctxt->channels[id]; | - |
254 | if (c == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
255 | logit("%s: %d: bad id: channel free", __func__, id); | - |
256 | return NULL; never executed: return ((void *)0) ; | 0 |
257 | } | - |
258 | return c; never executed: return c; | 0 |
259 | } | - |
260 | | - |
261 | Channel * | - |
262 | channel_by_remote_id(struct ssh *ssh, u_int remote_id) | - |
263 | { | - |
264 | Channel *c; | - |
265 | u_int i; | - |
266 | | - |
267 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
268 | c = ssh->chanctxt->channels[i]; | - |
269 | if (c != NULL && c->have_remote_id && c->remote_id == remote_id)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
270 | return c; never executed: return c; | 0 |
271 | } never executed: end of block | 0 |
272 | return NULL; never executed: return ((void *)0) ; | 0 |
273 | } | - |
274 | | - |
275 | | - |
276 | | - |
277 | | - |
278 | | - |
279 | Channel * | - |
280 | channel_lookup(struct ssh *ssh, int id) | - |
281 | { | - |
282 | Channel *c; | - |
283 | | - |
284 | if ((c = channel_by_id(ssh, id)) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
285 | return NULL; never executed: return ((void *)0) ; | 0 |
286 | | - |
287 | switch (c->type) { | - |
288 | case SSH_CHANNEL_X11_OPEN: never executed: case 7: | 0 |
289 | case SSH_CHANNEL_LARVAL: never executed: case 10: | 0 |
290 | case SSH_CHANNEL_CONNECTING: never executed: case 12: | 0 |
291 | case SSH_CHANNEL_DYNAMIC: never executed: case 13: | 0 |
292 | case SSH_CHANNEL_RDYNAMIC_OPEN: never executed: case 21: | 0 |
293 | case SSH_CHANNEL_RDYNAMIC_FINISH: never executed: case 22: | 0 |
294 | case SSH_CHANNEL_OPENING: never executed: case 3: | 0 |
295 | case SSH_CHANNEL_OPEN: never executed: case 4: | 0 |
296 | case SSH_CHANNEL_ABANDONED: never executed: case 17: | 0 |
297 | case SSH_CHANNEL_MUX_PROXY: never executed: case 20: | 0 |
298 | return c; never executed: return c; | 0 |
299 | } | - |
300 | logit("Non-public channel %d, type %d.", id, c->type); | - |
301 | return NULL; never executed: return ((void *)0) ; | 0 |
302 | } | - |
303 | | - |
304 | | - |
305 | | - |
306 | | - |
307 | | - |
308 | static void | - |
309 | channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, | - |
310 | int extusage, int nonblock, int is_tty) | - |
311 | { | - |
312 | struct ssh_channels *sc = ssh->chanctxt; | - |
313 | | - |
314 | | - |
315 | sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, rfd);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
316 | sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, wfd);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
317 | sc->channel_max_fd = MAXIMUM(sc->channel_max_fd, efd);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
318 | | - |
319 | if (rfd != -1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
320 | fcntl(rfd, F_SETFD, FD_CLOEXEC); never executed: fcntl(rfd, 2 , 1 ); | 0 |
321 | if (wfd != -1 && wfd != rfd)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
322 | fcntl(wfd, F_SETFD, FD_CLOEXEC); never executed: fcntl(wfd, 2 , 1 ); | 0 |
323 | if (efd != -1 && efd != rfd && efd != wfd)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
324 | fcntl(efd, F_SETFD, FD_CLOEXEC); never executed: fcntl(efd, 2 , 1 ); | 0 |
325 | | - |
326 | c->rfd = rfd; | - |
327 | c->wfd = wfd; | - |
328 | c->sock = (rfd == wfd) ? rfd : -1;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
329 | c->efd = efd; | - |
330 | c->extended_usage = extusage; | - |
331 | | - |
332 | if ((c->isatty = is_tty) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
333 | debug2("channel %d: rfd %d isatty", c->self, c->rfd); never executed: debug2("channel %d: rfd %d isatty", c->self, c->rfd); | 0 |
334 | #ifdef _AIX | - |
335 | | - |
336 | c->wfd_isatty = is_tty || isatty(c->wfd); | - |
337 | #endif | - |
338 | | - |
339 | | - |
340 | if (nonblock) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
341 | if (rfd != -1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
342 | set_nonblock(rfd); never executed: set_nonblock(rfd); | 0 |
343 | if (wfd != -1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
344 | set_nonblock(wfd); never executed: set_nonblock(wfd); | 0 |
345 | if (efd != -1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
346 | set_nonblock(efd); never executed: set_nonblock(efd); | 0 |
347 | } never executed: end of block | 0 |
348 | } never executed: end of block | 0 |
349 | | - |
350 | | - |
351 | | - |
352 | | - |
353 | | - |
354 | Channel * | - |
355 | channel_new(struct ssh *ssh, char *ctype, int type, int rfd, int wfd, int efd, | - |
356 | u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock) | - |
357 | { | - |
358 | struct ssh_channels *sc = ssh->chanctxt; | - |
359 | u_int i, found; | - |
360 | Channel *c; | - |
361 | | - |
362 | | - |
363 | for (i = 0; i < sc->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
364 | if (sc->channels[i] == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
365 | | - |
366 | found = i; | - |
367 | break; never executed: break; | 0 |
368 | } | - |
369 | } never executed: end of block | 0 |
370 | if (i >= sc->channels_alloc) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
371 | | - |
372 | | - |
373 | | - |
374 | | - |
375 | found = sc->channels_alloc; | - |
376 | if (sc->channels_alloc > CHANNELS_MAX_CHANNELS)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
377 | fatal("%s: internal error: channels_alloc %d too big", never executed: fatal("%s: internal error: channels_alloc %d too big", __func__, sc->channels_alloc); | 0 |
378 | __func__, sc->channels_alloc); never executed: fatal("%s: internal error: channels_alloc %d too big", __func__, sc->channels_alloc); | 0 |
379 | sc->channels = xrecallocarray(sc->channels, sc->channels_alloc, | - |
380 | sc->channels_alloc + 10, sizeof(*sc->channels)); | - |
381 | sc->channels_alloc += 10; | - |
382 | debug2("channel: expanding %d", sc->channels_alloc); | - |
383 | } never executed: end of block | 0 |
384 | | - |
385 | c = sc->channels[found] = xcalloc(1, sizeof(Channel)); | - |
386 | if ((c->input = sshbuf_new()) == NULL ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
387 | (c->output = sshbuf_new()) == NULL ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
388 | (c->extended = sshbuf_new()) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
389 | fatal("%s: sshbuf_new failed", __func__); never executed: fatal("%s: sshbuf_new failed", __func__); | 0 |
390 | c->ostate = CHAN_OUTPUT_OPEN; | - |
391 | c->istate = CHAN_INPUT_OPEN; | - |
392 | channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, 0); | - |
393 | c->self = found; | - |
394 | c->type = type; | - |
395 | c->ctype = ctype; | - |
396 | c->local_window = window; | - |
397 | c->local_window_max = window; | - |
398 | c->local_maxpacket = maxpack; | - |
399 | c->remote_name = xstrdup(remote_name); | - |
400 | c->ctl_chan = -1; | - |
401 | c->delayed = 1; | - |
402 | TAILQ_INIT(&c->status_confirms); | - |
403 | debug("channel %d: new [%s]", found, remote_name); | - |
404 | return c; never executed: return c; | 0 |
405 | } | - |
406 | | - |
407 | static void | - |
408 | channel_find_maxfd(struct ssh_channels *sc) | - |
409 | { | - |
410 | u_int i; | - |
411 | int max = 0; | - |
412 | Channel *c; | - |
413 | | - |
414 | for (i = 0; i < sc->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
415 | c = sc->channels[i]; | - |
416 | if (c != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
417 | max = MAXIMUM(max, c->rfd);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
418 | max = MAXIMUM(max, c->wfd);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
419 | max = MAXIMUM(max, c->efd);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
420 | } never executed: end of block | 0 |
421 | } never executed: end of block | 0 |
422 | sc->channel_max_fd = max; | - |
423 | } never executed: end of block | 0 |
424 | | - |
425 | int | - |
426 | channel_close_fd(struct ssh *ssh, int *fdp) | - |
427 | { | - |
428 | struct ssh_channels *sc = ssh->chanctxt; | - |
429 | int ret = 0, fd = *fdp; | - |
430 | | - |
431 | if (fd != -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
432 | ret = close(fd); | - |
433 | *fdp = -1; | - |
434 | if (fd == sc->channel_max_fd)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
435 | channel_find_maxfd(sc); never executed: channel_find_maxfd(sc); | 0 |
436 | } never executed: end of block | 0 |
437 | return ret; never executed: return ret; | 0 |
438 | } | - |
439 | | - |
440 | | - |
441 | static void | - |
442 | channel_close_fds(struct ssh *ssh, Channel *c) | - |
443 | { | - |
444 | int sock = c->sock, rfd = c->rfd, wfd = c->wfd, efd = c->efd; | - |
445 | | - |
446 | channel_close_fd(ssh, &c->sock); | - |
447 | if (rfd != sock)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
448 | channel_close_fd(ssh, &c->rfd); never executed: channel_close_fd(ssh, &c->rfd); | 0 |
449 | if (wfd != sock && wfd != rfd)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
450 | channel_close_fd(ssh, &c->wfd); never executed: channel_close_fd(ssh, &c->wfd); | 0 |
451 | if (efd != sock && efd != rfd && efd != wfd)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
452 | channel_close_fd(ssh, &c->efd); never executed: channel_close_fd(ssh, &c->efd); | 0 |
453 | } never executed: end of block | 0 |
454 | | - |
455 | static void | - |
456 | fwd_perm_clear(struct permission *perm) | - |
457 | { | - |
458 | free(perm->host_to_connect); | - |
459 | free(perm->listen_host); | - |
460 | free(perm->listen_path); | - |
461 | bzero(perm, sizeof(*perm)); | - |
462 | } never executed: end of block | 0 |
463 | | - |
464 | | - |
465 | static const char * | - |
466 | fwd_ident(int who, int where) | - |
467 | { | - |
468 | if (who == FORWARD_ADM) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
469 | if (where == FORWARD_LOCAL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
470 | return "admin local"; never executed: return "admin local"; | 0 |
471 | else if (where == FORWARD_REMOTE)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
472 | return "admin remote"; never executed: return "admin remote"; | 0 |
473 | } else if (who == FORWARD_USER) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
474 | if (where == FORWARD_LOCAL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
475 | return "user local"; never executed: return "user local"; | 0 |
476 | else if (where == FORWARD_REMOTE)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
477 | return "user remote"; never executed: return "user remote"; | 0 |
478 | } never executed: end of block | 0 |
479 | fatal("Unknown forward permission list %d/%d", who, where); | - |
480 | } never executed: end of block | 0 |
481 | | - |
482 | | - |
483 | static struct permission_set * | - |
484 | permission_set_get(struct ssh *ssh, int where) | - |
485 | { | - |
486 | struct ssh_channels *sc = ssh->chanctxt; | - |
487 | | - |
488 | switch (where) { | - |
489 | case FORWARD_LOCAL: never executed: case (1<<1): | 0 |
490 | return &sc->local_perms; never executed: return &sc->local_perms; | 0 |
491 | break; dead code: break; | - |
492 | case FORWARD_REMOTE: never executed: case (1): | 0 |
493 | return &sc->remote_perms; never executed: return &sc->remote_perms; | 0 |
494 | break; dead code: break; | - |
495 | default: never executed: default: | 0 |
496 | fatal("%s: invalid forwarding direction %d", __func__, where); | - |
497 | } never executed: end of block | 0 |
498 | } | - |
499 | | - |
500 | | - |
501 | static void | - |
502 | permission_set_get_array(struct ssh *ssh, int who, int where, | - |
503 | struct permission ***permpp, u_int **npermpp) | - |
504 | { | - |
505 | struct permission_set *pset = permission_set_get(ssh, where); | - |
506 | | - |
507 | switch (who) { | - |
508 | case FORWARD_USER: never executed: case 0x101: | 0 |
509 | *permpp = &pset->permitted_user; | - |
510 | *npermpp = &pset->num_permitted_user; | - |
511 | break; never executed: break; | 0 |
512 | case FORWARD_ADM: never executed: case 0x100: | 0 |
513 | *permpp = &pset->permitted_admin; | - |
514 | *npermpp = &pset->num_permitted_admin; | - |
515 | break; never executed: break; | 0 |
516 | default: never executed: default: | 0 |
517 | fatal("%s: invalid forwarding client %d", __func__, who); | - |
518 | } never executed: end of block | 0 |
519 | } | - |
520 | | - |
521 | | - |
522 | static int | - |
523 | permission_set_add(struct ssh *ssh, int who, int where, | - |
524 | const char *host_to_connect, int port_to_connect, | - |
525 | const char *listen_host, const char *listen_path, int listen_port, | - |
526 | Channel *downstream) | - |
527 | { | - |
528 | struct permission **permp; | - |
529 | u_int n, *npermp; | - |
530 | | - |
531 | permission_set_get_array(ssh, who, where, &permp, &npermp); | - |
532 | | - |
533 | if (*npermp >= INT_MAX)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
534 | fatal("%s: %s overflow", __func__, fwd_ident(who, where)); never executed: fatal("%s: %s overflow", __func__, fwd_ident(who, where)); | 0 |
535 | | - |
536 | *permp = xrecallocarray(*permp, *npermp, *npermp + 1, sizeof(**permp)); | - |
537 | n = (*npermp)++; | - |
538 | #define MAYBE_DUP(s) ((s == NULL) ? NULL : xstrdup(s)) | - |
539 | (*permp)[n].host_to_connect = MAYBE_DUP(host_to_connect);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
540 | (*permp)[n].port_to_connect = port_to_connect; | - |
541 | (*permp)[n].listen_host = MAYBE_DUP(listen_host);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
542 | (*permp)[n].listen_path = MAYBE_DUP(listen_path);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
543 | (*permp)[n].listen_port = listen_port; | - |
544 | (*permp)[n].downstream = downstream; | - |
545 | #undef MAYBE_DUP | - |
546 | return (int)n; never executed: return (int)n; | 0 |
547 | } | - |
548 | | - |
549 | static void | - |
550 | mux_remove_remote_forwardings(struct ssh *ssh, Channel *c) | - |
551 | { | - |
552 | struct ssh_channels *sc = ssh->chanctxt; | - |
553 | struct permission_set *pset = &sc->local_perms; | - |
554 | struct permission *perm; | - |
555 | int r; | - |
556 | u_int i; | - |
557 | | - |
558 | for (i = 0; i < pset->num_permitted_user; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
559 | perm = &pset->permitted_user[i]; | - |
560 | if (perm->downstream != c)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
561 | continue; never executed: continue; | 0 |
562 | | - |
563 | | - |
564 | debug("channel %d: cleanup remote forward for %s:%u", | - |
565 | c->self, perm->listen_host, perm->listen_port); | - |
566 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
567 | (r = sshpkt_put_cstring(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
568 | "cancel-tcpip-forward")) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
569 | (r = sshpkt_put_u8(ssh, 0)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
570 | (r = sshpkt_put_cstring(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
571 | channel_rfwd_bind_host(perm->listen_host))) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
572 | (r = sshpkt_put_u32(ssh, perm->listen_port)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
573 | (r = sshpkt_send(ssh)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
574 | fatal("%s: channel %i: %s", __func__, | - |
575 | c->self, ssh_err(r)); | - |
576 | } never executed: end of block | 0 |
577 | fwd_perm_clear(perm); | - |
578 | } never executed: end of block | 0 |
579 | } never executed: end of block | 0 |
580 | | - |
581 | | - |
582 | void | - |
583 | channel_free(struct ssh *ssh, Channel *c) | - |
584 | { | - |
585 | struct ssh_channels *sc = ssh->chanctxt; | - |
586 | char *s; | - |
587 | u_int i, n; | - |
588 | Channel *other; | - |
589 | struct channel_confirm *cc; | - |
590 | | - |
591 | for (n = 0, i = 0; i < sc->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
592 | if ((other = sc->channels[i]) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
593 | continue; never executed: continue; | 0 |
594 | n++; | - |
595 | | - |
596 | if (c->type == SSH_CHANNEL_MUX_CLIENT &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
597 | other->type == SSH_CHANNEL_MUX_PROXY &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
598 | other->mux_ctx == c) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
599 | other->mux_ctx = NULL; | - |
600 | other->type = SSH_CHANNEL_OPEN; | - |
601 | other->istate = CHAN_INPUT_CLOSED; | - |
602 | other->ostate = CHAN_OUTPUT_CLOSED; | - |
603 | } never executed: end of block | 0 |
604 | } never executed: end of block | 0 |
605 | debug("channel %d: free: %s, nchannels %u", c->self, | - |
606 | c->remote_name ? c->remote_name : "???", n); | - |
607 | | - |
608 | if (c->type == SSH_CHANNEL_MUX_CLIENT)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
609 | mux_remove_remote_forwardings(ssh, c); never executed: mux_remove_remote_forwardings(ssh, c); | 0 |
610 | | - |
611 | if (log_level_get() >= SYSLOG_LEVEL_DEBUG3) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
612 | s = channel_open_message(ssh); | - |
613 | debug3("channel %d: status: %s", c->self, s); | - |
614 | free(s); | - |
615 | } never executed: end of block | 0 |
616 | | - |
617 | channel_close_fds(ssh, c); | - |
618 | sshbuf_free(c->input); | - |
619 | sshbuf_free(c->output); | - |
620 | sshbuf_free(c->extended); | - |
621 | c->input = c->output = c->extended = NULL; | - |
622 | free(c->remote_name); | - |
623 | c->remote_name = NULL; | - |
624 | free(c->path); | - |
625 | c->path = NULL; | - |
626 | free(c->listening_addr); | - |
627 | c->listening_addr = NULL; | - |
628 | while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
629 | if (cc->abandon_cb != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
630 | cc->abandon_cb(ssh, c, cc->ctx); never executed: cc->abandon_cb(ssh, c, cc->ctx); | 0 |
631 | TAILQ_REMOVE(&c->status_confirms, cc, entry); never executed: (cc)->entry.tqe_next->entry.tqe_prev = (cc)->entry.tqe_prev; never executed: (&c->status_confirms)->tqh_last = (cc)->entry.tqe_prev; TRUE | never evaluated | FALSE | never evaluated |
| 0 |
632 | explicit_bzero(cc, sizeof(*cc)); | - |
633 | free(cc); | - |
634 | } never executed: end of block | 0 |
635 | if (c->filter_cleanup != NULL && c->filter_ctx != NULL)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
636 | c->filter_cleanup(ssh, c->self, c->filter_ctx); never executed: c->filter_cleanup(ssh, c->self, c->filter_ctx); | 0 |
637 | sc->channels[c->self] = NULL; | - |
638 | explicit_bzero(c, sizeof(*c)); | - |
639 | free(c); | - |
640 | } never executed: end of block | 0 |
641 | | - |
642 | void | - |
643 | channel_free_all(struct ssh *ssh) | - |
644 | { | - |
645 | u_int i; | - |
646 | | - |
647 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
648 | if (ssh->chanctxt->channels[i] != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
649 | channel_free(ssh, ssh->chanctxt->channels[i]); never executed: channel_free(ssh, ssh->chanctxt->channels[i]); | 0 |
650 | } never executed: end of block | 0 |
651 | | - |
652 | | - |
653 | | - |
654 | | - |
655 | | - |
656 | void | - |
657 | channel_close_all(struct ssh *ssh) | - |
658 | { | - |
659 | u_int i; | - |
660 | | - |
661 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
662 | if (ssh->chanctxt->channels[i] != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
663 | channel_close_fds(ssh, ssh->chanctxt->channels[i]); never executed: channel_close_fds(ssh, ssh->chanctxt->channels[i]); | 0 |
664 | } never executed: end of block | 0 |
665 | | - |
666 | | - |
667 | | - |
668 | | - |
669 | void | - |
670 | channel_stop_listening(struct ssh *ssh) | - |
671 | { | - |
672 | u_int i; | - |
673 | Channel *c; | - |
674 | | - |
675 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
676 | c = ssh->chanctxt->channels[i]; | - |
677 | if (c != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
678 | switch (c->type) { | - |
679 | case SSH_CHANNEL_AUTH_SOCKET: never executed: case 6: | 0 |
680 | case SSH_CHANNEL_PORT_LISTENER: never executed: case 2: | 0 |
681 | case SSH_CHANNEL_RPORT_LISTENER: never executed: case 11: | 0 |
682 | case SSH_CHANNEL_X11_LISTENER: never executed: case 1: | 0 |
683 | case SSH_CHANNEL_UNIX_LISTENER: never executed: case 18: | 0 |
684 | case SSH_CHANNEL_RUNIX_LISTENER: never executed: case 19: | 0 |
685 | channel_close_fd(ssh, &c->sock); | - |
686 | channel_free(ssh, c); | - |
687 | break; never executed: break; | 0 |
688 | } | - |
689 | } never executed: end of block | 0 |
690 | } never executed: end of block | 0 |
691 | } never executed: end of block | 0 |
692 | | - |
693 | | - |
694 | | - |
695 | | - |
696 | | - |
697 | int | - |
698 | channel_not_very_much_buffered_data(struct ssh *ssh) | - |
699 | { | - |
700 | u_int i; | - |
701 | u_int maxsize = ssh_packet_get_maxsize(ssh); | - |
702 | Channel *c; | - |
703 | | - |
704 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
705 | c = ssh->chanctxt->channels[i]; | - |
706 | if (c == NULL || c->type != SSH_CHANNEL_OPEN)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
707 | continue; never executed: continue; | 0 |
708 | if (sshbuf_len(c->output) > maxsize) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
709 | debug2("channel %d: big output buffer %zu > %u", | - |
710 | c->self, sshbuf_len(c->output), maxsize); | - |
711 | return 0; never executed: return 0; | 0 |
712 | } | - |
713 | } never executed: end of block | 0 |
714 | return 1; never executed: return 1; | 0 |
715 | } | - |
716 | | - |
717 | | - |
718 | int | - |
719 | channel_still_open(struct ssh *ssh) | - |
720 | { | - |
721 | u_int i; | - |
722 | Channel *c; | - |
723 | | - |
724 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
725 | c = ssh->chanctxt->channels[i]; | - |
726 | if (c == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
727 | continue; never executed: continue; | 0 |
728 | switch (c->type) { | - |
729 | case SSH_CHANNEL_X11_LISTENER: never executed: case 1: | 0 |
730 | case SSH_CHANNEL_PORT_LISTENER: never executed: case 2: | 0 |
731 | case SSH_CHANNEL_RPORT_LISTENER: never executed: case 11: | 0 |
732 | case SSH_CHANNEL_MUX_LISTENER: never executed: case 15: | 0 |
733 | case SSH_CHANNEL_CLOSED: never executed: case 5: | 0 |
734 | case SSH_CHANNEL_AUTH_SOCKET: never executed: case 6: | 0 |
735 | case SSH_CHANNEL_DYNAMIC: never executed: case 13: | 0 |
736 | case SSH_CHANNEL_RDYNAMIC_OPEN: never executed: case 21: | 0 |
737 | case SSH_CHANNEL_CONNECTING: never executed: case 12: | 0 |
738 | case SSH_CHANNEL_ZOMBIE: never executed: case 14: | 0 |
739 | case SSH_CHANNEL_ABANDONED: never executed: case 17: | 0 |
740 | case SSH_CHANNEL_UNIX_LISTENER: never executed: case 18: | 0 |
741 | case SSH_CHANNEL_RUNIX_LISTENER: never executed: case 19: | 0 |
742 | continue; never executed: continue; | 0 |
743 | case SSH_CHANNEL_LARVAL: never executed: case 10: | 0 |
744 | continue; never executed: continue; | 0 |
745 | case SSH_CHANNEL_OPENING: never executed: case 3: | 0 |
746 | case SSH_CHANNEL_OPEN: never executed: case 4: | 0 |
747 | case SSH_CHANNEL_RDYNAMIC_FINISH: never executed: case 22: | 0 |
748 | case SSH_CHANNEL_X11_OPEN: never executed: case 7: | 0 |
749 | case SSH_CHANNEL_MUX_CLIENT: never executed: case 16: | 0 |
750 | case SSH_CHANNEL_MUX_PROXY: never executed: case 20: | 0 |
751 | return 1; never executed: return 1; | 0 |
752 | default: never executed: default: | 0 |
753 | fatal("%s: bad channel type %d", __func__, c->type); | - |
754 | | - |
755 | } never executed: end of block | 0 |
756 | } | - |
757 | return 0; never executed: return 0; | 0 |
758 | } | - |
759 | | - |
760 | | - |
761 | int | - |
762 | channel_find_open(struct ssh *ssh) | - |
763 | { | - |
764 | u_int i; | - |
765 | Channel *c; | - |
766 | | - |
767 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
768 | c = ssh->chanctxt->channels[i]; | - |
769 | if (c == NULL || !c->have_remote_id)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
770 | continue; never executed: continue; | 0 |
771 | switch (c->type) { | - |
772 | case SSH_CHANNEL_CLOSED: never executed: case 5: | 0 |
773 | case SSH_CHANNEL_DYNAMIC: never executed: case 13: | 0 |
774 | case SSH_CHANNEL_RDYNAMIC_OPEN: never executed: case 21: | 0 |
775 | case SSH_CHANNEL_RDYNAMIC_FINISH: never executed: case 22: | 0 |
776 | case SSH_CHANNEL_X11_LISTENER: never executed: case 1: | 0 |
777 | case SSH_CHANNEL_PORT_LISTENER: never executed: case 2: | 0 |
778 | case SSH_CHANNEL_RPORT_LISTENER: never executed: case 11: | 0 |
779 | case SSH_CHANNEL_MUX_LISTENER: never executed: case 15: | 0 |
780 | case SSH_CHANNEL_MUX_CLIENT: never executed: case 16: | 0 |
781 | case SSH_CHANNEL_MUX_PROXY: never executed: case 20: | 0 |
782 | case SSH_CHANNEL_OPENING: never executed: case 3: | 0 |
783 | case SSH_CHANNEL_CONNECTING: never executed: case 12: | 0 |
784 | case SSH_CHANNEL_ZOMBIE: never executed: case 14: | 0 |
785 | case SSH_CHANNEL_ABANDONED: never executed: case 17: | 0 |
786 | case SSH_CHANNEL_UNIX_LISTENER: never executed: case 18: | 0 |
787 | case SSH_CHANNEL_RUNIX_LISTENER: never executed: case 19: | 0 |
788 | continue; never executed: continue; | 0 |
789 | case SSH_CHANNEL_LARVAL: never executed: case 10: | 0 |
790 | case SSH_CHANNEL_AUTH_SOCKET: never executed: case 6: | 0 |
791 | case SSH_CHANNEL_OPEN: never executed: case 4: | 0 |
792 | case SSH_CHANNEL_X11_OPEN: never executed: case 7: | 0 |
793 | return i; never executed: return i; | 0 |
794 | default: never executed: default: | 0 |
795 | fatal("%s: bad channel type %d", __func__, c->type); | - |
796 | | - |
797 | } never executed: end of block | 0 |
798 | } | - |
799 | return -1; never executed: return -1; | 0 |
800 | } | - |
801 | | - |
802 | | - |
803 | | - |
804 | | - |
805 | | - |
806 | | - |
807 | char * | - |
808 | channel_open_message(struct ssh *ssh) | - |
809 | { | - |
810 | struct sshbuf *buf; | - |
811 | Channel *c; | - |
812 | u_int i; | - |
813 | int r; | - |
814 | char *ret; | - |
815 | | - |
816 | if ((buf = sshbuf_new()) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
817 | fatal("%s: sshbuf_new", __func__); never executed: fatal("%s: sshbuf_new", __func__); | 0 |
818 | if ((r = sshbuf_putf(buf,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
819 | "The following connections are open:\r\n")) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
820 | fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); never executed: fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); | 0 |
821 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
822 | c = ssh->chanctxt->channels[i]; | - |
823 | if (c == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
824 | continue; never executed: continue; | 0 |
825 | switch (c->type) { | - |
826 | case SSH_CHANNEL_X11_LISTENER: never executed: case 1: | 0 |
827 | case SSH_CHANNEL_PORT_LISTENER: never executed: case 2: | 0 |
828 | case SSH_CHANNEL_RPORT_LISTENER: never executed: case 11: | 0 |
829 | case SSH_CHANNEL_CLOSED: never executed: case 5: | 0 |
830 | case SSH_CHANNEL_AUTH_SOCKET: never executed: case 6: | 0 |
831 | case SSH_CHANNEL_ZOMBIE: never executed: case 14: | 0 |
832 | case SSH_CHANNEL_ABANDONED: never executed: case 17: | 0 |
833 | case SSH_CHANNEL_MUX_LISTENER: never executed: case 15: | 0 |
834 | case SSH_CHANNEL_UNIX_LISTENER: never executed: case 18: | 0 |
835 | case SSH_CHANNEL_RUNIX_LISTENER: never executed: case 19: | 0 |
836 | continue; never executed: continue; | 0 |
837 | case SSH_CHANNEL_LARVAL: never executed: case 10: | 0 |
838 | case SSH_CHANNEL_OPENING: never executed: case 3: | 0 |
839 | case SSH_CHANNEL_CONNECTING: never executed: case 12: | 0 |
840 | case SSH_CHANNEL_DYNAMIC: never executed: case 13: | 0 |
841 | case SSH_CHANNEL_RDYNAMIC_OPEN: never executed: case 21: | 0 |
842 | case SSH_CHANNEL_RDYNAMIC_FINISH: never executed: case 22: | 0 |
843 | case SSH_CHANNEL_OPEN: never executed: case 4: | 0 |
844 | case SSH_CHANNEL_X11_OPEN: never executed: case 7: | 0 |
845 | case SSH_CHANNEL_MUX_PROXY: never executed: case 20: | 0 |
846 | case SSH_CHANNEL_MUX_CLIENT: never executed: case 16: | 0 |
847 | if ((r = sshbuf_putf(buf, " #%d %.300s "TRUE | never evaluated | FALSE | never evaluated |
| 0 |
848 | "(t%d %s%u i%u/%zu o%u/%zu fd %d/%d cc %d)\r\n",TRUE | never evaluated | FALSE | never evaluated |
| 0 |
849 | c->self, c->remote_name,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
850 | c->type,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
851 | c->have_remote_id ? "r" : "nr", c->remote_id,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
852 | c->istate, sshbuf_len(c->input),TRUE | never evaluated | FALSE | never evaluated |
| 0 |
853 | c->ostate, sshbuf_len(c->output),TRUE | never evaluated | FALSE | never evaluated |
| 0 |
854 | c->rfd, c->wfd, c->ctl_chan)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
855 | fatal("%s: sshbuf_putf: %s", never executed: fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); | 0 |
856 | __func__, ssh_err(r)); never executed: fatal("%s: sshbuf_putf: %s", __func__, ssh_err(r)); | 0 |
857 | continue; never executed: continue; | 0 |
858 | default: never executed: default: | 0 |
859 | fatal("%s: bad channel type %d", __func__, c->type); | - |
860 | | - |
861 | } never executed: end of block | 0 |
862 | } | - |
863 | if ((ret = sshbuf_dup_string(buf)) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
864 | fatal("%s: sshbuf_dup_string", __func__); never executed: fatal("%s: sshbuf_dup_string", __func__); | 0 |
865 | sshbuf_free(buf); | - |
866 | return ret; never executed: return ret; | 0 |
867 | } | - |
868 | | - |
869 | static void | - |
870 | open_preamble(struct ssh *ssh, const char *where, Channel *c, const char *type) | - |
871 | { | - |
872 | int r; | - |
873 | | - |
874 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
875 | (r = sshpkt_put_cstring(ssh, type)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
876 | (r = sshpkt_put_u32(ssh, c->self)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
877 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
878 | (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
879 | fatal("%s: channel %i: open: %s", where, c->self, ssh_err(r)); | - |
880 | } never executed: end of block | 0 |
881 | } never executed: end of block | 0 |
882 | | - |
883 | void | - |
884 | channel_send_open(struct ssh *ssh, int id) | - |
885 | { | - |
886 | Channel *c = channel_lookup(ssh, id); | - |
887 | int r; | - |
888 | | - |
889 | if (c == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
890 | logit("channel_send_open: %d: bad id", id); | - |
891 | return; never executed: return; | 0 |
892 | } | - |
893 | debug2("channel %d: send open", id); | - |
894 | open_preamble(ssh, __func__, c, c->ctype); | - |
895 | if ((r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
896 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); never executed: fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | 0 |
897 | } never executed: end of block | 0 |
898 | | - |
899 | void | - |
900 | channel_request_start(struct ssh *ssh, int id, char *service, int wantconfirm) | - |
901 | { | - |
902 | Channel *c = channel_lookup(ssh, id); | - |
903 | int r; | - |
904 | | - |
905 | if (c == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
906 | logit("%s: %d: unknown channel id", __func__, id); | - |
907 | return; never executed: return; | 0 |
908 | } | - |
909 | if (!c->have_remote_id)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
910 | fatal(":%s: channel %d: no remote id", __func__, c->self); never executed: fatal(":%s: channel %d: no remote id", __func__, c->self); | 0 |
911 | | - |
912 | debug2("channel %d: request %s confirm %d", id, service, wantconfirm); | - |
913 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_REQUEST)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
914 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
915 | (r = sshpkt_put_cstring(ssh, service)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
916 | (r = sshpkt_put_u8(ssh, wantconfirm)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
917 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | - |
918 | } never executed: end of block | 0 |
919 | } never executed: end of block | 0 |
920 | | - |
921 | void | - |
922 | channel_register_status_confirm(struct ssh *ssh, int id, | - |
923 | channel_confirm_cb *cb, channel_confirm_abandon_cb *abandon_cb, void *ctx) | - |
924 | { | - |
925 | struct channel_confirm *cc; | - |
926 | Channel *c; | - |
927 | | - |
928 | if ((c = channel_lookup(ssh, id)) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
929 | fatal("%s: %d: bad id", __func__, id); never executed: fatal("%s: %d: bad id", __func__, id); | 0 |
930 | | - |
931 | cc = xcalloc(1, sizeof(*cc)); | - |
932 | cc->cb = cb; | - |
933 | cc->abandon_cb = abandon_cb; | - |
934 | cc->ctx = ctx; | - |
935 | TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry); | - |
936 | } never executed: end of block | 0 |
937 | | - |
938 | void | - |
939 | channel_register_open_confirm(struct ssh *ssh, int id, | - |
940 | channel_open_fn *fn, void *ctx) | - |
941 | { | - |
942 | Channel *c = channel_lookup(ssh, id); | - |
943 | | - |
944 | if (c == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
945 | logit("%s: %d: bad id", __func__, id); | - |
946 | return; never executed: return; | 0 |
947 | } | - |
948 | c->open_confirm = fn; | - |
949 | c->open_confirm_ctx = ctx; | - |
950 | } never executed: end of block | 0 |
951 | | - |
952 | void | - |
953 | channel_register_cleanup(struct ssh *ssh, int id, | - |
954 | channel_callback_fn *fn, int do_close) | - |
955 | { | - |
956 | Channel *c = channel_by_id(ssh, id); | - |
957 | | - |
958 | if (c == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
959 | logit("%s: %d: bad id", __func__, id); | - |
960 | return; never executed: return; | 0 |
961 | } | - |
962 | c->detach_user = fn; | - |
963 | c->detach_close = do_close; | - |
964 | } never executed: end of block | 0 |
965 | | - |
966 | void | - |
967 | channel_cancel_cleanup(struct ssh *ssh, int id) | - |
968 | { | - |
969 | Channel *c = channel_by_id(ssh, id); | - |
970 | | - |
971 | if (c == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
972 | logit("%s: %d: bad id", __func__, id); | - |
973 | return; never executed: return; | 0 |
974 | } | - |
975 | c->detach_user = NULL; | - |
976 | c->detach_close = 0; | - |
977 | } never executed: end of block | 0 |
978 | | - |
979 | void | - |
980 | channel_register_filter(struct ssh *ssh, int id, channel_infilter_fn *ifn, | - |
981 | channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx) | - |
982 | { | - |
983 | Channel *c = channel_lookup(ssh, id); | - |
984 | | - |
985 | if (c == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
986 | logit("%s: %d: bad id", __func__, id); | - |
987 | return; never executed: return; | 0 |
988 | } | - |
989 | c->input_filter = ifn; | - |
990 | c->output_filter = ofn; | - |
991 | c->filter_ctx = ctx; | - |
992 | c->filter_cleanup = cfn; | - |
993 | } never executed: end of block | 0 |
994 | | - |
995 | void | - |
996 | channel_set_fds(struct ssh *ssh, int id, int rfd, int wfd, int efd, | - |
997 | int extusage, int nonblock, int is_tty, u_int window_max) | - |
998 | { | - |
999 | Channel *c = channel_lookup(ssh, id); | - |
1000 | int r; | - |
1001 | | - |
1002 | if (c == NULL || c->type != SSH_CHANNEL_LARVAL)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1003 | fatal("channel_activate for non-larval channel %d.", id); never executed: fatal("channel_activate for non-larval channel %d.", id); | 0 |
1004 | if (!c->have_remote_id)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1005 | fatal(":%s: channel %d: no remote id", __func__, c->self); never executed: fatal(":%s: channel %d: no remote id", __func__, c->self); | 0 |
1006 | | - |
1007 | channel_register_fds(ssh, c, rfd, wfd, efd, extusage, nonblock, is_tty); | - |
1008 | c->type = SSH_CHANNEL_OPEN; | - |
1009 | c->local_window = c->local_window_max = window_max; | - |
1010 | | - |
1011 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1012 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1013 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1014 | (r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1015 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); never executed: fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | 0 |
1016 | } never executed: end of block | 0 |
1017 | | - |
1018 | static void | - |
1019 | channel_pre_listener(struct ssh *ssh, Channel *c, | - |
1020 | fd_set *readset, fd_set *writeset) | - |
1021 | { | - |
1022 | FD_SET(c->sock, readset); | - |
1023 | } never executed: end of block | 0 |
1024 | | - |
1025 | static void | - |
1026 | channel_pre_connecting(struct ssh *ssh, Channel *c, | - |
1027 | fd_set *readset, fd_set *writeset) | - |
1028 | { | - |
1029 | debug3("channel %d: waiting for connection", c->self); | - |
1030 | FD_SET(c->sock, writeset); | - |
1031 | } never executed: end of block | 0 |
1032 | | - |
1033 | static void | - |
1034 | channel_pre_open(struct ssh *ssh, Channel *c, | - |
1035 | fd_set *readset, fd_set *writeset) | - |
1036 | { | - |
1037 | if (c->istate == CHAN_INPUT_OPEN &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1038 | c->remote_window > 0 &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1039 | sshbuf_len(c->input) < c->remote_window &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1040 | sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1041 | FD_SET(c->rfd, readset); never executed: kludge_FD_SET(c->rfd, readset); | 0 |
1042 | if (c->ostate == CHAN_OUTPUT_OPEN ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1043 | c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1044 | if (sshbuf_len(c->output) > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1045 | FD_SET(c->wfd, writeset); | - |
1046 | } else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1047 | if (CHANNEL_EFD_OUTPUT_ACTIVE(c))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1048 | debug2("channel %d: " never executed: debug2("channel %d: " "obuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); | 0 |
1049 | "obuf_empty delayed efd %d/(%zu)", c->self, never executed: debug2("channel %d: " "obuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); | 0 |
1050 | c->efd, sshbuf_len(c->extended)); never executed: debug2("channel %d: " "obuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); | 0 |
1051 | else | - |
1052 | chan_obuf_empty(ssh, c); never executed: chan_obuf_empty(ssh, c); | 0 |
1053 | } | - |
1054 | } never executed: end of block | 0 |
1055 | | - |
1056 | if (c->efd != -1 && !(c->istate == CHAN_INPUT_CLOSED &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1057 | c->ostate == CHAN_OUTPUT_CLOSED)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1058 | if (c->extended_usage == CHAN_EXTENDED_WRITE &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1059 | sshbuf_len(c->extended) > 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1060 | FD_SET(c->efd, writeset); never executed: kludge_FD_SET(c->efd, writeset); | 0 |
1061 | else if (c->efd != -1 && !(c->flags & CHAN_EOF_SENT) &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1062 | (c->extended_usage == CHAN_EXTENDED_READ ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1063 | c->extended_usage == CHAN_EXTENDED_IGNORE) &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1064 | sshbuf_len(c->extended) < c->remote_window)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1065 | FD_SET(c->efd, readset); never executed: kludge_FD_SET(c->efd, readset); | 0 |
1066 | } never executed: end of block | 0 |
1067 | | - |
1068 | } never executed: end of block | 0 |
1069 | | - |
1070 | | - |
1071 | | - |
1072 | | - |
1073 | | - |
1074 | | - |
1075 | | - |
1076 | | - |
1077 | | - |
1078 | | - |
1079 | static int | - |
1080 | x11_open_helper(struct ssh *ssh, struct sshbuf *b) | - |
1081 | { | - |
1082 | struct ssh_channels *sc = ssh->chanctxt; | - |
1083 | u_char *ucp; | - |
1084 | u_int proto_len, data_len; | - |
1085 | | - |
1086 | | - |
1087 | if (sc->x11_refuse_time != 0 &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1088 | (u_int)monotime() >= sc->x11_refuse_time) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1089 | verbose("Rejected X11 connection after ForwardX11Timeout " | - |
1090 | "expired"); | - |
1091 | return -1; never executed: return -1; | 0 |
1092 | } | - |
1093 | | - |
1094 | | - |
1095 | if (sshbuf_len(b) < 12)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1096 | return 0; never executed: return 0; | 0 |
1097 | | - |
1098 | | - |
1099 | ucp = sshbuf_mutable_ptr(b); | - |
1100 | if (ucp[0] == 0x42) { TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1101 | proto_len = 256 * ucp[6] + ucp[7]; | - |
1102 | data_len = 256 * ucp[8] + ucp[9]; | - |
1103 | } else if (ucp[0] == 0x6c) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1104 | proto_len = ucp[6] + 256 * ucp[7]; | - |
1105 | data_len = ucp[8] + 256 * ucp[9]; | - |
1106 | } else { never executed: end of block | 0 |
1107 | debug2("Initial X11 packet contains bad byte order byte: 0x%x", | - |
1108 | ucp[0]); | - |
1109 | return -1; never executed: return -1; | 0 |
1110 | } | - |
1111 | | - |
1112 | | - |
1113 | if (sshbuf_len(b) <TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1114 | 12 + ((proto_len + 3) & ~3) + ((data_len + 3) & ~3))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1115 | return 0; never executed: return 0; | 0 |
1116 | | - |
1117 | | - |
1118 | if (proto_len != strlen(sc->x11_saved_proto) ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1119 | memcmp(ucp + 12, sc->x11_saved_proto, proto_len) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1120 | debug2("X11 connection uses different authentication protocol."); | - |
1121 | return -1; never executed: return -1; | 0 |
1122 | } | - |
1123 | | - |
1124 | if (data_len != sc->x11_fake_data_len ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1125 | timingsafe_bcmp(ucp + 12 + ((proto_len + 3) & ~3),TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1126 | sc->x11_fake_data, sc->x11_fake_data_len) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1127 | debug2("X11 auth data does not match fake data."); | - |
1128 | return -1; never executed: return -1; | 0 |
1129 | } | - |
1130 | | - |
1131 | if (sc->x11_fake_data_len != sc->x11_saved_data_len) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1132 | error("X11 fake_data_len %d != saved_data_len %d", | - |
1133 | sc->x11_fake_data_len, sc->x11_saved_data_len); | - |
1134 | return -1; never executed: return -1; | 0 |
1135 | } | - |
1136 | | - |
1137 | | - |
1138 | | - |
1139 | | - |
1140 | | - |
1141 | memcpy(ucp + 12 + ((proto_len + 3) & ~3), | - |
1142 | sc->x11_saved_data, sc->x11_saved_data_len); | - |
1143 | return 1; never executed: return 1; | 0 |
1144 | } | - |
1145 | | - |
1146 | static void | - |
1147 | channel_pre_x11_open(struct ssh *ssh, Channel *c, | - |
1148 | fd_set *readset, fd_set *writeset) | - |
1149 | { | - |
1150 | int ret = x11_open_helper(ssh, c->output); | - |
1151 | | - |
1152 | | - |
1153 | | - |
1154 | if (ret == 1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1155 | c->type = SSH_CHANNEL_OPEN; | - |
1156 | channel_pre_open(ssh, c, readset, writeset); | - |
1157 | } else if (ret == -1) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1158 | logit("X11 connection rejected because of wrong authentication."); | - |
1159 | debug2("X11 rejected %d i%d/o%d", | - |
1160 | c->self, c->istate, c->ostate); | - |
1161 | chan_read_failed(ssh, c); | - |
1162 | sshbuf_reset(c->input); | - |
1163 | chan_ibuf_empty(ssh, c); | - |
1164 | sshbuf_reset(c->output); | - |
1165 | chan_write_failed(ssh, c); | - |
1166 | debug2("X11 closed %d i%d/o%d", c->self, c->istate, c->ostate); | - |
1167 | } never executed: end of block | 0 |
1168 | } never executed: end of block | 0 |
1169 | | - |
1170 | static void | - |
1171 | channel_pre_mux_client(struct ssh *ssh, | - |
1172 | Channel *c, fd_set *readset, fd_set *writeset) | - |
1173 | { | - |
1174 | if (c->istate == CHAN_INPUT_OPEN && !c->mux_pause &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1175 | sshbuf_check_reserve(c->input, CHAN_RBUF) == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1176 | FD_SET(c->rfd, readset); never executed: kludge_FD_SET(c->rfd, readset); | 0 |
1177 | if (c->istate == CHAN_INPUT_WAIT_DRAIN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1178 | | - |
1179 | sshbuf_reset(c->input); | - |
1180 | chan_ibuf_empty(ssh, c); | - |
1181 | | - |
1182 | chan_rcvd_oclose(ssh, c); | - |
1183 | } never executed: end of block | 0 |
1184 | if (c->ostate == CHAN_OUTPUT_OPEN ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1185 | c->ostate == CHAN_OUTPUT_WAIT_DRAIN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1186 | if (sshbuf_len(c->output) > 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1187 | FD_SET(c->wfd, writeset); never executed: kludge_FD_SET(c->wfd, writeset); | 0 |
1188 | else if (c->ostate == CHAN_OUTPUT_WAIT_DRAIN)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1189 | chan_obuf_empty(ssh, c); never executed: chan_obuf_empty(ssh, c); | 0 |
1190 | } never executed: end of block | 0 |
1191 | } never executed: end of block | 0 |
1192 | | - |
1193 | | - |
1194 | static int | - |
1195 | channel_decode_socks4(Channel *c, struct sshbuf *input, struct sshbuf *output) | - |
1196 | { | - |
1197 | const u_char *p; | - |
1198 | char *host; | - |
1199 | u_int len, have, i, found, need; | - |
1200 | char username[256]; | - |
1201 | struct { | - |
1202 | u_int8_t version; | - |
1203 | u_int8_t command; | - |
1204 | u_int16_t dest_port; | - |
1205 | struct in_addr dest_addr; | - |
1206 | } s4_req, s4_rsp; | - |
1207 | int r; | - |
1208 | | - |
1209 | debug2("channel %d: decode socks4", c->self); | - |
1210 | | - |
1211 | have = sshbuf_len(input); | - |
1212 | len = sizeof(s4_req); | - |
1213 | if (have < len)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1214 | return 0; never executed: return 0; | 0 |
1215 | p = sshbuf_ptr(input); | - |
1216 | | - |
1217 | need = 1; | - |
1218 | | - |
1219 | if (p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] != 0) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1220 | debug2("channel %d: socks4a request", c->self); | - |
1221 | | - |
1222 | need = 2; | - |
1223 | } never executed: end of block | 0 |
1224 | | - |
1225 | for (found = 0, i = len; i < have; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1226 | if (p[i] == '\0') {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1227 | found++; | - |
1228 | if (found == need)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1229 | break; never executed: break; | 0 |
1230 | } never executed: end of block | 0 |
1231 | if (i > 1024) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1232 | | - |
1233 | debug("channel %d: decode socks4: too long", | - |
1234 | c->self); | - |
1235 | return -1; never executed: return -1; | 0 |
1236 | } | - |
1237 | } never executed: end of block | 0 |
1238 | if (found < need)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1239 | return 0; never executed: return 0; | 0 |
1240 | if ((r = sshbuf_get(input, &s4_req.version, 1)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1241 | (r = sshbuf_get(input, &s4_req.command, 1)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1242 | (r = sshbuf_get(input, &s4_req.dest_port, 2)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1243 | (r = sshbuf_get(input, &s4_req.dest_addr, 4)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1244 | debug("channels %d: decode socks4: %s", c->self, ssh_err(r)); | - |
1245 | return -1; never executed: return -1; | 0 |
1246 | } | - |
1247 | have = sshbuf_len(input); | - |
1248 | p = sshbuf_ptr(input); | - |
1249 | if (memchr(p, '\0', have) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1250 | error("channel %d: decode socks4: user not nul terminated", | - |
1251 | c->self); | - |
1252 | return -1; never executed: return -1; | 0 |
1253 | } | - |
1254 | len = strlen(p); | - |
1255 | debug2("channel %d: decode socks4: user %s/%d", c->self, p, len); | - |
1256 | len++; | - |
1257 | strlcpy(username, p, sizeof(username)); | - |
1258 | if ((r = sshbuf_consume(input, len)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1259 | fatal("%s: channel %d: consume: %s", __func__, | - |
1260 | c->self, ssh_err(r)); | - |
1261 | } never executed: end of block | 0 |
1262 | free(c->path); | - |
1263 | c->path = NULL; | - |
1264 | if (need == 1) { TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1265 | host = inet_ntoa(s4_req.dest_addr); | - |
1266 | c->path = xstrdup(host); | - |
1267 | } else { never executed: end of block | 0 |
1268 | have = sshbuf_len(input); | - |
1269 | p = sshbuf_ptr(input); | - |
1270 | if (memchr(p, '\0', have) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1271 | error("channel %d: decode socks4a: host not nul " | - |
1272 | "terminated", c->self); | - |
1273 | return -1; never executed: return -1; | 0 |
1274 | } | - |
1275 | len = strlen(p); | - |
1276 | debug2("channel %d: decode socks4a: host %s/%d", | - |
1277 | c->self, p, len); | - |
1278 | len++; | - |
1279 | if (len > NI_MAXHOST) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1280 | error("channel %d: hostname \"%.100s\" too long", | - |
1281 | c->self, p); | - |
1282 | return -1; never executed: return -1; | 0 |
1283 | } | - |
1284 | c->path = xstrdup(p); | - |
1285 | if ((r = sshbuf_consume(input, len)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1286 | fatal("%s: channel %d: consume: %s", __func__, | - |
1287 | c->self, ssh_err(r)); | - |
1288 | } never executed: end of block | 0 |
1289 | } never executed: end of block | 0 |
1290 | c->host_port = ntohs(s4_req.dest_port); never executed: __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8))); never executed: __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1291 | | - |
1292 | debug2("channel %d: dynamic request: socks4 host %s port %u command %u", | - |
1293 | c->self, c->path, c->host_port, s4_req.command); | - |
1294 | | - |
1295 | if (s4_req.command != 1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1296 | debug("channel %d: cannot handle: %s cn %d", | - |
1297 | c->self, need == 1 ? "SOCKS4" : "SOCKS4A", s4_req.command); | - |
1298 | return -1; never executed: return -1; | 0 |
1299 | } | - |
1300 | s4_rsp.version = 0; | - |
1301 | s4_rsp.command = 90; | - |
1302 | s4_rsp.dest_port = 0; | - |
1303 | s4_rsp.dest_addr.s_addr = INADDR_ANY; | - |
1304 | if ((r = sshbuf_put(output, &s4_rsp, sizeof(s4_rsp))) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1305 | fatal("%s: channel %d: append reply: %s", __func__, | - |
1306 | c->self, ssh_err(r)); | - |
1307 | } never executed: end of block | 0 |
1308 | return 1; never executed: return 1; | 0 |
1309 | } | - |
1310 | | - |
1311 | | - |
1312 | #define SSH_SOCKS5_AUTHDONE 0x1000 | - |
1313 | #define SSH_SOCKS5_NOAUTH 0x00 | - |
1314 | #define SSH_SOCKS5_IPV4 0x01 | - |
1315 | #define SSH_SOCKS5_DOMAIN 0x03 | - |
1316 | #define SSH_SOCKS5_IPV6 0x04 | - |
1317 | #define SSH_SOCKS5_CONNECT 0x01 | - |
1318 | #define SSH_SOCKS5_SUCCESS 0x00 | - |
1319 | | - |
1320 | static int | - |
1321 | channel_decode_socks5(Channel *c, struct sshbuf *input, struct sshbuf *output) | - |
1322 | { | - |
1323 | | - |
1324 | struct { | - |
1325 | u_int8_t version; | - |
1326 | u_int8_t command; | - |
1327 | u_int8_t reserved; | - |
1328 | u_int8_t atyp; | - |
1329 | } s5_req, s5_rsp; | - |
1330 | u_int16_t dest_port; | - |
1331 | char dest_addr[255+1], ntop[INET6_ADDRSTRLEN]; | - |
1332 | const u_char *p; | - |
1333 | u_int have, need, i, found, nmethods, addrlen, af; | - |
1334 | int r; | - |
1335 | | - |
1336 | debug2("channel %d: decode socks5", c->self); | - |
1337 | p = sshbuf_ptr(input); | - |
1338 | if (p[0] != 0x05)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1339 | return -1; never executed: return -1; | 0 |
1340 | have = sshbuf_len(input); | - |
1341 | if (!(c->flags & SSH_SOCKS5_AUTHDONE)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1342 | | - |
1343 | if (have < 2)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1344 | return 0; never executed: return 0; | 0 |
1345 | nmethods = p[1]; | - |
1346 | if (have < nmethods + 2)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1347 | return 0; never executed: return 0; | 0 |
1348 | | - |
1349 | for (found = 0, i = 2; i < nmethods + 2; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1350 | if (p[i] == SSH_SOCKS5_NOAUTH) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1351 | found = 1; | - |
1352 | break; never executed: break; | 0 |
1353 | } | - |
1354 | } never executed: end of block | 0 |
1355 | if (!found) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1356 | debug("channel %d: method SSH_SOCKS5_NOAUTH not found", | - |
1357 | c->self); | - |
1358 | return -1; never executed: return -1; | 0 |
1359 | } | - |
1360 | if ((r = sshbuf_consume(input, nmethods + 2)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1361 | fatal("%s: channel %d: consume: %s", __func__, | - |
1362 | c->self, ssh_err(r)); | - |
1363 | } never executed: end of block | 0 |
1364 | | - |
1365 | if ((r = sshbuf_put_u8(output, 0x05)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1366 | (r = sshbuf_put_u8(output, SSH_SOCKS5_NOAUTH)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1367 | fatal("%s: channel %d: append reply: %s", __func__, | - |
1368 | c->self, ssh_err(r)); | - |
1369 | } never executed: end of block | 0 |
1370 | c->flags |= SSH_SOCKS5_AUTHDONE; | - |
1371 | debug2("channel %d: socks5 auth done", c->self); | - |
1372 | return 0; never executed: return 0; | 0 |
1373 | } | - |
1374 | debug2("channel %d: socks5 post auth", c->self); | - |
1375 | if (have < sizeof(s5_req)+1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1376 | return 0; never executed: return 0; | 0 |
1377 | memcpy(&s5_req, p, sizeof(s5_req)); | - |
1378 | if (s5_req.version != 0x05 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1379 | s5_req.command != SSH_SOCKS5_CONNECT ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1380 | s5_req.reserved != 0x00) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1381 | debug2("channel %d: only socks5 connect supported", c->self); | - |
1382 | return -1; never executed: return -1; | 0 |
1383 | } | - |
1384 | switch (s5_req.atyp){ | - |
1385 | case SSH_SOCKS5_IPV4: never executed: case 0x01: | 0 |
1386 | addrlen = 4; | - |
1387 | af = AF_INET; | - |
1388 | break; never executed: break; | 0 |
1389 | case SSH_SOCKS5_DOMAIN: never executed: case 0x03: | 0 |
1390 | addrlen = p[sizeof(s5_req)]; | - |
1391 | af = -1; | - |
1392 | break; never executed: break; | 0 |
1393 | case SSH_SOCKS5_IPV6: never executed: case 0x04: | 0 |
1394 | addrlen = 16; | - |
1395 | af = AF_INET6; | - |
1396 | break; never executed: break; | 0 |
1397 | default: never executed: default: | 0 |
1398 | debug2("channel %d: bad socks5 atyp %d", c->self, s5_req.atyp); | - |
1399 | return -1; never executed: return -1; | 0 |
1400 | } | - |
1401 | need = sizeof(s5_req) + addrlen + 2; | - |
1402 | if (s5_req.atyp == SSH_SOCKS5_DOMAIN)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1403 | need++; never executed: need++; | 0 |
1404 | if (have < need)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1405 | return 0; never executed: return 0; | 0 |
1406 | if ((r = sshbuf_consume(input, sizeof(s5_req))) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1407 | fatal("%s: channel %d: consume: %s", __func__, | - |
1408 | c->self, ssh_err(r)); | - |
1409 | } never executed: end of block | 0 |
1410 | if (s5_req.atyp == SSH_SOCKS5_DOMAIN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1411 | | - |
1412 | if ((r = sshbuf_consume(input, 1)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1413 | fatal("%s: channel %d: consume: %s", __func__, | - |
1414 | c->self, ssh_err(r)); | - |
1415 | } never executed: end of block | 0 |
1416 | } never executed: end of block | 0 |
1417 | if ((r = sshbuf_get(input, &dest_addr, addrlen)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1418 | (r = sshbuf_get(input, &dest_port, 2)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1419 | debug("channel %d: parse addr/port: %s", c->self, ssh_err(r)); | - |
1420 | return -1; never executed: return -1; | 0 |
1421 | } | - |
1422 | dest_addr[addrlen] = '\0'; | - |
1423 | free(c->path); | - |
1424 | c->path = NULL; | - |
1425 | if (s5_req.atyp == SSH_SOCKS5_DOMAIN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1426 | if (addrlen >= NI_MAXHOST) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1427 | error("channel %d: dynamic request: socks5 hostname " | - |
1428 | "\"%.100s\" too long", c->self, dest_addr); | - |
1429 | return -1; never executed: return -1; | 0 |
1430 | } | - |
1431 | c->path = xstrdup(dest_addr); | - |
1432 | } else { never executed: end of block | 0 |
1433 | if (inet_ntop(af, dest_addr, ntop, sizeof(ntop)) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1434 | return -1; never executed: return -1; | 0 |
1435 | c->path = xstrdup(ntop); | - |
1436 | } never executed: end of block | 0 |
1437 | c->host_port = ntohs(dest_port); never executed: __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8))); never executed: __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1438 | | - |
1439 | debug2("channel %d: dynamic request: socks5 host %s port %u command %u", | - |
1440 | c->self, c->path, c->host_port, s5_req.command); | - |
1441 | | - |
1442 | s5_rsp.version = 0x05; | - |
1443 | s5_rsp.command = SSH_SOCKS5_SUCCESS; | - |
1444 | s5_rsp.reserved = 0; | - |
1445 | s5_rsp.atyp = SSH_SOCKS5_IPV4; | - |
1446 | dest_port = 0; | - |
1447 | | - |
1448 | if ((r = sshbuf_put(output, &s5_rsp, sizeof(s5_rsp))) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1449 | (r = sshbuf_put_u32(output, ntohl(INADDR_ANY))) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1450 | (r = sshbuf_put(output, &dest_port, sizeof(dest_port))) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1451 | fatal("%s: channel %d: append reply: %s", __func__, never executed: fatal("%s: channel %d: append reply: %s", __func__, c->self, ssh_err(r)); | 0 |
1452 | c->self, ssh_err(r)); never executed: fatal("%s: channel %d: append reply: %s", __func__, c->self, ssh_err(r)); | 0 |
1453 | return 1; never executed: return 1; | 0 |
1454 | } | - |
1455 | | - |
1456 | Channel * | - |
1457 | channel_connect_stdio_fwd(struct ssh *ssh, | - |
1458 | const char *host_to_connect, u_short port_to_connect, int in, int out) | - |
1459 | { | - |
1460 | Channel *c; | - |
1461 | | - |
1462 | debug("%s %s:%d", __func__, host_to_connect, port_to_connect); | - |
1463 | | - |
1464 | c = channel_new(ssh, "stdio-forward", SSH_CHANNEL_OPENING, in, out, | - |
1465 | -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | - |
1466 | 0, "stdio-forward", 0); | - |
1467 | | - |
1468 | c->path = xstrdup(host_to_connect); | - |
1469 | c->host_port = port_to_connect; | - |
1470 | c->listening_port = 0; | - |
1471 | c->force_drain = 1; | - |
1472 | | - |
1473 | channel_register_fds(ssh, c, in, out, -1, 0, 1, 0); | - |
1474 | port_open_helper(ssh, c, "direct-tcpip"); | - |
1475 | | - |
1476 | return c; never executed: return c; | 0 |
1477 | } | - |
1478 | | - |
1479 | | - |
1480 | static void | - |
1481 | channel_pre_dynamic(struct ssh *ssh, Channel *c, | - |
1482 | fd_set *readset, fd_set *writeset) | - |
1483 | { | - |
1484 | const u_char *p; | - |
1485 | u_int have; | - |
1486 | int ret; | - |
1487 | | - |
1488 | have = sshbuf_len(c->input); | - |
1489 | debug2("channel %d: pre_dynamic: have %d", c->self, have); | - |
1490 | | - |
1491 | | - |
1492 | if (have < 3) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1493 | | - |
1494 | FD_SET(c->sock, readset); | - |
1495 | return; never executed: return; | 0 |
1496 | } | - |
1497 | | - |
1498 | p = sshbuf_ptr(c->input); | - |
1499 | | - |
1500 | switch (p[0]) { | - |
1501 | case 0x04: never executed: case 0x04: | 0 |
1502 | ret = channel_decode_socks4(c, c->input, c->output); | - |
1503 | break; never executed: break; | 0 |
1504 | case 0x05: never executed: case 0x05: | 0 |
1505 | ret = channel_decode_socks5(c, c->input, c->output); | - |
1506 | break; never executed: break; | 0 |
1507 | default: never executed: default: | 0 |
1508 | ret = -1; | - |
1509 | break; never executed: break; | 0 |
1510 | } | - |
1511 | if (ret < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1512 | chan_mark_dead(ssh, c); | - |
1513 | } else if (ret == 0) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1514 | debug2("channel %d: pre_dynamic: need more", c->self); | - |
1515 | | - |
1516 | FD_SET(c->sock, readset); | - |
1517 | if (sshbuf_len(c->output))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1518 | FD_SET(c->sock, writeset); never executed: kludge_FD_SET(c->sock, writeset); | 0 |
1519 | } else { never executed: end of block | 0 |
1520 | | - |
1521 | c->type = SSH_CHANNEL_OPENING; | - |
1522 | port_open_helper(ssh, c, "direct-tcpip"); | - |
1523 | } never executed: end of block | 0 |
1524 | } | - |
1525 | | - |
1526 | | - |
1527 | static void | - |
1528 | rdynamic_close(struct ssh *ssh, Channel *c) | - |
1529 | { | - |
1530 | c->type = SSH_CHANNEL_OPEN; | - |
1531 | chan_read_failed(ssh, c); | - |
1532 | sshbuf_reset(c->input); | - |
1533 | chan_ibuf_empty(ssh, c); | - |
1534 | sshbuf_reset(c->output); | - |
1535 | chan_write_failed(ssh, c); | - |
1536 | } never executed: end of block | 0 |
1537 | | - |
1538 | | - |
1539 | static void | - |
1540 | channel_before_prepare_select_rdynamic(struct ssh *ssh, Channel *c) | - |
1541 | { | - |
1542 | const u_char *p; | - |
1543 | u_int have, len; | - |
1544 | int r, ret; | - |
1545 | | - |
1546 | have = sshbuf_len(c->output); | - |
1547 | debug2("channel %d: pre_rdynamic: have %d", c->self, have); | - |
1548 | | - |
1549 | | - |
1550 | if (c->flags & CHAN_EOF_RCVD) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1551 | if ((r = sshbuf_consume(c->output, have)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1552 | fatal("%s: channel %d: consume: %s", | - |
1553 | __func__, c->self, ssh_err(r)); | - |
1554 | } never executed: end of block | 0 |
1555 | rdynamic_close(ssh, c); | - |
1556 | return; never executed: return; | 0 |
1557 | } | - |
1558 | | - |
1559 | if (have < 3)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1560 | return; never executed: return; | 0 |
1561 | | - |
1562 | p = sshbuf_ptr(c->output); | - |
1563 | switch (p[0]) { | - |
1564 | case 0x04: never executed: case 0x04: | 0 |
1565 | | - |
1566 | ret = channel_decode_socks4(c, c->output, c->input); | - |
1567 | break; never executed: break; | 0 |
1568 | case 0x05: never executed: case 0x05: | 0 |
1569 | ret = channel_decode_socks5(c, c->output, c->input); | - |
1570 | break; never executed: break; | 0 |
1571 | default: never executed: default: | 0 |
1572 | ret = -1; | - |
1573 | break; never executed: break; | 0 |
1574 | } | - |
1575 | if (ret < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1576 | rdynamic_close(ssh, c); | - |
1577 | } else if (ret == 0) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1578 | debug2("channel %d: pre_rdynamic: need more", c->self); | - |
1579 | | - |
1580 | len = sshbuf_len(c->input); | - |
1581 | if (len > 0 && len < c->remote_window) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1582 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1583 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1584 | (r = sshpkt_put_stringb(ssh, c->input)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1585 | (r = sshpkt_send(ssh)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1586 | fatal("%s: channel %i: rdynamic: %s", __func__, | - |
1587 | c->self, ssh_err(r)); | - |
1588 | } never executed: end of block | 0 |
1589 | if ((r = sshbuf_consume(c->input, len)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1590 | fatal("%s: channel %d: consume: %s", | - |
1591 | __func__, c->self, ssh_err(r)); | - |
1592 | } never executed: end of block | 0 |
1593 | c->remote_window -= len; | - |
1594 | } never executed: end of block | 0 |
1595 | } else if (rdynamic_connect_finish(ssh, c) < 0) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1596 | | - |
1597 | rdynamic_close(ssh, c); | - |
1598 | } never executed: end of block | 0 |
1599 | } never executed: end of block | 0 |
1600 | | - |
1601 | | - |
1602 | static void | - |
1603 | channel_post_x11_listener(struct ssh *ssh, Channel *c, | - |
1604 | fd_set *readset, fd_set *writeset) | - |
1605 | { | - |
1606 | Channel *nc; | - |
1607 | struct sockaddr_storage addr; | - |
1608 | int r, newsock, oerrno, remote_port; | - |
1609 | socklen_t addrlen; | - |
1610 | char buf[16384], *remote_ipaddr; | - |
1611 | | - |
1612 | if (!FD_ISSET(c->sock, readset))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1613 | return; never executed: return; | 0 |
1614 | | - |
1615 | debug("X11 connection requested."); | - |
1616 | addrlen = sizeof(addr); | - |
1617 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | - |
1618 | if (c->single_connection) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1619 | oerrno = errno; | - |
1620 | debug2("single_connection: closing X11 listener."); | - |
1621 | channel_close_fd(ssh, &c->sock); | - |
1622 | chan_mark_dead(ssh, c); | - |
1623 | errno = oerrno; | - |
1624 | } never executed: end of block | 0 |
1625 | if (newsock < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1626 | if (errno != EINTR && errno != EWOULDBLOCK &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1627 | errno != ECONNABORTED)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1628 | error("accept: %.100s", strerror(errno)); never executed: error("accept: %.100s", strerror( (*__errno_location ()) )); | 0 |
1629 | if (errno == EMFILE || errno == ENFILE)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1630 | c->notbefore = monotime() + 1; never executed: c->notbefore = monotime() + 1; | 0 |
1631 | return; never executed: return; | 0 |
1632 | } | - |
1633 | set_nodelay(newsock); | - |
1634 | remote_ipaddr = get_peer_ipaddr(newsock); | - |
1635 | remote_port = get_peer_port(newsock); | - |
1636 | snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", | - |
1637 | remote_ipaddr, remote_port); | - |
1638 | | - |
1639 | nc = channel_new(ssh, "accepted x11 socket", | - |
1640 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | - |
1641 | c->local_window_max, c->local_maxpacket, 0, buf, 1); | - |
1642 | open_preamble(ssh, __func__, nc, "x11"); | - |
1643 | if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1644 | (r = sshpkt_put_u32(ssh, remote_port)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1645 | fatal("%s: channel %i: reply %s", __func__, | - |
1646 | c->self, ssh_err(r)); | - |
1647 | } never executed: end of block | 0 |
1648 | if ((r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1649 | fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); never executed: fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); | 0 |
1650 | free(remote_ipaddr); | - |
1651 | } never executed: end of block | 0 |
1652 | | - |
1653 | static void | - |
1654 | port_open_helper(struct ssh *ssh, Channel *c, char *rtype) | - |
1655 | { | - |
1656 | char *local_ipaddr = get_local_ipaddr(c->sock); | - |
1657 | int local_port = c->sock == -1 ? 65536 : get_local_port(c->sock);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1658 | char *remote_ipaddr = get_peer_ipaddr(c->sock); | - |
1659 | int remote_port = get_peer_port(c->sock); | - |
1660 | int r; | - |
1661 | | - |
1662 | if (remote_port == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1663 | | - |
1664 | free(remote_ipaddr); | - |
1665 | remote_ipaddr = xstrdup("127.0.0.1"); | - |
1666 | remote_port = 65535; | - |
1667 | } never executed: end of block | 0 |
1668 | | - |
1669 | free(c->remote_name); | - |
1670 | xasprintf(&c->remote_name, | - |
1671 | "%s: listening port %d for %.100s port %d, " | - |
1672 | "connect from %.200s port %d to %.100s port %d", | - |
1673 | rtype, c->listening_port, c->path, c->host_port, | - |
1674 | remote_ipaddr, remote_port, local_ipaddr, local_port); | - |
1675 | | - |
1676 | open_preamble(ssh, __func__, c, rtype); | - |
1677 | if (strcmp(rtype, "direct-tcpip") == 0) { never executed: __result = (((const unsigned char *) (const char *) ( rtype ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "direct-tcpip" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1678 | | - |
1679 | if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1680 | (r = sshpkt_put_u32(ssh, c->host_port)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1681 | fatal("%s: channel %i: reply %s", __func__, | - |
1682 | c->self, ssh_err(r)); | - |
1683 | } never executed: end of block | 0 |
1684 | } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) { never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( rtype ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "direct-streamlocal@openssh.com" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1685 | | - |
1686 | if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1687 | fatal("%s: channel %i: reply %s", __func__, | - |
1688 | c->self, ssh_err(r)); | - |
1689 | } never executed: end of block | 0 |
1690 | } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( rtype ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "forwarded-streamlocal@openssh.com" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1691 | | - |
1692 | if ((r = sshpkt_put_cstring(ssh, c->path)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1693 | fatal("%s: channel %i: reply %s", __func__, | - |
1694 | c->self, ssh_err(r)); | - |
1695 | } never executed: end of block | 0 |
1696 | } else { never executed: end of block | 0 |
1697 | | - |
1698 | if ((r = sshpkt_put_cstring(ssh, c->path)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1699 | (r = sshpkt_put_u32(ssh, local_port)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1700 | fatal("%s: channel %i: reply %s", __func__, | - |
1701 | c->self, ssh_err(r)); | - |
1702 | } never executed: end of block | 0 |
1703 | } never executed: end of block | 0 |
1704 | if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) { never executed: __result = (((const unsigned char *) (const char *) ( rtype ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "forwarded-streamlocal@openssh.com" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1705 | | - |
1706 | if ((r = sshpkt_put_cstring(ssh, "")) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1707 | fatal("%s: channel %i: reply %s", __func__, | - |
1708 | c->self, ssh_err(r)); | - |
1709 | } never executed: end of block | 0 |
1710 | } else { never executed: end of block | 0 |
1711 | | - |
1712 | if ((r = sshpkt_put_cstring(ssh, remote_ipaddr)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1713 | (r = sshpkt_put_u32(ssh, (u_int)remote_port)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1714 | fatal("%s: channel %i: reply %s", __func__, | - |
1715 | c->self, ssh_err(r)); | - |
1716 | } never executed: end of block | 0 |
1717 | } never executed: end of block | 0 |
1718 | if ((r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1719 | fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); never executed: fatal("%s: channel %i: send %s", __func__, c->self, ssh_err(r)); | 0 |
1720 | free(remote_ipaddr); | - |
1721 | free(local_ipaddr); | - |
1722 | } never executed: end of block | 0 |
1723 | | - |
1724 | void | - |
1725 | channel_set_x11_refuse_time(struct ssh *ssh, u_int refuse_time) | - |
1726 | { | - |
1727 | ssh->chanctxt->x11_refuse_time = refuse_time; | - |
1728 | } never executed: end of block | 0 |
1729 | | - |
1730 | | - |
1731 | | - |
1732 | | - |
1733 | static void | - |
1734 | channel_post_port_listener(struct ssh *ssh, Channel *c, | - |
1735 | fd_set *readset, fd_set *writeset) | - |
1736 | { | - |
1737 | Channel *nc; | - |
1738 | struct sockaddr_storage addr; | - |
1739 | int newsock, nextstate; | - |
1740 | socklen_t addrlen; | - |
1741 | char *rtype; | - |
1742 | | - |
1743 | if (!FD_ISSET(c->sock, readset))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1744 | return; never executed: return; | 0 |
1745 | | - |
1746 | debug("Connection to port %d forwarding to %.100s port %d requested.", | - |
1747 | c->listening_port, c->path, c->host_port); | - |
1748 | | - |
1749 | if (c->type == SSH_CHANNEL_RPORT_LISTENER) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1750 | nextstate = SSH_CHANNEL_OPENING; | - |
1751 | rtype = "forwarded-tcpip"; | - |
1752 | } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1753 | nextstate = SSH_CHANNEL_OPENING; | - |
1754 | rtype = "forwarded-streamlocal@openssh.com"; | - |
1755 | } else if (c->host_port == PORT_STREAMLOCAL) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1756 | nextstate = SSH_CHANNEL_OPENING; | - |
1757 | rtype = "direct-streamlocal@openssh.com"; | - |
1758 | } else if (c->host_port == 0) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1759 | nextstate = SSH_CHANNEL_DYNAMIC; | - |
1760 | rtype = "dynamic-tcpip"; | - |
1761 | } else { never executed: end of block | 0 |
1762 | nextstate = SSH_CHANNEL_OPENING; | - |
1763 | rtype = "direct-tcpip"; | - |
1764 | } never executed: end of block | 0 |
1765 | | - |
1766 | addrlen = sizeof(addr); | - |
1767 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | - |
1768 | if (newsock < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1769 | if (errno != EINTR && errno != EWOULDBLOCK &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1770 | errno != ECONNABORTED)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1771 | error("accept: %.100s", strerror(errno)); never executed: error("accept: %.100s", strerror( (*__errno_location ()) )); | 0 |
1772 | if (errno == EMFILE || errno == ENFILE)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1773 | c->notbefore = monotime() + 1; never executed: c->notbefore = monotime() + 1; | 0 |
1774 | return; never executed: return; | 0 |
1775 | } | - |
1776 | if (c->host_port != PORT_STREAMLOCAL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1777 | set_nodelay(newsock); never executed: set_nodelay(newsock); | 0 |
1778 | nc = channel_new(ssh, rtype, nextstate, newsock, newsock, -1, | - |
1779 | c->local_window_max, c->local_maxpacket, 0, rtype, 1); | - |
1780 | nc->listening_port = c->listening_port; | - |
1781 | nc->host_port = c->host_port; | - |
1782 | if (c->path != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1783 | nc->path = xstrdup(c->path); never executed: nc->path = xstrdup(c->path); | 0 |
1784 | | - |
1785 | if (nextstate != SSH_CHANNEL_DYNAMIC)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1786 | port_open_helper(ssh, nc, rtype); never executed: port_open_helper(ssh, nc, rtype); | 0 |
1787 | } never executed: end of block | 0 |
1788 | | - |
1789 | | - |
1790 | | - |
1791 | | - |
1792 | | - |
1793 | static void | - |
1794 | channel_post_auth_listener(struct ssh *ssh, Channel *c, | - |
1795 | fd_set *readset, fd_set *writeset) | - |
1796 | { | - |
1797 | Channel *nc; | - |
1798 | int r, newsock; | - |
1799 | struct sockaddr_storage addr; | - |
1800 | socklen_t addrlen; | - |
1801 | | - |
1802 | if (!FD_ISSET(c->sock, readset))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1803 | return; never executed: return; | 0 |
1804 | | - |
1805 | addrlen = sizeof(addr); | - |
1806 | newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen); | - |
1807 | if (newsock < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1808 | error("accept from auth socket: %.100s", strerror(errno)); | - |
1809 | if (errno == EMFILE || errno == ENFILE)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1810 | c->notbefore = monotime() + 1; never executed: c->notbefore = monotime() + 1; | 0 |
1811 | return; never executed: return; | 0 |
1812 | } | - |
1813 | nc = channel_new(ssh, "accepted auth socket", | - |
1814 | SSH_CHANNEL_OPENING, newsock, newsock, -1, | - |
1815 | c->local_window_max, c->local_maxpacket, | - |
1816 | 0, "accepted auth socket", 1); | - |
1817 | open_preamble(ssh, __func__, nc, "auth-agent@openssh.com"); | - |
1818 | if ((r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1819 | fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); never executed: fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | 0 |
1820 | } never executed: end of block | 0 |
1821 | | - |
1822 | static void | - |
1823 | channel_post_connecting(struct ssh *ssh, Channel *c, | - |
1824 | fd_set *readset, fd_set *writeset) | - |
1825 | { | - |
1826 | int err = 0, sock, isopen, r; | - |
1827 | socklen_t sz = sizeof(err); | - |
1828 | | - |
1829 | if (!FD_ISSET(c->sock, writeset))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1830 | return; never executed: return; | 0 |
1831 | if (!c->have_remote_id)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1832 | fatal(":%s: channel %d: no remote id", __func__, c->self); never executed: fatal(":%s: channel %d: no remote id", __func__, c->self); | 0 |
1833 | | - |
1834 | isopen = (c->type == SSH_CHANNEL_RDYNAMIC_FINISH); | - |
1835 | if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &err, &sz) < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1836 | err = errno; | - |
1837 | error("getsockopt SO_ERROR failed"); | - |
1838 | } never executed: end of block | 0 |
1839 | if (err == 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1840 | debug("channel %d: connected to %s port %d", | - |
1841 | c->self, c->connect_ctx.host, c->connect_ctx.port); | - |
1842 | channel_connect_ctx_free(&c->connect_ctx); | - |
1843 | c->type = SSH_CHANNEL_OPEN; | - |
1844 | if (isopen) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1845 | | - |
1846 | } else { never executed: end of block | 0 |
1847 | if ((r = sshpkt_start(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1848 | SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1849 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1850 | (r = sshpkt_put_u32(ssh, c->self)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1851 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1852 | (r = sshpkt_put_u32(ssh, c->local_maxpacket))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1853 | != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1854 | fatal("%s: channel %i: confirm: %s", __func__, never executed: fatal("%s: channel %i: confirm: %s", __func__, c->self, ssh_err(r)); | 0 |
1855 | c->self, ssh_err(r)); never executed: fatal("%s: channel %i: confirm: %s", __func__, c->self, ssh_err(r)); | 0 |
1856 | if ((r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1857 | fatal("%s: channel %i: %s", __func__, c->self, never executed: fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | 0 |
1858 | ssh_err(r)); never executed: fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | 0 |
1859 | } never executed: end of block | 0 |
1860 | } else { | - |
1861 | debug("channel %d: connection failed: %s", | - |
1862 | c->self, strerror(err)); | - |
1863 | | - |
1864 | if ((sock = connect_next(&c->connect_ctx)) > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1865 | close(c->sock); | - |
1866 | c->sock = c->rfd = c->wfd = sock; | - |
1867 | channel_find_maxfd(ssh->chanctxt); | - |
1868 | return; never executed: return; | 0 |
1869 | } | - |
1870 | | - |
1871 | error("connect_to %.100s port %d: failed.", | - |
1872 | c->connect_ctx.host, c->connect_ctx.port); | - |
1873 | channel_connect_ctx_free(&c->connect_ctx); | - |
1874 | if (isopen) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1875 | rdynamic_close(ssh, c); | - |
1876 | } else { never executed: end of block | 0 |
1877 | if ((r = sshpkt_start(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1878 | SSH2_MSG_CHANNEL_OPEN_FAILURE)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1879 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1880 | (r = sshpkt_put_u32(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1881 | SSH2_OPEN_CONNECT_FAILED)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1882 | (r = sshpkt_put_cstring(ssh, strerror(err))) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1883 | (r = sshpkt_put_cstring(ssh, "")) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1884 | fatal("%s: channel %i: failure: %s", __func__, | - |
1885 | c->self, ssh_err(r)); | - |
1886 | } never executed: end of block | 0 |
1887 | if ((r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1888 | fatal("%s: channel %i: %s", __func__, c->self, never executed: fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | 0 |
1889 | ssh_err(r)); never executed: fatal("%s: channel %i: %s", __func__, c->self, ssh_err(r)); | 0 |
1890 | chan_mark_dead(ssh, c); | - |
1891 | } never executed: end of block | 0 |
1892 | } | - |
1893 | } | - |
1894 | | - |
1895 | static int | - |
1896 | channel_handle_rfd(struct ssh *ssh, Channel *c, | - |
1897 | fd_set *readset, fd_set *writeset) | - |
1898 | { | - |
1899 | char buf[CHAN_RBUF]; | - |
1900 | ssize_t len; | - |
1901 | int r, force; | - |
1902 | | - |
1903 | force = c->isatty && c->detach_close && c->istate != CHAN_INPUT_CLOSED;TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1904 | | - |
1905 | if (c->rfd == -1 || (!force && !FD_ISSET(c->rfd, readset)))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1906 | return 1; never executed: return 1; | 0 |
1907 | | - |
1908 | errno = 0; | - |
1909 | len = read(c->rfd, buf, sizeof(buf)); | - |
1910 | if (len < 0 && (errno == EINTR ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1911 | ((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1912 | return 1; never executed: return 1; | 0 |
1913 | #ifndef PTY_ZEROREAD | - |
1914 | if (len <= 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1915 | #else | - |
1916 | if ((!c->isatty && len <= 0) || | - |
1917 | (c->isatty && (len < 0 || (len == 0 && errno != 0)))) { | - |
1918 | #endif | - |
1919 | debug2("channel %d: read<=0 rfd %d len %zd", | - |
1920 | c->self, c->rfd, len); | - |
1921 | if (c->type != SSH_CHANNEL_OPEN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1922 | debug2("channel %d: not open", c->self); | - |
1923 | chan_mark_dead(ssh, c); | - |
1924 | return -1; never executed: return -1; | 0 |
1925 | } else { | - |
1926 | chan_read_failed(ssh, c); | - |
1927 | } never executed: end of block | 0 |
1928 | return -1; never executed: return -1; | 0 |
1929 | } | - |
1930 | if (c->input_filter != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1931 | if (c->input_filter(ssh, c, buf, len) == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1932 | debug2("channel %d: filter stops", c->self); | - |
1933 | chan_read_failed(ssh, c); | - |
1934 | } never executed: end of block | 0 |
1935 | } else if (c->datagram) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1936 | if ((r = sshbuf_put_string(c->input, buf, len)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1937 | fatal("%s: channel %d: put datagram: %s", __func__, never executed: fatal("%s: channel %d: put datagram: %s", __func__, c->self, ssh_err(r)); | 0 |
1938 | c->self, ssh_err(r)); never executed: fatal("%s: channel %d: put datagram: %s", __func__, c->self, ssh_err(r)); | 0 |
1939 | } else if ((r = sshbuf_put(c->input, buf, len)) != 0) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1940 | fatal("%s: channel %d: put data: %s", __func__, | - |
1941 | c->self, ssh_err(r)); | - |
1942 | } never executed: end of block | 0 |
1943 | return 1; never executed: return 1; | 0 |
1944 | } | - |
1945 | | - |
1946 | static int | - |
1947 | channel_handle_wfd(struct ssh *ssh, Channel *c, | - |
1948 | fd_set *readset, fd_set *writeset) | - |
1949 | { | - |
1950 | struct termios tio; | - |
1951 | u_char *data = NULL, *buf; | - |
1952 | size_t dlen, olen = 0; | - |
1953 | int r, len; | - |
1954 | | - |
1955 | if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1956 | sshbuf_len(c->output) == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1957 | return 1; never executed: return 1; | 0 |
1958 | | - |
1959 | | - |
1960 | olen = sshbuf_len(c->output); | - |
1961 | if (c->output_filter != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1962 | if ((buf = c->output_filter(ssh, c, &data, &dlen)) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1963 | debug2("channel %d: filter stops", c->self); | - |
1964 | if (c->type != SSH_CHANNEL_OPEN)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1965 | chan_mark_dead(ssh, c); never executed: chan_mark_dead(ssh, c); | 0 |
1966 | else | - |
1967 | chan_write_failed(ssh, c); never executed: chan_write_failed(ssh, c); | 0 |
1968 | return -1; never executed: return -1; | 0 |
1969 | } | - |
1970 | } else if (c->datagram) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1971 | if ((r = sshbuf_get_string(c->output, &data, &dlen)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1972 | fatal("%s: channel %d: get datagram: %s", __func__, never executed: fatal("%s: channel %d: get datagram: %s", __func__, c->self, ssh_err(r)); | 0 |
1973 | c->self, ssh_err(r)); never executed: fatal("%s: channel %d: get datagram: %s", __func__, c->self, ssh_err(r)); | 0 |
1974 | buf = data; | - |
1975 | } else { never executed: end of block | 0 |
1976 | buf = data = sshbuf_mutable_ptr(c->output); | - |
1977 | dlen = sshbuf_len(c->output); | - |
1978 | } never executed: end of block | 0 |
1979 | | - |
1980 | if (c->datagram) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1981 | | - |
1982 | len = write(c->wfd, buf, dlen); | - |
1983 | free(data); | - |
1984 | if (len < 0 && (errno == EINTR || errno == EAGAIN ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1985 | errno == EWOULDBLOCK))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1986 | return 1; never executed: return 1; | 0 |
1987 | if (len <= 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
1988 | goto write_fail; never executed: goto write_fail; | 0 |
1989 | goto out; never executed: goto out; | 0 |
1990 | } | - |
1991 | | - |
1992 | #ifdef _AIX | - |
1993 | | - |
1994 | if (c->wfd_isatty) | - |
1995 | dlen = MIN(dlen, 8*1024); | - |
1996 | #endif | - |
1997 | | - |
1998 | len = write(c->wfd, buf, dlen); | - |
1999 | if (len < 0 &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2000 | (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2001 | return 1; never executed: return 1; | 0 |
2002 | if (len <= 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2003 | write_fail: | - |
2004 | if (c->type != SSH_CHANNEL_OPEN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2005 | debug2("channel %d: not open", c->self); | - |
2006 | chan_mark_dead(ssh, c); | - |
2007 | return -1; never executed: return -1; | 0 |
2008 | } else { | - |
2009 | chan_write_failed(ssh, c); | - |
2010 | } never executed: end of block | 0 |
2011 | return -1; never executed: return -1; | 0 |
2012 | } | - |
2013 | #ifndef BROKEN_TCGETATTR_ICANON | - |
2014 | if (c->isatty && dlen >= 1 && buf[0] != '\r') {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2015 | if (tcgetattr(c->wfd, &tio) == 0 &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2016 | !(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2017 | | - |
2018 | | - |
2019 | | - |
2020 | | - |
2021 | | - |
2022 | | - |
2023 | if ((r = sshpkt_msg_ignore(ssh, 4+len)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2024 | (r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2025 | fatal("%s: channel %d: ignore: %s", never executed: fatal("%s: channel %d: ignore: %s", __func__, c->self, ssh_err(r)); | 0 |
2026 | __func__, c->self, ssh_err(r)); never executed: fatal("%s: channel %d: ignore: %s", __func__, c->self, ssh_err(r)); | 0 |
2027 | } never executed: end of block | 0 |
2028 | } never executed: end of block | 0 |
2029 | #endif /* BROKEN_TCGETATTR_ICANON */ | - |
2030 | if ((r = sshbuf_consume(c->output, len)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2031 | fatal("%s: channel %d: consume: %s", | - |
2032 | __func__, c->self, ssh_err(r)); | - |
2033 | } never executed: end of block | 0 |
2034 | out: code before this statement never executed: out: | 0 |
2035 | c->local_consumed += olen - sshbuf_len(c->output); | - |
2036 | | - |
2037 | return 1; never executed: return 1; | 0 |
2038 | } | - |
2039 | | - |
2040 | static int | - |
2041 | channel_handle_efd_write(struct ssh *ssh, Channel *c, | - |
2042 | fd_set *readset, fd_set *writeset) | - |
2043 | { | - |
2044 | int r; | - |
2045 | ssize_t len; | - |
2046 | | - |
2047 | if (!FD_ISSET(c->efd, writeset) || sshbuf_len(c->extended) == 0)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2048 | return 1; never executed: return 1; | 0 |
2049 | | - |
2050 | len = write(c->efd, sshbuf_ptr(c->extended), | - |
2051 | sshbuf_len(c->extended)); | - |
2052 | debug2("channel %d: written %zd to efd %d", c->self, len, c->efd); | - |
2053 | if (len < 0 && (errno == EINTR || errno == EAGAIN ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2054 | errno == EWOULDBLOCK))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2055 | return 1; never executed: return 1; | 0 |
2056 | if (len <= 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2057 | debug2("channel %d: closing write-efd %d", c->self, c->efd); | - |
2058 | channel_close_fd(ssh, &c->efd); | - |
2059 | } else { never executed: end of block | 0 |
2060 | if ((r = sshbuf_consume(c->extended, len)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2061 | fatal("%s: channel %d: consume: %s", | - |
2062 | __func__, c->self, ssh_err(r)); | - |
2063 | } never executed: end of block | 0 |
2064 | c->local_consumed += len; | - |
2065 | } never executed: end of block | 0 |
2066 | return 1; never executed: return 1; | 0 |
2067 | } | - |
2068 | | - |
2069 | static int | - |
2070 | channel_handle_efd_read(struct ssh *ssh, Channel *c, | - |
2071 | fd_set *readset, fd_set *writeset) | - |
2072 | { | - |
2073 | char buf[CHAN_RBUF]; | - |
2074 | int r; | - |
2075 | ssize_t len; | - |
2076 | | - |
2077 | if (!c->detach_close && !FD_ISSET(c->efd, readset))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2078 | return 1; never executed: return 1; | 0 |
2079 | | - |
2080 | len = read(c->efd, buf, sizeof(buf)); | - |
2081 | debug2("channel %d: read %zd from efd %d", c->self, len, c->efd); | - |
2082 | if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2083 | errno == EWOULDBLOCK) && !c->detach_close)))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2084 | return 1; never executed: return 1; | 0 |
2085 | if (len <= 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2086 | debug2("channel %d: closing read-efd %d", | - |
2087 | c->self, c->efd); | - |
2088 | channel_close_fd(ssh, &c->efd); | - |
2089 | } else { never executed: end of block | 0 |
2090 | if (c->extended_usage == CHAN_EXTENDED_IGNORE) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2091 | debug3("channel %d: discard efd", | - |
2092 | c->self); | - |
2093 | } else if ((r = sshbuf_put(c->extended, buf, len)) != 0) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2094 | fatal("%s: channel %d: append: %s", | - |
2095 | __func__, c->self, ssh_err(r)); | - |
2096 | } never executed: end of block | 0 |
2097 | } never executed: end of block | 0 |
2098 | return 1; never executed: return 1; | 0 |
2099 | } | - |
2100 | | - |
2101 | static int | - |
2102 | channel_handle_efd(struct ssh *ssh, Channel *c, | - |
2103 | fd_set *readset, fd_set *writeset) | - |
2104 | { | - |
2105 | if (c->efd == -1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2106 | return 1; never executed: return 1; | 0 |
2107 | | - |
2108 | | - |
2109 | | - |
2110 | if (c->extended_usage == CHAN_EXTENDED_WRITE)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2111 | return channel_handle_efd_write(ssh, c, readset, writeset); never executed: return channel_handle_efd_write(ssh, c, readset, writeset); | 0 |
2112 | else if (c->extended_usage == CHAN_EXTENDED_READ ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2113 | c->extended_usage == CHAN_EXTENDED_IGNORE)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2114 | return channel_handle_efd_read(ssh, c, readset, writeset); never executed: return channel_handle_efd_read(ssh, c, readset, writeset); | 0 |
2115 | | - |
2116 | return 1; never executed: return 1; | 0 |
2117 | } | - |
2118 | | - |
2119 | static int | - |
2120 | channel_check_window(struct ssh *ssh, Channel *c) | - |
2121 | { | - |
2122 | int r; | - |
2123 | | - |
2124 | if (c->type == SSH_CHANNEL_OPEN &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2125 | !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2126 | ((c->local_window_max - c->local_window >TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2127 | c->local_maxpacket*3) ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2128 | c->local_window < c->local_window_max/2) &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2129 | c->local_consumed > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2130 | if (!c->have_remote_id)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2131 | fatal(":%s: channel %d: no remote id", never executed: fatal(":%s: channel %d: no remote id", __func__, c->self); | 0 |
2132 | __func__, c->self); never executed: fatal(":%s: channel %d: no remote id", __func__, c->self); | 0 |
2133 | if ((r = sshpkt_start(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2134 | SSH2_MSG_CHANNEL_WINDOW_ADJUST)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2135 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2136 | (r = sshpkt_put_u32(ssh, c->local_consumed)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2137 | (r = sshpkt_send(ssh)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2138 | fatal("%s: channel %i: %s", __func__, | - |
2139 | c->self, ssh_err(r)); | - |
2140 | } never executed: end of block | 0 |
2141 | debug2("channel %d: window %d sent adjust %d", | - |
2142 | c->self, c->local_window, | - |
2143 | c->local_consumed); | - |
2144 | c->local_window += c->local_consumed; | - |
2145 | c->local_consumed = 0; | - |
2146 | } never executed: end of block | 0 |
2147 | return 1; never executed: return 1; | 0 |
2148 | } | - |
2149 | | - |
2150 | static void | - |
2151 | channel_post_open(struct ssh *ssh, Channel *c, | - |
2152 | fd_set *readset, fd_set *writeset) | - |
2153 | { | - |
2154 | channel_handle_rfd(ssh, c, readset, writeset); | - |
2155 | channel_handle_wfd(ssh, c, readset, writeset); | - |
2156 | channel_handle_efd(ssh, c, readset, writeset); | - |
2157 | channel_check_window(ssh, c); | - |
2158 | } never executed: end of block | 0 |
2159 | | - |
2160 | static u_int | - |
2161 | read_mux(struct ssh *ssh, Channel *c, u_int need) | - |
2162 | { | - |
2163 | char buf[CHAN_RBUF]; | - |
2164 | ssize_t len; | - |
2165 | u_int rlen; | - |
2166 | int r; | - |
2167 | | - |
2168 | if (sshbuf_len(c->input) < need) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2169 | rlen = need - sshbuf_len(c->input); | - |
2170 | len = read(c->rfd, buf, MINIMUM(rlen, CHAN_RBUF)); | - |
2171 | if (len < 0 && (errno == EINTR || errno == EAGAIN))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2172 | return sshbuf_len(c->input); never executed: return sshbuf_len(c->input); | 0 |
2173 | if (len <= 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2174 | debug2("channel %d: ctl read<=0 rfd %d len %zd", | - |
2175 | c->self, c->rfd, len); | - |
2176 | chan_read_failed(ssh, c); | - |
2177 | return 0; never executed: return 0; | 0 |
2178 | } else if ((r = sshbuf_put(c->input, buf, len)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2179 | fatal("%s: channel %d: append: %s", | - |
2180 | __func__, c->self, ssh_err(r)); | - |
2181 | } never executed: end of block | 0 |
2182 | } never executed: end of block | 0 |
2183 | return sshbuf_len(c->input); never executed: return sshbuf_len(c->input); | 0 |
2184 | } | - |
2185 | | - |
2186 | static void | - |
2187 | channel_post_mux_client_read(struct ssh *ssh, Channel *c, | - |
2188 | fd_set *readset, fd_set *writeset) | - |
2189 | { | - |
2190 | u_int need; | - |
2191 | | - |
2192 | if (c->rfd == -1 || !FD_ISSET(c->rfd, readset))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2193 | return; never executed: return; | 0 |
2194 | if (c->istate != CHAN_INPUT_OPEN && c->istate != CHAN_INPUT_WAIT_DRAIN)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2195 | return; never executed: return; | 0 |
2196 | if (c->mux_pause)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2197 | return; never executed: return; | 0 |
2198 | | - |
2199 | | - |
2200 | | - |
2201 | | - |
2202 | | - |
2203 | if (read_mux(ssh, c, 4) < 4) TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2204 | return; never executed: return; | 0 |
2205 | | - |
2206 | need = PEEK_U32(sshbuf_ptr(c->input)); | - |
2207 | #define CHANNEL_MUX_MAX_PACKET (256 * 1024) | - |
2208 | if (need > CHANNEL_MUX_MAX_PACKET) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2209 | debug2("channel %d: packet too big %u > %u", | - |
2210 | c->self, CHANNEL_MUX_MAX_PACKET, need); | - |
2211 | chan_rcvd_oclose(ssh, c); | - |
2212 | return; never executed: return; | 0 |
2213 | } | - |
2214 | if (read_mux(ssh, c, need + 4) < need + 4) TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2215 | return; never executed: return; | 0 |
2216 | if (c->mux_rcb(ssh, c) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2217 | debug("channel %d: mux_rcb failed", c->self); | - |
2218 | chan_mark_dead(ssh, c); | - |
2219 | return; never executed: return; | 0 |
2220 | } | - |
2221 | } never executed: end of block | 0 |
2222 | | - |
2223 | static void | - |
2224 | channel_post_mux_client_write(struct ssh *ssh, Channel *c, | - |
2225 | fd_set *readset, fd_set *writeset) | - |
2226 | { | - |
2227 | ssize_t len; | - |
2228 | int r; | - |
2229 | | - |
2230 | if (c->wfd == -1 || !FD_ISSET(c->wfd, writeset) ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2231 | sshbuf_len(c->output) == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2232 | return; never executed: return; | 0 |
2233 | | - |
2234 | len = write(c->wfd, sshbuf_ptr(c->output), sshbuf_len(c->output)); | - |
2235 | if (len < 0 && (errno == EINTR || errno == EAGAIN))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2236 | return; never executed: return; | 0 |
2237 | if (len <= 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2238 | chan_mark_dead(ssh, c); | - |
2239 | return; never executed: return; | 0 |
2240 | } | - |
2241 | if ((r = sshbuf_consume(c->output, len)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2242 | fatal("%s: channel %d: consume: %s", __func__, never executed: fatal("%s: channel %d: consume: %s", __func__, c->self, ssh_err(r)); | 0 |
2243 | c->self, ssh_err(r)); never executed: fatal("%s: channel %d: consume: %s", __func__, c->self, ssh_err(r)); | 0 |
2244 | } never executed: end of block | 0 |
2245 | | - |
2246 | static void | - |
2247 | channel_post_mux_client(struct ssh *ssh, Channel *c, | - |
2248 | fd_set *readset, fd_set *writeset) | - |
2249 | { | - |
2250 | channel_post_mux_client_read(ssh, c, readset, writeset); | - |
2251 | channel_post_mux_client_write(ssh, c, readset, writeset); | - |
2252 | } never executed: end of block | 0 |
2253 | | - |
2254 | static void | - |
2255 | channel_post_mux_listener(struct ssh *ssh, Channel *c, | - |
2256 | fd_set *readset, fd_set *writeset) | - |
2257 | { | - |
2258 | Channel *nc; | - |
2259 | struct sockaddr_storage addr; | - |
2260 | socklen_t addrlen; | - |
2261 | int newsock; | - |
2262 | uid_t euid; | - |
2263 | gid_t egid; | - |
2264 | | - |
2265 | if (!FD_ISSET(c->sock, readset))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2266 | return; never executed: return; | 0 |
2267 | | - |
2268 | debug("multiplexing control connection"); | - |
2269 | | - |
2270 | | - |
2271 | | - |
2272 | | - |
2273 | memset(&addr, 0, sizeof(addr)); | - |
2274 | addrlen = sizeof(addr); | - |
2275 | if ((newsock = accept(c->sock, (struct sockaddr*)&addr,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2276 | &addrlen)) == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2277 | error("%s accept: %s", __func__, strerror(errno)); | - |
2278 | if (errno == EMFILE || errno == ENFILE)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2279 | c->notbefore = monotime() + 1; never executed: c->notbefore = monotime() + 1; | 0 |
2280 | return; never executed: return; | 0 |
2281 | } | - |
2282 | | - |
2283 | if (getpeereid(newsock, &euid, &egid) < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2284 | error("%s getpeereid failed: %s", __func__, | - |
2285 | strerror(errno)); | - |
2286 | close(newsock); | - |
2287 | return; never executed: return; | 0 |
2288 | } | - |
2289 | if ((euid != 0) && (getuid() != euid)) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2290 | error("multiplex uid mismatch: peer euid %u != uid %u", | - |
2291 | (u_int)euid, (u_int)getuid()); | - |
2292 | close(newsock); | - |
2293 | return; never executed: return; | 0 |
2294 | } | - |
2295 | nc = channel_new(ssh, "multiplex client", SSH_CHANNEL_MUX_CLIENT, | - |
2296 | newsock, newsock, -1, c->local_window_max, | - |
2297 | c->local_maxpacket, 0, "mux-control", 1); | - |
2298 | nc->mux_rcb = c->mux_rcb; | - |
2299 | debug3("%s: new mux channel %d fd %d", __func__, nc->self, nc->sock); | - |
2300 | | - |
2301 | nc->mux_rcb(ssh, nc); | - |
2302 | | - |
2303 | nc->flags |= CHAN_LOCAL; | - |
2304 | } never executed: end of block | 0 |
2305 | | - |
2306 | static void | - |
2307 | channel_handler_init(struct ssh_channels *sc) | - |
2308 | { | - |
2309 | chan_fn **pre, **post; | - |
2310 | | - |
2311 | if ((pre = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*pre))) == NULL ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2312 | (post = calloc(SSH_CHANNEL_MAX_TYPE, sizeof(*post))) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2313 | fatal("%s: allocation failed", __func__); never executed: fatal("%s: allocation failed", __func__); | 0 |
2314 | | - |
2315 | pre[SSH_CHANNEL_OPEN] = &channel_pre_open; | - |
2316 | pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; | - |
2317 | pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; | - |
2318 | pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; | - |
2319 | pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener; | - |
2320 | pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener; | - |
2321 | pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; | - |
2322 | pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; | - |
2323 | pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; | - |
2324 | pre[SSH_CHANNEL_DYNAMIC] = &channel_pre_dynamic; | - |
2325 | pre[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_pre_connecting; | - |
2326 | pre[SSH_CHANNEL_MUX_LISTENER] = &channel_pre_listener; | - |
2327 | pre[SSH_CHANNEL_MUX_CLIENT] = &channel_pre_mux_client; | - |
2328 | | - |
2329 | post[SSH_CHANNEL_OPEN] = &channel_post_open; | - |
2330 | post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; | - |
2331 | post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; | - |
2332 | post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener; | - |
2333 | post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener; | - |
2334 | post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; | - |
2335 | post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; | - |
2336 | post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; | - |
2337 | post[SSH_CHANNEL_DYNAMIC] = &channel_post_open; | - |
2338 | post[SSH_CHANNEL_RDYNAMIC_FINISH] = &channel_post_connecting; | - |
2339 | post[SSH_CHANNEL_MUX_LISTENER] = &channel_post_mux_listener; | - |
2340 | post[SSH_CHANNEL_MUX_CLIENT] = &channel_post_mux_client; | - |
2341 | | - |
2342 | sc->channel_pre = pre; | - |
2343 | sc->channel_post = post; | - |
2344 | } never executed: end of block | 0 |
2345 | | - |
2346 | | - |
2347 | static void | - |
2348 | channel_garbage_collect(struct ssh *ssh, Channel *c) | - |
2349 | { | - |
2350 | if (c == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2351 | return; never executed: return; | 0 |
2352 | if (c->detach_user != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2353 | if (!chan_is_dead(ssh, c, c->detach_close))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2354 | return; never executed: return; | 0 |
2355 | debug2("channel %d: gc: notify user", c->self); | - |
2356 | c->detach_user(ssh, c->self, NULL); | - |
2357 | | - |
2358 | if (c->detach_user != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2359 | return; never executed: return; | 0 |
2360 | debug2("channel %d: gc: user detached", c->self); | - |
2361 | } never executed: end of block | 0 |
2362 | if (!chan_is_dead(ssh, c, 1))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2363 | return; never executed: return; | 0 |
2364 | debug2("channel %d: garbage collecting", c->self); | - |
2365 | channel_free(ssh, c); | - |
2366 | } never executed: end of block | 0 |
2367 | | - |
2368 | enum channel_table { CHAN_PRE, CHAN_POST }; | - |
2369 | | - |
2370 | static void | - |
2371 | channel_handler(struct ssh *ssh, int table, | - |
2372 | fd_set *readset, fd_set *writeset, time_t *unpause_secs) | - |
2373 | { | - |
2374 | struct ssh_channels *sc = ssh->chanctxt; | - |
2375 | chan_fn **ftab = table == CHAN_PRE ? sc->channel_pre : sc->channel_post;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2376 | u_int i, oalloc; | - |
2377 | Channel *c; | - |
2378 | time_t now; | - |
2379 | | - |
2380 | now = monotime(); | - |
2381 | if (unpause_secs != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2382 | *unpause_secs = 0; never executed: *unpause_secs = 0; | 0 |
2383 | for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2384 | c = sc->channels[i]; | - |
2385 | if (c == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2386 | continue; never executed: continue; | 0 |
2387 | if (c->delayed) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2388 | if (table == CHAN_PRE)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2389 | c->delayed = 0; never executed: c->delayed = 0; | 0 |
2390 | else | - |
2391 | continue; never executed: continue; | 0 |
2392 | } | - |
2393 | if (ftab[c->type] != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2394 | | - |
2395 | | - |
2396 | | - |
2397 | if (c->notbefore <= now)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2398 | (*ftab[c->type])(ssh, c, readset, writeset); never executed: (*ftab[c->type])(ssh, c, readset, writeset); | 0 |
2399 | else if (unpause_secs != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2400 | | - |
2401 | | - |
2402 | | - |
2403 | | - |
2404 | debug3("%s: chan %d: skip for %d more seconds", | - |
2405 | __func__, c->self, | - |
2406 | (int)(c->notbefore - now)); | - |
2407 | if (*unpause_secs == 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2408 | (c->notbefore - now) < *unpause_secs)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2409 | *unpause_secs = c->notbefore - now; never executed: *unpause_secs = c->notbefore - now; | 0 |
2410 | } never executed: end of block | 0 |
2411 | } never executed: end of block | 0 |
2412 | channel_garbage_collect(ssh, c); | - |
2413 | } never executed: end of block | 0 |
2414 | if (unpause_secs != NULL && *unpause_secs != 0)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2415 | debug3("%s: first channel unpauses in %d seconds", never executed: debug3("%s: first channel unpauses in %d seconds", __func__, (int)*unpause_secs); | 0 |
2416 | __func__, (int)*unpause_secs); never executed: debug3("%s: first channel unpauses in %d seconds", __func__, (int)*unpause_secs); | 0 |
2417 | } never executed: end of block | 0 |
2418 | | - |
2419 | | - |
2420 | | - |
2421 | | - |
2422 | | - |
2423 | | - |
2424 | static void | - |
2425 | channel_before_prepare_select(struct ssh *ssh) | - |
2426 | { | - |
2427 | struct ssh_channels *sc = ssh->chanctxt; | - |
2428 | Channel *c; | - |
2429 | u_int i, oalloc; | - |
2430 | | - |
2431 | for (i = 0, oalloc = sc->channels_alloc; i < oalloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2432 | c = sc->channels[i]; | - |
2433 | if (c == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2434 | continue; never executed: continue; | 0 |
2435 | if (c->type == SSH_CHANNEL_RDYNAMIC_OPEN)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2436 | channel_before_prepare_select_rdynamic(ssh, c); never executed: channel_before_prepare_select_rdynamic(ssh, c); | 0 |
2437 | } never executed: end of block | 0 |
2438 | } never executed: end of block | 0 |
2439 | | - |
2440 | | - |
2441 | | - |
2442 | | - |
2443 | | - |
2444 | void | - |
2445 | channel_prepare_select(struct ssh *ssh, fd_set **readsetp, fd_set **writesetp, | - |
2446 | int *maxfdp, u_int *nallocp, time_t *minwait_secs) | - |
2447 | { | - |
2448 | u_int n, sz, nfdset; | - |
2449 | | - |
2450 | channel_before_prepare_select(ssh); | - |
2451 | | - |
2452 | n = MAXIMUM(*maxfdp, ssh->chanctxt->channel_max_fd);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2453 | | - |
2454 | nfdset = howmany(n+1, NFDBITS); | - |
2455 | | - |
2456 | if (nfdset && SIZE_MAX / nfdset < sizeof(fd_mask))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2457 | fatal("channel_prepare_select: max_fd (%d) is too large", n); never executed: fatal("channel_prepare_select: max_fd (%d) is too large", n); | 0 |
2458 | sz = nfdset * sizeof(fd_mask); | - |
2459 | | - |
2460 | | - |
2461 | if (*readsetp == NULL || sz > *nallocp) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2462 | *readsetp = xreallocarray(*readsetp, nfdset, sizeof(fd_mask)); | - |
2463 | *writesetp = xreallocarray(*writesetp, nfdset, sizeof(fd_mask)); | - |
2464 | *nallocp = sz; | - |
2465 | } never executed: end of block | 0 |
2466 | *maxfdp = n; | - |
2467 | memset(*readsetp, 0, sz); | - |
2468 | memset(*writesetp, 0, sz); | - |
2469 | | - |
2470 | if (!ssh_packet_is_rekeying(ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2471 | channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp, never executed: channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp, minwait_secs); | 0 |
2472 | minwait_secs); never executed: channel_handler(ssh, CHAN_PRE, *readsetp, *writesetp, minwait_secs); | 0 |
2473 | } never executed: end of block | 0 |
2474 | | - |
2475 | | - |
2476 | | - |
2477 | | - |
2478 | | - |
2479 | void | - |
2480 | channel_after_select(struct ssh *ssh, fd_set *readset, fd_set *writeset) | - |
2481 | { | - |
2482 | channel_handler(ssh, CHAN_POST, readset, writeset, NULL); | - |
2483 | } never executed: end of block | 0 |
2484 | | - |
2485 | | - |
2486 | | - |
2487 | | - |
2488 | static void | - |
2489 | channel_output_poll_input_open(struct ssh *ssh, Channel *c) | - |
2490 | { | - |
2491 | size_t len, plen; | - |
2492 | const u_char *pkt; | - |
2493 | int r; | - |
2494 | | - |
2495 | if ((len = sshbuf_len(c->input)) == 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2496 | if (c->istate == CHAN_INPUT_WAIT_DRAIN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2497 | | - |
2498 | | - |
2499 | | - |
2500 | | - |
2501 | | - |
2502 | | - |
2503 | | - |
2504 | if (CHANNEL_EFD_INPUT_ACTIVE(c))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2505 | debug2("channel %d: " never executed: debug2("channel %d: " "ibuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); | 0 |
2506 | "ibuf_empty delayed efd %d/(%zu)", never executed: debug2("channel %d: " "ibuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); | 0 |
2507 | c->self, c->efd, sshbuf_len(c->extended)); never executed: debug2("channel %d: " "ibuf_empty delayed efd %d/(%zu)", c->self, c->efd, sshbuf_len(c->extended)); | 0 |
2508 | else | - |
2509 | chan_ibuf_empty(ssh, c); never executed: chan_ibuf_empty(ssh, c); | 0 |
2510 | } | - |
2511 | return; never executed: return; | 0 |
2512 | } | - |
2513 | | - |
2514 | if (!c->have_remote_id)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2515 | fatal(":%s: channel %d: no remote id", __func__, c->self); never executed: fatal(":%s: channel %d: no remote id", __func__, c->self); | 0 |
2516 | | - |
2517 | if (c->datagram) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2518 | | - |
2519 | if ((r = sshbuf_get_string_direct(c->input, &pkt, &plen)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2520 | fatal("%s: channel %d: get datagram: %s", __func__, never executed: fatal("%s: channel %d: get datagram: %s", __func__, c->self, ssh_err(r)); | 0 |
2521 | c->self, ssh_err(r)); never executed: fatal("%s: channel %d: get datagram: %s", __func__, c->self, ssh_err(r)); | 0 |
2522 | | - |
2523 | | - |
2524 | | - |
2525 | | - |
2526 | | - |
2527 | if (plen > c->remote_window || plen > c->remote_maxpacket) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2528 | debug("channel %d: datagram too big", c->self); | - |
2529 | return; never executed: return; | 0 |
2530 | } | - |
2531 | | - |
2532 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2533 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2534 | (r = sshpkt_put_string(ssh, pkt, plen)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2535 | (r = sshpkt_send(ssh)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2536 | fatal("%s: channel %i: datagram: %s", __func__, | - |
2537 | c->self, ssh_err(r)); | - |
2538 | } never executed: end of block | 0 |
2539 | c->remote_window -= plen; | - |
2540 | return; never executed: return; | 0 |
2541 | } | - |
2542 | | - |
2543 | | - |
2544 | if (len > c->remote_window)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2545 | len = c->remote_window; never executed: len = c->remote_window; | 0 |
2546 | if (len > c->remote_maxpacket)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2547 | len = c->remote_maxpacket; never executed: len = c->remote_maxpacket; | 0 |
2548 | if (len == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2549 | return; never executed: return; | 0 |
2550 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2551 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2552 | (r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2553 | (r = sshpkt_send(ssh)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2554 | fatal("%s: channel %i: data: %s", __func__, | - |
2555 | c->self, ssh_err(r)); | - |
2556 | } never executed: end of block | 0 |
2557 | if ((r = sshbuf_consume(c->input, len)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2558 | fatal("%s: channel %i: consume: %s", __func__, never executed: fatal("%s: channel %i: consume: %s", __func__, c->self, ssh_err(r)); | 0 |
2559 | c->self, ssh_err(r)); never executed: fatal("%s: channel %i: consume: %s", __func__, c->self, ssh_err(r)); | 0 |
2560 | c->remote_window -= len; | - |
2561 | } never executed: end of block | 0 |
2562 | | - |
2563 | | - |
2564 | | - |
2565 | | - |
2566 | static void | - |
2567 | channel_output_poll_extended_read(struct ssh *ssh, Channel *c) | - |
2568 | { | - |
2569 | size_t len; | - |
2570 | int r; | - |
2571 | | - |
2572 | if ((len = sshbuf_len(c->extended)) == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2573 | return; never executed: return; | 0 |
2574 | | - |
2575 | debug2("channel %d: rwin %u elen %zu euse %d", c->self, | - |
2576 | c->remote_window, sshbuf_len(c->extended), c->extended_usage); | - |
2577 | if (len > c->remote_window)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2578 | len = c->remote_window; never executed: len = c->remote_window; | 0 |
2579 | if (len > c->remote_maxpacket)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2580 | len = c->remote_maxpacket; never executed: len = c->remote_maxpacket; | 0 |
2581 | if (len == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2582 | return; never executed: return; | 0 |
2583 | if (!c->have_remote_id)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2584 | fatal(":%s: channel %d: no remote id", __func__, c->self); never executed: fatal(":%s: channel %d: no remote id", __func__, c->self); | 0 |
2585 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2586 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2587 | (r = sshpkt_put_u32(ssh, SSH2_EXTENDED_DATA_STDERR)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2588 | (r = sshpkt_put_string(ssh, sshbuf_ptr(c->extended), len)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2589 | (r = sshpkt_send(ssh)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2590 | fatal("%s: channel %i: data: %s", __func__, | - |
2591 | c->self, ssh_err(r)); | - |
2592 | } never executed: end of block | 0 |
2593 | if ((r = sshbuf_consume(c->extended, len)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2594 | fatal("%s: channel %i: consume: %s", __func__, never executed: fatal("%s: channel %i: consume: %s", __func__, c->self, ssh_err(r)); | 0 |
2595 | c->self, ssh_err(r)); never executed: fatal("%s: channel %i: consume: %s", __func__, c->self, ssh_err(r)); | 0 |
2596 | c->remote_window -= len; | - |
2597 | debug2("channel %d: sent ext data %zu", c->self, len); | - |
2598 | } never executed: end of block | 0 |
2599 | | - |
2600 | | - |
2601 | void | - |
2602 | channel_output_poll(struct ssh *ssh) | - |
2603 | { | - |
2604 | struct ssh_channels *sc = ssh->chanctxt; | - |
2605 | Channel *c; | - |
2606 | u_int i; | - |
2607 | | - |
2608 | for (i = 0; i < sc->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2609 | c = sc->channels[i]; | - |
2610 | if (c == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2611 | continue; never executed: continue; | 0 |
2612 | | - |
2613 | | - |
2614 | | - |
2615 | | - |
2616 | | - |
2617 | if (c->type != SSH_CHANNEL_OPEN)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2618 | continue; never executed: continue; | 0 |
2619 | if ((c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD))) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2620 | | - |
2621 | debug3("channel %d: will not send data after close", | - |
2622 | c->self); | - |
2623 | continue; never executed: continue; | 0 |
2624 | } | - |
2625 | | - |
2626 | | - |
2627 | if (c->istate == CHAN_INPUT_OPEN ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2628 | c->istate == CHAN_INPUT_WAIT_DRAIN)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2629 | channel_output_poll_input_open(ssh, c); never executed: channel_output_poll_input_open(ssh, c); | 0 |
2630 | | - |
2631 | if (!(c->flags & CHAN_EOF_SENT) &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2632 | c->extended_usage == CHAN_EXTENDED_READ)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2633 | channel_output_poll_extended_read(ssh, c); never executed: channel_output_poll_extended_read(ssh, c); | 0 |
2634 | } never executed: end of block | 0 |
2635 | } never executed: end of block | 0 |
2636 | | - |
2637 | | - |
2638 | | - |
2639 | | - |
2640 | | - |
2641 | | - |
2642 | | - |
2643 | | - |
2644 | | - |
2645 | | - |
2646 | | - |
2647 | | - |
2648 | | - |
2649 | | - |
2650 | | - |
2651 | | - |
2652 | | - |
2653 | | - |
2654 | | - |
2655 | | - |
2656 | | - |
2657 | | - |
2658 | | - |
2659 | | - |
2660 | | - |
2661 | | - |
2662 | | - |
2663 | | - |
2664 | | - |
2665 | | - |
2666 | | - |
2667 | | - |
2668 | | - |
2669 | | - |
2670 | | - |
2671 | | - |
2672 | | - |
2673 | | - |
2674 | | - |
2675 | | - |
2676 | | - |
2677 | int | - |
2678 | channel_proxy_downstream(struct ssh *ssh, Channel *downstream) | - |
2679 | { | - |
2680 | Channel *c = NULL; | - |
2681 | struct sshbuf *original = NULL, *modified = NULL; | - |
2682 | const u_char *cp; | - |
2683 | char *ctype = NULL, *listen_host = NULL; | - |
2684 | u_char type; | - |
2685 | size_t have; | - |
2686 | int ret = -1, r; | - |
2687 | u_int id, remote_id, listen_port; | - |
2688 | | - |
2689 | | - |
2690 | if ((r = sshbuf_get_string_direct(downstream->input, &cp, &have))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2691 | != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2692 | error("%s: malformed message: %s", __func__, ssh_err(r)); | - |
2693 | return -1; never executed: return -1; | 0 |
2694 | } | - |
2695 | if (have < 2) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2696 | error("%s: short message", __func__); | - |
2697 | return -1; never executed: return -1; | 0 |
2698 | } | - |
2699 | type = cp[1]; | - |
2700 | | - |
2701 | cp += 2; | - |
2702 | have -= 2; | - |
2703 | if (ssh_packet_log_type(type))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2704 | debug3("%s: channel %u: down->up: type %u", __func__, never executed: debug3("%s: channel %u: down->up: type %u", __func__, downstream->self, type); | 0 |
2705 | downstream->self, type); never executed: debug3("%s: channel %u: down->up: type %u", __func__, downstream->self, type); | 0 |
2706 | | - |
2707 | switch (type) { | - |
2708 | case SSH2_MSG_CHANNEL_OPEN: never executed: case 90: | 0 |
2709 | if ((original = sshbuf_from(cp, have)) == NULL ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2710 | (modified = sshbuf_new()) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2711 | error("%s: alloc", __func__); | - |
2712 | goto out; never executed: goto out; | 0 |
2713 | } | - |
2714 | if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2715 | (r = sshbuf_get_u32(original, &id)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2716 | error("%s: parse error %s", __func__, ssh_err(r)); | - |
2717 | goto out; never executed: goto out; | 0 |
2718 | } | - |
2719 | c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY, | - |
2720 | -1, -1, -1, 0, 0, 0, ctype, 1); | - |
2721 | c->mux_ctx = downstream; | - |
2722 | c->mux_downstream_id = id; | - |
2723 | if ((r = sshbuf_put_cstring(modified, ctype)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2724 | (r = sshbuf_put_u32(modified, c->self)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2725 | (r = sshbuf_putb(modified, original)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2726 | error("%s: compose error %s", __func__, ssh_err(r)); | - |
2727 | channel_free(ssh, c); | - |
2728 | goto out; never executed: goto out; | 0 |
2729 | } | - |
2730 | break; never executed: break; | 0 |
2731 | case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: never executed: case 91: | 0 |
2732 | | - |
2733 | | - |
2734 | | - |
2735 | | - |
2736 | if ((original = sshbuf_from(cp, have)) == NULL ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2737 | (modified = sshbuf_new()) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2738 | error("%s: alloc", __func__); | - |
2739 | goto out; never executed: goto out; | 0 |
2740 | } | - |
2741 | if ((r = sshbuf_get_u32(original, &remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2742 | (r = sshbuf_get_u32(original, &id)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2743 | error("%s: parse error %s", __func__, ssh_err(r)); | - |
2744 | goto out; never executed: goto out; | 0 |
2745 | } | - |
2746 | c = channel_new(ssh, "mux proxy", SSH_CHANNEL_MUX_PROXY, | - |
2747 | -1, -1, -1, 0, 0, 0, "mux-down-connect", 1); | - |
2748 | c->mux_ctx = downstream; | - |
2749 | c->mux_downstream_id = id; | - |
2750 | c->remote_id = remote_id; | - |
2751 | c->have_remote_id = 1; | - |
2752 | if ((r = sshbuf_put_u32(modified, remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2753 | (r = sshbuf_put_u32(modified, c->self)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2754 | (r = sshbuf_putb(modified, original)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2755 | error("%s: compose error %s", __func__, ssh_err(r)); | - |
2756 | channel_free(ssh, c); | - |
2757 | goto out; never executed: goto out; | 0 |
2758 | } | - |
2759 | break; never executed: break; | 0 |
2760 | case SSH2_MSG_GLOBAL_REQUEST: never executed: case 80: | 0 |
2761 | if ((original = sshbuf_from(cp, have)) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2762 | error("%s: alloc", __func__); | - |
2763 | goto out; never executed: goto out; | 0 |
2764 | } | - |
2765 | if ((r = sshbuf_get_cstring(original, &ctype, NULL)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2766 | error("%s: parse error %s", __func__, ssh_err(r)); | - |
2767 | goto out; never executed: goto out; | 0 |
2768 | } | - |
2769 | if (strcmp(ctype, "tcpip-forward") != 0) { never executed: __result = (((const unsigned char *) (const char *) ( ctype ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "tcpip-forward" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2770 | error("%s: unsupported request %s", __func__, ctype); | - |
2771 | goto out; never executed: goto out; | 0 |
2772 | } | - |
2773 | if ((r = sshbuf_get_u8(original, NULL)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2774 | (r = sshbuf_get_cstring(original, &listen_host, NULL)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2775 | (r = sshbuf_get_u32(original, &listen_port)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2776 | error("%s: parse error %s", __func__, ssh_err(r)); | - |
2777 | goto out; never executed: goto out; | 0 |
2778 | } | - |
2779 | if (listen_port > 65535) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2780 | error("%s: tcpip-forward for %s: bad port %u", | - |
2781 | __func__, listen_host, listen_port); | - |
2782 | goto out; never executed: goto out; | 0 |
2783 | } | - |
2784 | | - |
2785 | permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, "<mux>", -1, | - |
2786 | listen_host, NULL, (int)listen_port, downstream); | - |
2787 | listen_host = NULL; | - |
2788 | break; never executed: break; | 0 |
2789 | case SSH2_MSG_CHANNEL_CLOSE: never executed: case 97: | 0 |
2790 | if (have < 4)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2791 | break; never executed: break; | 0 |
2792 | remote_id = PEEK_U32(cp); | - |
2793 | if ((c = channel_by_remote_id(ssh, remote_id)) != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2794 | if (c->flags & CHAN_CLOSE_RCVD)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2795 | channel_free(ssh, c); never executed: channel_free(ssh, c); | 0 |
2796 | else | - |
2797 | c->flags |= CHAN_CLOSE_SENT; never executed: c->flags |= 0x01; | 0 |
2798 | } | - |
2799 | break; never executed: break; | 0 |
2800 | } | - |
2801 | if (modified) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2802 | if ((r = sshpkt_start(ssh, type)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2803 | (r = sshpkt_putb(ssh, modified)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2804 | (r = sshpkt_send(ssh)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2805 | error("%s: send %s", __func__, ssh_err(r)); | - |
2806 | goto out; never executed: goto out; | 0 |
2807 | } | - |
2808 | } else { never executed: end of block | 0 |
2809 | if ((r = sshpkt_start(ssh, type)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2810 | (r = sshpkt_put(ssh, cp, have)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2811 | (r = sshpkt_send(ssh)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2812 | error("%s: send %s", __func__, ssh_err(r)); | - |
2813 | goto out; never executed: goto out; | 0 |
2814 | } | - |
2815 | } never executed: end of block | 0 |
2816 | ret = 0; | - |
2817 | out: code before this statement never executed: out: | 0 |
2818 | free(ctype); | - |
2819 | free(listen_host); | - |
2820 | sshbuf_free(original); | - |
2821 | sshbuf_free(modified); | - |
2822 | return ret; never executed: return ret; | 0 |
2823 | } | - |
2824 | | - |
2825 | | - |
2826 | | - |
2827 | | - |
2828 | | - |
2829 | | - |
2830 | | - |
2831 | int | - |
2832 | channel_proxy_upstream(Channel *c, int type, u_int32_t seq, struct ssh *ssh) | - |
2833 | { | - |
2834 | struct sshbuf *b = NULL; | - |
2835 | Channel *downstream; | - |
2836 | const u_char *cp = NULL; | - |
2837 | size_t len; | - |
2838 | int r; | - |
2839 | | - |
2840 | | - |
2841 | | - |
2842 | | - |
2843 | | - |
2844 | | - |
2845 | | - |
2846 | if (c == NULL || c->type != SSH_CHANNEL_MUX_PROXY)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2847 | return 0; never executed: return 0; | 0 |
2848 | if ((downstream = c->mux_ctx) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2849 | return 0; never executed: return 0; | 0 |
2850 | switch (type) { | - |
2851 | case SSH2_MSG_CHANNEL_CLOSE: never executed: case 97: | 0 |
2852 | case SSH2_MSG_CHANNEL_DATA: never executed: case 94: | 0 |
2853 | case SSH2_MSG_CHANNEL_EOF: never executed: case 96: | 0 |
2854 | case SSH2_MSG_CHANNEL_EXTENDED_DATA: never executed: case 95: | 0 |
2855 | case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: never executed: case 91: | 0 |
2856 | case SSH2_MSG_CHANNEL_OPEN_FAILURE: never executed: case 92: | 0 |
2857 | case SSH2_MSG_CHANNEL_WINDOW_ADJUST: never executed: case 93: | 0 |
2858 | case SSH2_MSG_CHANNEL_SUCCESS: never executed: case 99: | 0 |
2859 | case SSH2_MSG_CHANNEL_FAILURE: never executed: case 100: | 0 |
2860 | case SSH2_MSG_CHANNEL_REQUEST: never executed: case 98: | 0 |
2861 | break; never executed: break; | 0 |
2862 | default: never executed: default: | 0 |
2863 | debug2("%s: channel %u: unsupported type %u", __func__, | - |
2864 | c->self, type); | - |
2865 | return 0; never executed: return 0; | 0 |
2866 | } | - |
2867 | if ((b = sshbuf_new()) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2868 | error("%s: alloc reply", __func__); | - |
2869 | goto out; never executed: goto out; | 0 |
2870 | } | - |
2871 | | - |
2872 | cp = sshpkt_ptr(ssh, &len); | - |
2873 | if (cp == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2874 | error("%s: no packet", __func__); | - |
2875 | goto out; never executed: goto out; | 0 |
2876 | } | - |
2877 | | - |
2878 | if ((r = sshbuf_put_u8(b, 0)) != 0 || TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2879 | (r = sshbuf_put_u8(b, type)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2880 | (r = sshbuf_put_u32(b, c->mux_downstream_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2881 | (r = sshbuf_put(b, cp, len)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2882 | (r = sshbuf_put_stringb(downstream->output, b)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2883 | error("%s: compose for muxclient %s", __func__, ssh_err(r)); | - |
2884 | goto out; never executed: goto out; | 0 |
2885 | } | - |
2886 | | - |
2887 | if (ssh_packet_log_type(type))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2888 | debug3("%s: channel %u: up->down: type %u", __func__, c->self, never executed: debug3("%s: channel %u: up->down: type %u", __func__, c->self, type); | 0 |
2889 | type); never executed: debug3("%s: channel %u: up->down: type %u", __func__, c->self, type); | 0 |
2890 | out: code before this statement never executed: out: | 0 |
2891 | | - |
2892 | switch (type) { | - |
2893 | case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION: never executed: case 91: | 0 |
2894 | | - |
2895 | if (cp && len > 4) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2896 | c->remote_id = PEEK_U32(cp); | - |
2897 | c->have_remote_id = 1; | - |
2898 | } never executed: end of block | 0 |
2899 | break; never executed: break; | 0 |
2900 | case SSH2_MSG_CHANNEL_CLOSE: never executed: case 97: | 0 |
2901 | if (c->flags & CHAN_CLOSE_SENT)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2902 | channel_free(ssh, c); never executed: channel_free(ssh, c); | 0 |
2903 | else | - |
2904 | c->flags |= CHAN_CLOSE_RCVD; never executed: c->flags |= 0x02; | 0 |
2905 | break; never executed: break; | 0 |
2906 | } | - |
2907 | sshbuf_free(b); | - |
2908 | return 1; never executed: return 1; | 0 |
2909 | } | - |
2910 | | - |
2911 | | - |
2912 | | - |
2913 | | - |
2914 | static int | - |
2915 | channel_parse_id(struct ssh *ssh, const char *where, const char *what) | - |
2916 | { | - |
2917 | u_int32_t id; | - |
2918 | int r; | - |
2919 | | - |
2920 | if ((r = sshpkt_get_u32(ssh, &id)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2921 | error("%s: parse id: %s", where, ssh_err(r)); | - |
2922 | ssh_packet_disconnect(ssh, "Invalid %s message", what); | - |
2923 | } never executed: end of block | 0 |
2924 | if (id > INT_MAX) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2925 | error("%s: bad channel id %u: %s", where, id, ssh_err(r)); | - |
2926 | ssh_packet_disconnect(ssh, "Invalid %s channel id", what); | - |
2927 | } never executed: end of block | 0 |
2928 | return (int)id; never executed: return (int)id; | 0 |
2929 | } | - |
2930 | | - |
2931 | | - |
2932 | static Channel * | - |
2933 | channel_from_packet_id(struct ssh *ssh, const char *where, const char *what) | - |
2934 | { | - |
2935 | int id = channel_parse_id(ssh, where, what); | - |
2936 | Channel *c; | - |
2937 | | - |
2938 | if ((c = channel_lookup(ssh, id)) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2939 | ssh_packet_disconnect(ssh, | - |
2940 | "%s packet referred to nonexistent channel %d", what, id); | - |
2941 | } never executed: end of block | 0 |
2942 | return c; never executed: return c; | 0 |
2943 | } | - |
2944 | | - |
2945 | int | - |
2946 | channel_input_data(int type, u_int32_t seq, struct ssh *ssh) | - |
2947 | { | - |
2948 | const u_char *data; | - |
2949 | size_t data_len, win_len; | - |
2950 | Channel *c = channel_from_packet_id(ssh, __func__, "data"); | - |
2951 | int r; | - |
2952 | | - |
2953 | if (channel_proxy_upstream(c, type, seq, ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2954 | return 0; never executed: return 0; | 0 |
2955 | | - |
2956 | | - |
2957 | if (c->type != SSH_CHANNEL_OPEN &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2958 | c->type != SSH_CHANNEL_RDYNAMIC_OPEN &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2959 | c->type != SSH_CHANNEL_RDYNAMIC_FINISH &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2960 | c->type != SSH_CHANNEL_X11_OPEN)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2961 | return 0; never executed: return 0; | 0 |
2962 | | - |
2963 | | - |
2964 | if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2965 | fatal("%s: channel %d: get data: %s", __func__, never executed: fatal("%s: channel %d: get data: %s", __func__, c->self, ssh_err(r)); | 0 |
2966 | c->self, ssh_err(r)); never executed: fatal("%s: channel %d: get data: %s", __func__, c->self, ssh_err(r)); | 0 |
2967 | ssh_packet_check_eom(ssh); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2968 | | - |
2969 | win_len = data_len; | - |
2970 | if (c->datagram)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2971 | win_len += 4; never executed: win_len += 4; | 0 |
2972 | | - |
2973 | | - |
2974 | | - |
2975 | | - |
2976 | | - |
2977 | | - |
2978 | if (c->ostate != CHAN_OUTPUT_OPEN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2979 | c->local_window -= win_len; | - |
2980 | c->local_consumed += win_len; | - |
2981 | return 0; never executed: return 0; | 0 |
2982 | } | - |
2983 | | - |
2984 | if (win_len > c->local_maxpacket) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2985 | logit("channel %d: rcvd big packet %zu, maxpack %u", | - |
2986 | c->self, win_len, c->local_maxpacket); | - |
2987 | return 0; never executed: return 0; | 0 |
2988 | } | - |
2989 | if (win_len > c->local_window) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2990 | logit("channel %d: rcvd too much data %zu, win %u", | - |
2991 | c->self, win_len, c->local_window); | - |
2992 | return 0; never executed: return 0; | 0 |
2993 | } | - |
2994 | c->local_window -= win_len; | - |
2995 | | - |
2996 | if (c->datagram) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2997 | if ((r = sshbuf_put_string(c->output, data, data_len)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
2998 | fatal("%s: channel %d: append datagram: %s", never executed: fatal("%s: channel %d: append datagram: %s", __func__, c->self, ssh_err(r)); | 0 |
2999 | __func__, c->self, ssh_err(r)); never executed: fatal("%s: channel %d: append datagram: %s", __func__, c->self, ssh_err(r)); | 0 |
3000 | } else if ((r = sshbuf_put(c->output, data, data_len)) != 0) never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3001 | fatal("%s: channel %d: append data: %s", never executed: fatal("%s: channel %d: append data: %s", __func__, c->self, ssh_err(r)); | 0 |
3002 | __func__, c->self, ssh_err(r)); never executed: fatal("%s: channel %d: append data: %s", __func__, c->self, ssh_err(r)); | 0 |
3003 | | - |
3004 | return 0; never executed: return 0; | 0 |
3005 | } | - |
3006 | | - |
3007 | int | - |
3008 | channel_input_extended_data(int type, u_int32_t seq, struct ssh *ssh) | - |
3009 | { | - |
3010 | const u_char *data; | - |
3011 | size_t data_len; | - |
3012 | u_int32_t tcode; | - |
3013 | Channel *c = channel_from_packet_id(ssh, __func__, "extended data"); | - |
3014 | int r; | - |
3015 | | - |
3016 | if (channel_proxy_upstream(c, type, seq, ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3017 | return 0; never executed: return 0; | 0 |
3018 | if (c->type != SSH_CHANNEL_OPEN) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3019 | logit("channel %d: ext data for non open", c->self); | - |
3020 | return 0; never executed: return 0; | 0 |
3021 | } | - |
3022 | if (c->flags & CHAN_EOF_RCVD) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3023 | if (datafellows & SSH_BUG_EXTEOF)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3024 | debug("channel %d: accepting ext data after eof", never executed: debug("channel %d: accepting ext data after eof", c->self); | 0 |
3025 | c->self); never executed: debug("channel %d: accepting ext data after eof", c->self); | 0 |
3026 | else | - |
3027 | ssh_packet_disconnect(ssh, "Received extended_data " never executed: ssh_packet_disconnect(ssh, "Received extended_data " "after EOF on channel %d.", c->self); | 0 |
3028 | "after EOF on channel %d.", c->self); never executed: ssh_packet_disconnect(ssh, "Received extended_data " "after EOF on channel %d.", c->self); | 0 |
3029 | } | - |
3030 | | - |
3031 | if ((r = sshpkt_get_u32(ssh, &tcode)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3032 | error("%s: parse tcode: %s", __func__, ssh_err(r)); | - |
3033 | ssh_packet_disconnect(ssh, "Invalid extended_data message"); | - |
3034 | } never executed: end of block | 0 |
3035 | if (c->efd == -1 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3036 | c->extended_usage != CHAN_EXTENDED_WRITE ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3037 | tcode != SSH2_EXTENDED_DATA_STDERR) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3038 | logit("channel %d: bad ext data", c->self); | - |
3039 | return 0; never executed: return 0; | 0 |
3040 | } | - |
3041 | if ((r = sshpkt_get_string_direct(ssh, &data, &data_len)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3042 | error("%s: parse data: %s", __func__, ssh_err(r)); | - |
3043 | ssh_packet_disconnect(ssh, "Invalid extended_data message"); | - |
3044 | } never executed: end of block | 0 |
3045 | ssh_packet_check_eom(ssh); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3046 | | - |
3047 | if (data_len > c->local_window) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3048 | logit("channel %d: rcvd too much extended_data %zu, win %u", | - |
3049 | c->self, data_len, c->local_window); | - |
3050 | return 0; never executed: return 0; | 0 |
3051 | } | - |
3052 | debug2("channel %d: rcvd ext data %zu", c->self, data_len); | - |
3053 | | - |
3054 | if ((r = sshbuf_put(c->extended, data, data_len)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3055 | error("%s: append: %s", __func__, ssh_err(r)); never executed: error("%s: append: %s", __func__, ssh_err(r)); | 0 |
3056 | c->local_window -= data_len; | - |
3057 | return 0; never executed: return 0; | 0 |
3058 | } | - |
3059 | | - |
3060 | int | - |
3061 | channel_input_ieof(int type, u_int32_t seq, struct ssh *ssh) | - |
3062 | { | - |
3063 | Channel *c = channel_from_packet_id(ssh, __func__, "ieof"); | - |
3064 | | - |
3065 | ssh_packet_check_eom(ssh); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3066 | | - |
3067 | if (channel_proxy_upstream(c, type, seq, ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3068 | return 0; never executed: return 0; | 0 |
3069 | chan_rcvd_ieof(ssh, c); | - |
3070 | | - |
3071 | | - |
3072 | if (c->force_drain && c->istate == CHAN_INPUT_OPEN) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3073 | debug("channel %d: FORCE input drain", c->self); | - |
3074 | c->istate = CHAN_INPUT_WAIT_DRAIN; | - |
3075 | if (sshbuf_len(c->input) == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3076 | chan_ibuf_empty(ssh, c); never executed: chan_ibuf_empty(ssh, c); | 0 |
3077 | } never executed: end of block | 0 |
3078 | return 0; never executed: return 0; | 0 |
3079 | } | - |
3080 | | - |
3081 | int | - |
3082 | channel_input_oclose(int type, u_int32_t seq, struct ssh *ssh) | - |
3083 | { | - |
3084 | Channel *c = channel_from_packet_id(ssh, __func__, "oclose"); | - |
3085 | | - |
3086 | if (channel_proxy_upstream(c, type, seq, ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3087 | return 0; never executed: return 0; | 0 |
3088 | ssh_packet_check_eom(ssh); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3089 | chan_rcvd_oclose(ssh, c); | - |
3090 | return 0; never executed: return 0; | 0 |
3091 | } | - |
3092 | | - |
3093 | int | - |
3094 | channel_input_open_confirmation(int type, u_int32_t seq, struct ssh *ssh) | - |
3095 | { | - |
3096 | Channel *c = channel_from_packet_id(ssh, __func__, "open confirmation"); | - |
3097 | u_int32_t remote_window, remote_maxpacket; | - |
3098 | int r; | - |
3099 | | - |
3100 | if (channel_proxy_upstream(c, type, seq, ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3101 | return 0; never executed: return 0; | 0 |
3102 | if (c->type != SSH_CHANNEL_OPENING)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3103 | packet_disconnect("Received open confirmation for " never executed: packet_disconnect("Received open confirmation for " "non-opening channel %d.", c->self); | 0 |
3104 | "non-opening channel %d.", c->self); never executed: packet_disconnect("Received open confirmation for " "non-opening channel %d.", c->self); | 0 |
3105 | | - |
3106 | | - |
3107 | | - |
3108 | | - |
3109 | if ((r = sshpkt_get_u32(ssh, &c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3110 | (r = sshpkt_get_u32(ssh, &remote_window)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3111 | (r = sshpkt_get_u32(ssh, &remote_maxpacket)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3112 | error("%s: window/maxpacket: %s", __func__, ssh_err(r)); | - |
3113 | packet_disconnect("Invalid open confirmation message"); | - |
3114 | } never executed: end of block | 0 |
3115 | ssh_packet_check_eom(ssh); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3116 | | - |
3117 | c->have_remote_id = 1; | - |
3118 | c->remote_window = remote_window; | - |
3119 | c->remote_maxpacket = remote_maxpacket; | - |
3120 | c->type = SSH_CHANNEL_OPEN; | - |
3121 | if (c->open_confirm) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3122 | debug2("%s: channel %d: callback start", __func__, c->self); | - |
3123 | c->open_confirm(ssh, c->self, 1, c->open_confirm_ctx); | - |
3124 | debug2("%s: channel %d: callback done", __func__, c->self); | - |
3125 | } never executed: end of block | 0 |
3126 | debug2("channel %d: open confirm rwindow %u rmax %u", c->self, | - |
3127 | c->remote_window, c->remote_maxpacket); | - |
3128 | return 0; never executed: return 0; | 0 |
3129 | } | - |
3130 | | - |
3131 | static char * | - |
3132 | reason2txt(int reason) | - |
3133 | { | - |
3134 | switch (reason) { | - |
3135 | case SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED: never executed: case 1: | 0 |
3136 | return "administratively prohibited"; never executed: return "administratively prohibited"; | 0 |
3137 | case SSH2_OPEN_CONNECT_FAILED: never executed: case 2: | 0 |
3138 | return "connect failed"; never executed: return "connect failed"; | 0 |
3139 | case SSH2_OPEN_UNKNOWN_CHANNEL_TYPE: never executed: case 3: | 0 |
3140 | return "unknown channel type"; never executed: return "unknown channel type"; | 0 |
3141 | case SSH2_OPEN_RESOURCE_SHORTAGE: never executed: case 4: | 0 |
3142 | return "resource shortage"; never executed: return "resource shortage"; | 0 |
3143 | } | - |
3144 | return "unknown reason"; never executed: return "unknown reason"; | 0 |
3145 | } | - |
3146 | | - |
3147 | int | - |
3148 | channel_input_open_failure(int type, u_int32_t seq, struct ssh *ssh) | - |
3149 | { | - |
3150 | Channel *c = channel_from_packet_id(ssh, __func__, "open failure"); | - |
3151 | u_int32_t reason; | - |
3152 | char *msg = NULL; | - |
3153 | int r; | - |
3154 | | - |
3155 | if (channel_proxy_upstream(c, type, seq, ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3156 | return 0; never executed: return 0; | 0 |
3157 | if (c->type != SSH_CHANNEL_OPENING)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3158 | packet_disconnect("Received open failure for " never executed: packet_disconnect("Received open failure for " "non-opening channel %d.", c->self); | 0 |
3159 | "non-opening channel %d.", c->self); never executed: packet_disconnect("Received open failure for " "non-opening channel %d.", c->self); | 0 |
3160 | if ((r = sshpkt_get_u32(ssh, &reason)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3161 | error("%s: reason: %s", __func__, ssh_err(r)); | - |
3162 | packet_disconnect("Invalid open failure message"); | - |
3163 | } never executed: end of block | 0 |
3164 | | - |
3165 | if ((r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3166 | (r = sshpkt_get_string_direct(ssh, NULL, NULL)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3167 | error("%s: message/lang: %s", __func__, ssh_err(r)); | - |
3168 | packet_disconnect("Invalid open failure message"); | - |
3169 | } never executed: end of block | 0 |
3170 | ssh_packet_check_eom(ssh); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3171 | logit("channel %d: open failed: %s%s%s", c->self, | - |
3172 | reason2txt(reason), msg ? ": ": "", msg ? msg : ""); | - |
3173 | free(msg); | - |
3174 | if (c->open_confirm) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3175 | debug2("%s: channel %d: callback start", __func__, c->self); | - |
3176 | c->open_confirm(ssh, c->self, 0, c->open_confirm_ctx); | - |
3177 | debug2("%s: channel %d: callback done", __func__, c->self); | - |
3178 | } never executed: end of block | 0 |
3179 | | - |
3180 | chan_mark_dead(ssh, c); | - |
3181 | return 0; never executed: return 0; | 0 |
3182 | } | - |
3183 | | - |
3184 | int | - |
3185 | channel_input_window_adjust(int type, u_int32_t seq, struct ssh *ssh) | - |
3186 | { | - |
3187 | int id = channel_parse_id(ssh, __func__, "window adjust"); | - |
3188 | Channel *c; | - |
3189 | u_int32_t adjust; | - |
3190 | u_int new_rwin; | - |
3191 | int r; | - |
3192 | | - |
3193 | if ((c = channel_lookup(ssh, id)) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3194 | logit("Received window adjust for non-open channel %d.", id); | - |
3195 | return 0; never executed: return 0; | 0 |
3196 | } | - |
3197 | | - |
3198 | if (channel_proxy_upstream(c, type, seq, ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3199 | return 0; never executed: return 0; | 0 |
3200 | if ((r = sshpkt_get_u32(ssh, &adjust)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3201 | error("%s: adjust: %s", __func__, ssh_err(r)); | - |
3202 | packet_disconnect("Invalid window adjust message"); | - |
3203 | } never executed: end of block | 0 |
3204 | ssh_packet_check_eom(ssh); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3205 | debug2("channel %d: rcvd adjust %u", c->self, adjust); | - |
3206 | if ((new_rwin = c->remote_window + adjust) < c->remote_window) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3207 | fatal("channel %d: adjust %u overflows remote window %u", | - |
3208 | c->self, adjust, c->remote_window); | - |
3209 | } never executed: end of block | 0 |
3210 | c->remote_window = new_rwin; | - |
3211 | return 0; never executed: return 0; | 0 |
3212 | } | - |
3213 | | - |
3214 | int | - |
3215 | channel_input_status_confirm(int type, u_int32_t seq, struct ssh *ssh) | - |
3216 | { | - |
3217 | int id = channel_parse_id(ssh, __func__, "status confirm"); | - |
3218 | Channel *c; | - |
3219 | struct channel_confirm *cc; | - |
3220 | | - |
3221 | | - |
3222 | packet_set_alive_timeouts(0); | - |
3223 | | - |
3224 | debug2("%s: type %d id %d", __func__, type, id); | - |
3225 | | - |
3226 | if ((c = channel_lookup(ssh, id)) == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3227 | logit("%s: %d: unknown", __func__, id); | - |
3228 | return 0; never executed: return 0; | 0 |
3229 | } | - |
3230 | if (channel_proxy_upstream(c, type, seq, ssh))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3231 | return 0; never executed: return 0; | 0 |
3232 | ssh_packet_check_eom(ssh); never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3233 | if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3234 | return 0; never executed: return 0; | 0 |
3235 | cc->cb(ssh, type, c, cc->ctx); | - |
3236 | TAILQ_REMOVE(&c->status_confirms, cc, entry); never executed: (cc)->entry.tqe_next->entry.tqe_prev = (cc)->entry.tqe_prev; never executed: (&c->status_confirms)->tqh_last = (cc)->entry.tqe_prev; TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3237 | explicit_bzero(cc, sizeof(*cc)); | - |
3238 | free(cc); | - |
3239 | return 0; never executed: return 0; | 0 |
3240 | } | - |
3241 | | - |
3242 | | - |
3243 | | - |
3244 | void | - |
3245 | channel_set_af(struct ssh *ssh, int af) | - |
3246 | { | - |
3247 | ssh->chanctxt->IPv4or6 = af; | - |
3248 | } never executed: end of block | 0 |
3249 | | - |
3250 | | - |
3251 | | - |
3252 | | - |
3253 | | - |
3254 | | - |
3255 | | - |
3256 | | - |
3257 | | - |
3258 | | - |
3259 | | - |
3260 | | - |
3261 | | - |
3262 | | - |
3263 | | - |
3264 | | - |
3265 | | - |
3266 | static const char * | - |
3267 | channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, | - |
3268 | int is_client, struct ForwardOptions *fwd_opts) | - |
3269 | { | - |
3270 | const char *addr = NULL; | - |
3271 | int wildcard = 0; | - |
3272 | | - |
3273 | if (listen_addr == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3274 | | - |
3275 | if (fwd_opts->gateway_ports)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3276 | wildcard = 1; never executed: wildcard = 1; | 0 |
3277 | } else if (fwd_opts->gateway_ports || is_client) { never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3278 | if (((datafellows & SSH_OLD_FORWARD_ADDR) &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3279 | strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "0.0.0.0" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3280 | *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "*" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3281 | (!is_client && fwd_opts->gateway_ports == 1)) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3282 | wildcard = 1; | - |
3283 | | - |
3284 | | - |
3285 | | - |
3286 | | - |
3287 | if (*listen_addr != '\0' &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3288 | strcmp(listen_addr, "0.0.0.0") != 0 && never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "0.0.0.0" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3289 | strcmp(listen_addr, "*") != 0) { never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "*" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3290 | packet_send_debug("Forwarding listen address " | - |
3291 | "\"%s\" overridden by server " | - |
3292 | "GatewayPorts", listen_addr); | - |
3293 | } never executed: end of block | 0 |
3294 | } else if (strcmp(listen_addr, "localhost") != 0 || never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "localhost" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3295 | strcmp(listen_addr, "127.0.0.1") == 0 || never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "127.0.0.1" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3296 | strcmp(listen_addr, "::1") == 0) { never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "::1" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3297 | | - |
3298 | addr = listen_addr; | - |
3299 | } never executed: end of block | 0 |
3300 | } else if (strcmp(listen_addr, "127.0.0.1") == 0 || never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "127.0.0.1" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3301 | strcmp(listen_addr, "::1") == 0) { never executed: __result = (((const unsigned char *) (const char *) ( listen_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "::1" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3302 | | - |
3303 | | - |
3304 | | - |
3305 | | - |
3306 | | - |
3307 | addr = listen_addr; | - |
3308 | } never executed: end of block | 0 |
3309 | if (wildcardp != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3310 | *wildcardp = wildcard; never executed: *wildcardp = wildcard; | 0 |
3311 | return addr; never executed: return addr; | 0 |
3312 | } | - |
3313 | | - |
3314 | static int | - |
3315 | channel_setup_fwd_listener_tcpip(struct ssh *ssh, int type, | - |
3316 | struct Forward *fwd, int *allocated_listen_port, | - |
3317 | struct ForwardOptions *fwd_opts) | - |
3318 | { | - |
3319 | Channel *c; | - |
3320 | int sock, r, success = 0, wildcard = 0, is_client; | - |
3321 | struct addrinfo hints, *ai, *aitop; | - |
3322 | const char *host, *addr; | - |
3323 | char ntop[NI_MAXHOST], strport[NI_MAXSERV]; | - |
3324 | in_port_t *lport_p; | - |
3325 | | - |
3326 | is_client = (type == SSH_CHANNEL_PORT_LISTENER); | - |
3327 | | - |
3328 | if (is_client && fwd->connect_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3329 | host = fwd->connect_path; | - |
3330 | } else { never executed: end of block | 0 |
3331 | host = (type == SSH_CHANNEL_RPORT_LISTENER) ?TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3332 | fwd->listen_host : fwd->connect_host; | - |
3333 | if (host == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3334 | error("No forward host name."); | - |
3335 | return 0; never executed: return 0; | 0 |
3336 | } | - |
3337 | if (strlen(host) >= NI_MAXHOST) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3338 | error("Forward host name too long."); | - |
3339 | return 0; never executed: return 0; | 0 |
3340 | } | - |
3341 | } never executed: end of block | 0 |
3342 | | - |
3343 | | - |
3344 | addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard, | - |
3345 | is_client, fwd_opts); | - |
3346 | debug3("%s: type %d wildcard %d addr %s", __func__, | - |
3347 | type, wildcard, (addr == NULL) ? "NULL" : addr); | - |
3348 | | - |
3349 | | - |
3350 | | - |
3351 | | - |
3352 | | - |
3353 | memset(&hints, 0, sizeof(hints)); | - |
3354 | hints.ai_family = ssh->chanctxt->IPv4or6; | - |
3355 | hints.ai_flags = wildcard ? AI_PASSIVE : 0;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3356 | hints.ai_socktype = SOCK_STREAM; | - |
3357 | snprintf(strport, sizeof strport, "%d", fwd->listen_port); | - |
3358 | if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3359 | if (addr == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3360 | | - |
3361 | packet_disconnect("getaddrinfo: fatal error: %s", | - |
3362 | ssh_gai_strerror(r)); | - |
3363 | } else { never executed: end of block | 0 |
3364 | error("%s: getaddrinfo(%.64s): %s", __func__, addr, | - |
3365 | ssh_gai_strerror(r)); | - |
3366 | } never executed: end of block | 0 |
3367 | return 0; never executed: return 0; | 0 |
3368 | } | - |
3369 | if (allocated_listen_port != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3370 | *allocated_listen_port = 0; never executed: *allocated_listen_port = 0; | 0 |
3371 | for (ai = aitop; ai; ai = ai->ai_next) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3372 | switch (ai->ai_family) { | - |
3373 | case AF_INET: never executed: case 2 : | 0 |
3374 | lport_p = &((struct sockaddr_in *)ai->ai_addr)-> | - |
3375 | sin_port; | - |
3376 | break; never executed: break; | 0 |
3377 | case AF_INET6: never executed: case 10 : | 0 |
3378 | lport_p = &((struct sockaddr_in6 *)ai->ai_addr)-> | - |
3379 | sin6_port; | - |
3380 | break; never executed: break; | 0 |
3381 | default: never executed: default: | 0 |
3382 | continue; never executed: continue; | 0 |
3383 | } | - |
3384 | | - |
3385 | | - |
3386 | | - |
3387 | | - |
3388 | if (type == SSH_CHANNEL_RPORT_LISTENER &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3389 | fwd->listen_port == 0 && allocated_listen_port != NULL &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3390 | *allocated_listen_port > 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3391 | *lport_p = htons(*allocated_listen_port); never executed: *lport_p = (__extension__ ({ unsigned short int __v, __x = (unsigned short int) ( *allocated_listen_port ); if (__builtin_constant_p (__x)) __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8))); else __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); __v; })) ; never executed: __v = ((unsigned short int) ((((__x) >> 8) & 0xff) | (((__x) & 0xff) << 8))); never executed: __asm__ ("rorw $8, %w0" : "=r" (__v) : "0" (__x) : "cc"); TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3392 | | - |
3393 | if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3394 | strport, sizeof(strport),TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3395 | NI_NUMERICHOST|NI_NUMERICSERV) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3396 | error("%s: getnameinfo failed", __func__); | - |
3397 | continue; never executed: continue; | 0 |
3398 | } | - |
3399 | | - |
3400 | sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); | - |
3401 | if (sock < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3402 | | - |
3403 | verbose("socket [%s]:%s: %.100s", ntop, strport, | - |
3404 | strerror(errno)); | - |
3405 | continue; never executed: continue; | 0 |
3406 | } | - |
3407 | | - |
3408 | set_reuseaddr(sock); | - |
3409 | if (ai->ai_family == AF_INET6)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3410 | sock_set_v6only(sock); never executed: sock_set_v6only(sock); | 0 |
3411 | | - |
3412 | debug("Local forwarding listening on %s port %s.", | - |
3413 | ntop, strport); | - |
3414 | | - |
3415 | | - |
3416 | if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3417 | | - |
3418 | | - |
3419 | | - |
3420 | | - |
3421 | if (!ai->ai_next)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3422 | error("bind [%s]:%s: %.100s", never executed: error("bind [%s]:%s: %.100s", ntop, strport, strerror( (*__errno_location ()) )); | 0 |
3423 | ntop, strport, strerror(errno)); never executed: error("bind [%s]:%s: %.100s", ntop, strport, strerror( (*__errno_location ()) )); | 0 |
3424 | else | - |
3425 | verbose("bind [%s]:%s: %.100s", never executed: verbose("bind [%s]:%s: %.100s", ntop, strport, strerror( (*__errno_location ()) )); | 0 |
3426 | ntop, strport, strerror(errno)); never executed: verbose("bind [%s]:%s: %.100s", ntop, strport, strerror( (*__errno_location ()) )); | 0 |
3427 | | - |
3428 | close(sock); | - |
3429 | continue; never executed: continue; | 0 |
3430 | } | - |
3431 | | - |
3432 | if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3433 | error("listen: %.100s", strerror(errno)); | - |
3434 | error("listen [%s]:%s: %.100s", ntop, strport, | - |
3435 | strerror(errno)); | - |
3436 | close(sock); | - |
3437 | continue; never executed: continue; | 0 |
3438 | } | - |
3439 | | - |
3440 | | - |
3441 | | - |
3442 | | - |
3443 | | - |
3444 | if (type == SSH_CHANNEL_RPORT_LISTENER &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3445 | fwd->listen_port == 0 &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3446 | allocated_listen_port != NULL &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3447 | *allocated_listen_port == 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3448 | *allocated_listen_port = get_local_port(sock); | - |
3449 | debug("Allocated listen port %d", | - |
3450 | *allocated_listen_port); | - |
3451 | } never executed: end of block | 0 |
3452 | | - |
3453 | | - |
3454 | c = channel_new(ssh, "port listener", type, sock, sock, -1, | - |
3455 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | - |
3456 | 0, "port listener", 1); | - |
3457 | c->path = xstrdup(host); | - |
3458 | c->host_port = fwd->connect_port; | - |
3459 | c->listening_addr = addr == NULL ? NULL : xstrdup(addr);TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3460 | if (fwd->listen_port == 0 && allocated_listen_port != NULL &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3461 | !(datafellows & SSH_BUG_DYNAMIC_RPORT))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3462 | c->listening_port = *allocated_listen_port; never executed: c->listening_port = *allocated_listen_port; | 0 |
3463 | else | - |
3464 | c->listening_port = fwd->listen_port; never executed: c->listening_port = fwd->listen_port; | 0 |
3465 | success = 1; | - |
3466 | } never executed: end of block | 0 |
3467 | if (success == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3468 | error("%s: cannot listen to port: %d", __func__, never executed: error("%s: cannot listen to port: %d", __func__, fwd->listen_port); | 0 |
3469 | fwd->listen_port); never executed: error("%s: cannot listen to port: %d", __func__, fwd->listen_port); | 0 |
3470 | freeaddrinfo(aitop); | - |
3471 | return success; never executed: return success; | 0 |
3472 | } | - |
3473 | | - |
3474 | static int | - |
3475 | channel_setup_fwd_listener_streamlocal(struct ssh *ssh, int type, | - |
3476 | struct Forward *fwd, struct ForwardOptions *fwd_opts) | - |
3477 | { | - |
3478 | struct sockaddr_un sunaddr; | - |
3479 | const char *path; | - |
3480 | Channel *c; | - |
3481 | int port, sock; | - |
3482 | mode_t omask; | - |
3483 | | - |
3484 | switch (type) { | - |
3485 | case SSH_CHANNEL_UNIX_LISTENER: never executed: case 18: | 0 |
3486 | if (fwd->connect_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3487 | if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3488 | error("Local connecting path too long: %s", | - |
3489 | fwd->connect_path); | - |
3490 | return 0; never executed: return 0; | 0 |
3491 | } | - |
3492 | path = fwd->connect_path; | - |
3493 | port = PORT_STREAMLOCAL; | - |
3494 | } else { never executed: end of block | 0 |
3495 | if (fwd->connect_host == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3496 | error("No forward host name."); | - |
3497 | return 0; never executed: return 0; | 0 |
3498 | } | - |
3499 | if (strlen(fwd->connect_host) >= NI_MAXHOST) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3500 | error("Forward host name too long."); | - |
3501 | return 0; never executed: return 0; | 0 |
3502 | } | - |
3503 | path = fwd->connect_host; | - |
3504 | port = fwd->connect_port; | - |
3505 | } never executed: end of block | 0 |
3506 | break; never executed: break; | 0 |
3507 | case SSH_CHANNEL_RUNIX_LISTENER: never executed: case 19: | 0 |
3508 | path = fwd->listen_path; | - |
3509 | port = PORT_STREAMLOCAL; | - |
3510 | break; never executed: break; | 0 |
3511 | default: never executed: default: | 0 |
3512 | error("%s: unexpected channel type %d", __func__, type); | - |
3513 | return 0; never executed: return 0; | 0 |
3514 | } | - |
3515 | | - |
3516 | if (fwd->listen_path == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3517 | error("No forward path name."); | - |
3518 | return 0; never executed: return 0; | 0 |
3519 | } | - |
3520 | if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3521 | error("Local listening path too long: %s", fwd->listen_path); | - |
3522 | return 0; never executed: return 0; | 0 |
3523 | } | - |
3524 | | - |
3525 | debug3("%s: type %d path %s", __func__, type, fwd->listen_path); | - |
3526 | | - |
3527 | | - |
3528 | omask = umask(fwd_opts->streamlocal_bind_mask); | - |
3529 | sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG, | - |
3530 | fwd_opts->streamlocal_bind_unlink); | - |
3531 | umask(omask); | - |
3532 | if (sock < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3533 | return 0; never executed: return 0; | 0 |
3534 | | - |
3535 | debug("Local forwarding listening on path %s.", fwd->listen_path); | - |
3536 | | - |
3537 | | - |
3538 | c = channel_new(ssh, "unix listener", type, sock, sock, -1, | - |
3539 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, | - |
3540 | 0, "unix listener", 1); | - |
3541 | c->path = xstrdup(path); | - |
3542 | c->host_port = port; | - |
3543 | c->listening_port = PORT_STREAMLOCAL; | - |
3544 | c->listening_addr = xstrdup(fwd->listen_path); | - |
3545 | return 1; never executed: return 1; | 0 |
3546 | } | - |
3547 | | - |
3548 | static int | - |
3549 | channel_cancel_rport_listener_tcpip(struct ssh *ssh, | - |
3550 | const char *host, u_short port) | - |
3551 | { | - |
3552 | u_int i; | - |
3553 | int found = 0; | - |
3554 | | - |
3555 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3556 | Channel *c = ssh->chanctxt->channels[i]; | - |
3557 | if (c == NULL || c->type != SSH_CHANNEL_RPORT_LISTENER)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3558 | continue; never executed: continue; | 0 |
3559 | if (strcmp(c->path, host) == 0 && c->listening_port == port) { never executed: __result = (((const unsigned char *) (const char *) ( c->path ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( host ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3560 | debug2("%s: close channel %d", __func__, i); | - |
3561 | channel_free(ssh, c); | - |
3562 | found = 1; | - |
3563 | } never executed: end of block | 0 |
3564 | } never executed: end of block | 0 |
3565 | | - |
3566 | return found; never executed: return found; | 0 |
3567 | } | - |
3568 | | - |
3569 | static int | - |
3570 | channel_cancel_rport_listener_streamlocal(struct ssh *ssh, const char *path) | - |
3571 | { | - |
3572 | u_int i; | - |
3573 | int found = 0; | - |
3574 | | - |
3575 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3576 | Channel *c = ssh->chanctxt->channels[i]; | - |
3577 | if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3578 | continue; never executed: continue; | 0 |
3579 | if (c->path == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3580 | continue; never executed: continue; | 0 |
3581 | if (strcmp(c->path, path) == 0) { never executed: __result = (((const unsigned char *) (const char *) ( c->path ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( path ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3582 | debug2("%s: close channel %d", __func__, i); | - |
3583 | channel_free(ssh, c); | - |
3584 | found = 1; | - |
3585 | } never executed: end of block | 0 |
3586 | } never executed: end of block | 0 |
3587 | | - |
3588 | return found; never executed: return found; | 0 |
3589 | } | - |
3590 | | - |
3591 | int | - |
3592 | channel_cancel_rport_listener(struct ssh *ssh, struct Forward *fwd) | - |
3593 | { | - |
3594 | if (fwd->listen_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3595 | return channel_cancel_rport_listener_streamlocal(ssh, never executed: return channel_cancel_rport_listener_streamlocal(ssh, fwd->listen_path); | 0 |
3596 | fwd->listen_path); never executed: return channel_cancel_rport_listener_streamlocal(ssh, fwd->listen_path); | 0 |
3597 | } else { | - |
3598 | return channel_cancel_rport_listener_tcpip(ssh, never executed: return channel_cancel_rport_listener_tcpip(ssh, fwd->listen_host, fwd->listen_port); | 0 |
3599 | fwd->listen_host, fwd->listen_port); never executed: return channel_cancel_rport_listener_tcpip(ssh, fwd->listen_host, fwd->listen_port); | 0 |
3600 | } | - |
3601 | } | - |
3602 | | - |
3603 | static int | - |
3604 | channel_cancel_lport_listener_tcpip(struct ssh *ssh, | - |
3605 | const char *lhost, u_short lport, int cport, | - |
3606 | struct ForwardOptions *fwd_opts) | - |
3607 | { | - |
3608 | u_int i; | - |
3609 | int found = 0; | - |
3610 | const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts); | - |
3611 | | - |
3612 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3613 | Channel *c = ssh->chanctxt->channels[i]; | - |
3614 | if (c == NULL || c->type != SSH_CHANNEL_PORT_LISTENER)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3615 | continue; never executed: continue; | 0 |
3616 | if (c->listening_port != lport)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3617 | continue; never executed: continue; | 0 |
3618 | if (cport == CHANNEL_CANCEL_PORT_STATIC) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3619 | | - |
3620 | if (c->host_port == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3621 | continue; never executed: continue; | 0 |
3622 | } else { never executed: end of block | 0 |
3623 | if (c->host_port != cport)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3624 | continue; never executed: continue; | 0 |
3625 | } never executed: end of block | 0 |
3626 | if ((c->listening_addr == NULL && addr != NULL) ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3627 | (c->listening_addr != NULL && addr == NULL))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3628 | continue; never executed: continue; | 0 |
3629 | if (addr == NULL || strcmp(c->listening_addr, addr) == 0) { never executed: __result = (((const unsigned char *) (const char *) ( c->listening_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( addr ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3630 | debug2("%s: close channel %d", __func__, i); | - |
3631 | channel_free(ssh, c); | - |
3632 | found = 1; | - |
3633 | } never executed: end of block | 0 |
3634 | } never executed: end of block | 0 |
3635 | | - |
3636 | return found; never executed: return found; | 0 |
3637 | } | - |
3638 | | - |
3639 | static int | - |
3640 | channel_cancel_lport_listener_streamlocal(struct ssh *ssh, const char *path) | - |
3641 | { | - |
3642 | u_int i; | - |
3643 | int found = 0; | - |
3644 | | - |
3645 | if (path == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3646 | error("%s: no path specified.", __func__); | - |
3647 | return 0; never executed: return 0; | 0 |
3648 | } | - |
3649 | | - |
3650 | for (i = 0; i < ssh->chanctxt->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3651 | Channel *c = ssh->chanctxt->channels[i]; | - |
3652 | if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3653 | continue; never executed: continue; | 0 |
3654 | if (c->listening_addr == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3655 | continue; never executed: continue; | 0 |
3656 | if (strcmp(c->listening_addr, path) == 0) { never executed: __result = (((const unsigned char *) (const char *) ( c->listening_addr ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( path ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3657 | debug2("%s: close channel %d", __func__, i); | - |
3658 | channel_free(ssh, c); | - |
3659 | found = 1; | - |
3660 | } never executed: end of block | 0 |
3661 | } never executed: end of block | 0 |
3662 | | - |
3663 | return found; never executed: return found; | 0 |
3664 | } | - |
3665 | | - |
3666 | int | - |
3667 | channel_cancel_lport_listener(struct ssh *ssh, | - |
3668 | struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts) | - |
3669 | { | - |
3670 | if (fwd->listen_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3671 | return channel_cancel_lport_listener_streamlocal(ssh, never executed: return channel_cancel_lport_listener_streamlocal(ssh, fwd->listen_path); | 0 |
3672 | fwd->listen_path); never executed: return channel_cancel_lport_listener_streamlocal(ssh, fwd->listen_path); | 0 |
3673 | } else { | - |
3674 | return channel_cancel_lport_listener_tcpip(ssh, never executed: return channel_cancel_lport_listener_tcpip(ssh, fwd->listen_host, fwd->listen_port, cport, fwd_opts); | 0 |
3675 | fwd->listen_host, fwd->listen_port, cport, fwd_opts); never executed: return channel_cancel_lport_listener_tcpip(ssh, fwd->listen_host, fwd->listen_port, cport, fwd_opts); | 0 |
3676 | } | - |
3677 | } | - |
3678 | | - |
3679 | | - |
3680 | int | - |
3681 | channel_setup_local_fwd_listener(struct ssh *ssh, | - |
3682 | struct Forward *fwd, struct ForwardOptions *fwd_opts) | - |
3683 | { | - |
3684 | if (fwd->listen_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3685 | return channel_setup_fwd_listener_streamlocal(ssh, never executed: return channel_setup_fwd_listener_streamlocal(ssh, 18, fwd, fwd_opts); | 0 |
3686 | SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts); never executed: return channel_setup_fwd_listener_streamlocal(ssh, 18, fwd, fwd_opts); | 0 |
3687 | } else { | - |
3688 | return channel_setup_fwd_listener_tcpip(ssh, never executed: return channel_setup_fwd_listener_tcpip(ssh, 2, fwd, ((void *)0) , fwd_opts); | 0 |
3689 | SSH_CHANNEL_PORT_LISTENER, fwd, NULL, fwd_opts); never executed: return channel_setup_fwd_listener_tcpip(ssh, 2, fwd, ((void *)0) , fwd_opts); | 0 |
3690 | } | - |
3691 | } | - |
3692 | | - |
3693 | | - |
3694 | static int | - |
3695 | remote_open_match(struct permission *allowed_open, struct Forward *fwd) | - |
3696 | { | - |
3697 | int ret; | - |
3698 | char *lhost; | - |
3699 | | - |
3700 | | - |
3701 | if (fwd->listen_path != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3702 | return 1; never executed: return 1; | 0 |
3703 | | - |
3704 | if (fwd->listen_host == NULL || allowed_open->listen_host == NULL)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3705 | return 0; never executed: return 0; | 0 |
3706 | | - |
3707 | if (allowed_open->listen_port != FWD_PERMIT_ANY_PORT &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3708 | allowed_open->listen_port != fwd->listen_port)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3709 | return 0; never executed: return 0; | 0 |
3710 | | - |
3711 | | - |
3712 | lhost = xstrdup(fwd->listen_host); | - |
3713 | lowercase(lhost); | - |
3714 | ret = match_pattern(lhost, allowed_open->listen_host); | - |
3715 | free(lhost); | - |
3716 | | - |
3717 | return ret; never executed: return ret; | 0 |
3718 | } | - |
3719 | | - |
3720 | | - |
3721 | static int | - |
3722 | check_rfwd_permission(struct ssh *ssh, struct Forward *fwd) | - |
3723 | { | - |
3724 | struct ssh_channels *sc = ssh->chanctxt; | - |
3725 | struct permission_set *pset = &sc->remote_perms; | - |
3726 | u_int i, permit, permit_adm = 1; | - |
3727 | struct permission *perm; | - |
3728 | | - |
3729 | | - |
3730 | | - |
3731 | permit = pset->all_permitted; | - |
3732 | if (!permit) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3733 | for (i = 0; i < pset->num_permitted_user; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3734 | perm = &pset->permitted_user[i]; | - |
3735 | if (remote_open_match(perm, fwd)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3736 | permit = 1; | - |
3737 | break; never executed: break; | 0 |
3738 | } | - |
3739 | } never executed: end of block | 0 |
3740 | } never executed: end of block | 0 |
3741 | | - |
3742 | if (pset->num_permitted_admin > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3743 | permit_adm = 0; | - |
3744 | for (i = 0; i < pset->num_permitted_admin; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3745 | perm = &pset->permitted_admin[i]; | - |
3746 | if (remote_open_match(perm, fwd)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3747 | permit_adm = 1; | - |
3748 | break; never executed: break; | 0 |
3749 | } | - |
3750 | } never executed: end of block | 0 |
3751 | } never executed: end of block | 0 |
3752 | | - |
3753 | return permit && permit_adm; never executed: return permit && permit_adm; TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3754 | } | - |
3755 | | - |
3756 | | - |
3757 | int | - |
3758 | channel_setup_remote_fwd_listener(struct ssh *ssh, struct Forward *fwd, | - |
3759 | int *allocated_listen_port, struct ForwardOptions *fwd_opts) | - |
3760 | { | - |
3761 | if (!check_rfwd_permission(ssh, fwd)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3762 | packet_send_debug("port forwarding refused"); | - |
3763 | return 0; never executed: return 0; | 0 |
3764 | } | - |
3765 | if (fwd->listen_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3766 | return channel_setup_fwd_listener_streamlocal(ssh, never executed: return channel_setup_fwd_listener_streamlocal(ssh, 19, fwd, fwd_opts); | 0 |
3767 | SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts); never executed: return channel_setup_fwd_listener_streamlocal(ssh, 19, fwd, fwd_opts); | 0 |
3768 | } else { | - |
3769 | return channel_setup_fwd_listener_tcpip(ssh, never executed: return channel_setup_fwd_listener_tcpip(ssh, 11, fwd, allocated_listen_port, fwd_opts); | 0 |
3770 | SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port, never executed: return channel_setup_fwd_listener_tcpip(ssh, 11, fwd, allocated_listen_port, fwd_opts); | 0 |
3771 | fwd_opts); never executed: return channel_setup_fwd_listener_tcpip(ssh, 11, fwd, allocated_listen_port, fwd_opts); | 0 |
3772 | } | - |
3773 | } | - |
3774 | | - |
3775 | | - |
3776 | | - |
3777 | | - |
3778 | | - |
3779 | static const char * | - |
3780 | channel_rfwd_bind_host(const char *listen_host) | - |
3781 | { | - |
3782 | if (listen_host == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3783 | return "localhost"; never executed: return "localhost"; | 0 |
3784 | } else if (*listen_host == '\0' || strcmp(listen_host, "*") == 0) { never executed: __result = (((const unsigned char *) (const char *) ( listen_host ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "*" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3785 | return ""; never executed: return ""; | 0 |
3786 | } else | - |
3787 | return listen_host; never executed: return listen_host; | 0 |
3788 | } | - |
3789 | | - |
3790 | | - |
3791 | | - |
3792 | | - |
3793 | | - |
3794 | | - |
3795 | | - |
3796 | int | - |
3797 | channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) | - |
3798 | { | - |
3799 | int r, success = 0, idx = -1; | - |
3800 | char *host_to_connect, *listen_host, *listen_path; | - |
3801 | int port_to_connect, listen_port; | - |
3802 | | - |
3803 | | - |
3804 | if (fwd->listen_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3805 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3806 | (r = sshpkt_put_cstring(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3807 | "streamlocal-forward@openssh.com")) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3808 | (r = sshpkt_put_u8(ssh, 1)) != 0 || TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3809 | (r = sshpkt_put_cstring(ssh, fwd->listen_path)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3810 | (r = sshpkt_send(ssh)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3811 | (r = ssh_packet_write_wait(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3812 | fatal("%s: request streamlocal: %s", never executed: fatal("%s: request streamlocal: %s", __func__, ssh_err(r)); | 0 |
3813 | __func__, ssh_err(r)); never executed: fatal("%s: request streamlocal: %s", __func__, ssh_err(r)); | 0 |
3814 | } else { never executed: end of block | 0 |
3815 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3816 | (r = sshpkt_put_cstring(ssh, "tcpip-forward")) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3817 | (r = sshpkt_put_u8(ssh, 1)) != 0 || TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3818 | (r = sshpkt_put_cstring(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3819 | channel_rfwd_bind_host(fwd->listen_host))) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3820 | (r = sshpkt_put_u32(ssh, fwd->listen_port)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3821 | (r = sshpkt_send(ssh)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3822 | (r = ssh_packet_write_wait(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3823 | fatal("%s: request tcpip-forward: %s", never executed: fatal("%s: request tcpip-forward: %s", __func__, ssh_err(r)); | 0 |
3824 | __func__, ssh_err(r)); never executed: fatal("%s: request tcpip-forward: %s", __func__, ssh_err(r)); | 0 |
3825 | } never executed: end of block | 0 |
3826 | | - |
3827 | success = 1; | - |
3828 | if (success) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3829 | | - |
3830 | host_to_connect = listen_host = listen_path = NULL; | - |
3831 | port_to_connect = listen_port = 0; | - |
3832 | if (fwd->connect_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3833 | host_to_connect = xstrdup(fwd->connect_path); | - |
3834 | port_to_connect = PORT_STREAMLOCAL; | - |
3835 | } else { never executed: end of block | 0 |
3836 | host_to_connect = xstrdup(fwd->connect_host); | - |
3837 | port_to_connect = fwd->connect_port; | - |
3838 | } never executed: end of block | 0 |
3839 | if (fwd->listen_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3840 | listen_path = xstrdup(fwd->listen_path); | - |
3841 | listen_port = PORT_STREAMLOCAL; | - |
3842 | } else { never executed: end of block | 0 |
3843 | if (fwd->listen_host != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3844 | listen_host = xstrdup(fwd->listen_host); never executed: listen_host = xstrdup(fwd->listen_host); | 0 |
3845 | listen_port = fwd->listen_port; | - |
3846 | } never executed: end of block | 0 |
3847 | idx = permission_set_add(ssh, FORWARD_USER, FORWARD_LOCAL, | - |
3848 | host_to_connect, port_to_connect, | - |
3849 | listen_host, listen_path, listen_port, NULL); | - |
3850 | } never executed: end of block | 0 |
3851 | return idx; never executed: return idx; | 0 |
3852 | } | - |
3853 | | - |
3854 | static int | - |
3855 | open_match(struct permission *allowed_open, const char *requestedhost, | - |
3856 | int requestedport) | - |
3857 | { | - |
3858 | if (allowed_open->host_to_connect == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3859 | return 0; never executed: return 0; | 0 |
3860 | if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3861 | allowed_open->port_to_connect != requestedport)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3862 | return 0; never executed: return 0; | 0 |
3863 | if (strcmp(allowed_open->host_to_connect, FWD_PERMIT_ANY_HOST) != 0 && never executed: __result = (((const unsigned char *) (const char *) ( allowed_open->host_to_connect ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "*" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3864 | strcmp(allowed_open->host_to_connect, requestedhost) != 0) never executed: __result = (((const unsigned char *) (const char *) ( allowed_open->host_to_connect ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( requestedhost ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3865 | return 0; never executed: return 0; | 0 |
3866 | return 1; never executed: return 1; | 0 |
3867 | } | - |
3868 | | - |
3869 | | - |
3870 | | - |
3871 | | - |
3872 | | - |
3873 | | - |
3874 | | - |
3875 | static int | - |
3876 | open_listen_match_tcpip(struct permission *allowed_open, | - |
3877 | const char *requestedhost, u_short requestedport, int translate) | - |
3878 | { | - |
3879 | const char *allowed_host; | - |
3880 | | - |
3881 | if (allowed_open->host_to_connect == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3882 | return 0; never executed: return 0; | 0 |
3883 | if (allowed_open->listen_port != requestedport)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3884 | return 0; never executed: return 0; | 0 |
3885 | if (!translate && allowed_open->listen_host == NULL &&TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3886 | requestedhost == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3887 | return 1; never executed: return 1; | 0 |
3888 | allowed_host = translate ?TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3889 | channel_rfwd_bind_host(allowed_open->listen_host) : | - |
3890 | allowed_open->listen_host; | - |
3891 | if (allowed_host == NULL || requestedhost == NULL ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3892 | strcmp(allowed_host, requestedhost) != 0) never executed: __result = (((const unsigned char *) (const char *) ( allowed_host ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( requestedhost ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3893 | return 0; never executed: return 0; | 0 |
3894 | return 1; never executed: return 1; | 0 |
3895 | } | - |
3896 | | - |
3897 | static int | - |
3898 | open_listen_match_streamlocal(struct permission *allowed_open, | - |
3899 | const char *requestedpath) | - |
3900 | { | - |
3901 | if (allowed_open->host_to_connect == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3902 | return 0; never executed: return 0; | 0 |
3903 | if (allowed_open->listen_port != PORT_STREAMLOCAL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3904 | return 0; never executed: return 0; | 0 |
3905 | if (allowed_open->listen_path == NULL ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3906 | strcmp(allowed_open->listen_path, requestedpath) != 0) never executed: __result = (((const unsigned char *) (const char *) ( allowed_open->listen_path ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( requestedpath ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3907 | return 0; never executed: return 0; | 0 |
3908 | return 1; never executed: return 1; | 0 |
3909 | } | - |
3910 | | - |
3911 | | - |
3912 | | - |
3913 | | - |
3914 | | - |
3915 | static int | - |
3916 | channel_request_rforward_cancel_tcpip(struct ssh *ssh, | - |
3917 | const char *host, u_short port) | - |
3918 | { | - |
3919 | struct ssh_channels *sc = ssh->chanctxt; | - |
3920 | struct permission_set *pset = &sc->local_perms; | - |
3921 | int r; | - |
3922 | u_int i; | - |
3923 | struct permission *perm; | - |
3924 | | - |
3925 | for (i = 0; i < pset->num_permitted_user; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3926 | perm = &pset->permitted_user[i]; | - |
3927 | if (open_listen_match_tcpip(perm, host, port, 0))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3928 | break; never executed: break; | 0 |
3929 | perm = NULL; | - |
3930 | } never executed: end of block | 0 |
3931 | if (perm == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3932 | debug("%s: requested forward not found", __func__); | - |
3933 | return -1; never executed: return -1; | 0 |
3934 | } | - |
3935 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3936 | (r = sshpkt_put_cstring(ssh, "cancel-tcpip-forward")) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3937 | (r = sshpkt_put_u8(ssh, 0)) != 0 || TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3938 | (r = sshpkt_put_cstring(ssh, channel_rfwd_bind_host(host))) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3939 | (r = sshpkt_put_u32(ssh, port)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3940 | (r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3941 | fatal("%s: send cancel: %s", __func__, ssh_err(r)); never executed: fatal("%s: send cancel: %s", __func__, ssh_err(r)); | 0 |
3942 | | - |
3943 | fwd_perm_clear(perm); | - |
3944 | | - |
3945 | return 0; never executed: return 0; | 0 |
3946 | } | - |
3947 | | - |
3948 | | - |
3949 | | - |
3950 | | - |
3951 | | - |
3952 | static int | - |
3953 | channel_request_rforward_cancel_streamlocal(struct ssh *ssh, const char *path) | - |
3954 | { | - |
3955 | struct ssh_channels *sc = ssh->chanctxt; | - |
3956 | struct permission_set *pset = &sc->local_perms; | - |
3957 | int r; | - |
3958 | u_int i; | - |
3959 | struct permission *perm; | - |
3960 | | - |
3961 | for (i = 0; i < pset->num_permitted_user; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3962 | perm = &pset->permitted_user[i]; | - |
3963 | if (open_listen_match_streamlocal(perm, path))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3964 | break; never executed: break; | 0 |
3965 | perm = NULL; | - |
3966 | } never executed: end of block | 0 |
3967 | if (perm == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3968 | debug("%s: requested forward not found", __func__); | - |
3969 | return -1; never executed: return -1; | 0 |
3970 | } | - |
3971 | if ((r = sshpkt_start(ssh, SSH2_MSG_GLOBAL_REQUEST)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3972 | (r = sshpkt_put_cstring(ssh,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3973 | "cancel-streamlocal-forward@openssh.com")) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3974 | (r = sshpkt_put_u8(ssh, 0)) != 0 || TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3975 | (r = sshpkt_put_cstring(ssh, path)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3976 | (r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3977 | fatal("%s: send cancel: %s", __func__, ssh_err(r)); never executed: fatal("%s: send cancel: %s", __func__, ssh_err(r)); | 0 |
3978 | | - |
3979 | fwd_perm_clear(perm); | - |
3980 | | - |
3981 | return 0; never executed: return 0; | 0 |
3982 | } | - |
3983 | | - |
3984 | | - |
3985 | | - |
3986 | | - |
3987 | int | - |
3988 | channel_request_rforward_cancel(struct ssh *ssh, struct Forward *fwd) | - |
3989 | { | - |
3990 | if (fwd->listen_path != NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
3991 | return channel_request_rforward_cancel_streamlocal(ssh, never executed: return channel_request_rforward_cancel_streamlocal(ssh, fwd->listen_path); | 0 |
3992 | fwd->listen_path); never executed: return channel_request_rforward_cancel_streamlocal(ssh, fwd->listen_path); | 0 |
3993 | } else { | - |
3994 | return channel_request_rforward_cancel_tcpip(ssh, never executed: return channel_request_rforward_cancel_tcpip(ssh, fwd->listen_host, fwd->listen_port ? fwd->listen_port : fwd->allocated_port); | 0 |
3995 | fwd->listen_host, never executed: return channel_request_rforward_cancel_tcpip(ssh, fwd->listen_host, fwd->listen_port ? fwd->listen_port : fwd->allocated_port); | 0 |
3996 | fwd->listen_port ? fwd->listen_port : fwd->allocated_port); never executed: return channel_request_rforward_cancel_tcpip(ssh, fwd->listen_host, fwd->listen_port ? fwd->listen_port : fwd->allocated_port); | 0 |
3997 | } | - |
3998 | } | - |
3999 | | - |
4000 | | - |
4001 | | - |
4002 | | - |
4003 | | - |
4004 | | - |
4005 | void | - |
4006 | channel_permit_all(struct ssh *ssh, int where) | - |
4007 | { | - |
4008 | struct permission_set *pset = permission_set_get(ssh, where); | - |
4009 | | - |
4010 | if (pset->num_permitted_user == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4011 | pset->all_permitted = 1; never executed: pset->all_permitted = 1; | 0 |
4012 | } never executed: end of block | 0 |
4013 | | - |
4014 | | - |
4015 | | - |
4016 | | - |
4017 | void | - |
4018 | channel_add_permission(struct ssh *ssh, int who, int where, | - |
4019 | char *host, int port) | - |
4020 | { | - |
4021 | int local = where == FORWARD_LOCAL; | - |
4022 | struct permission_set *pset = permission_set_get(ssh, where); | - |
4023 | | - |
4024 | debug("allow %s forwarding to host %s port %d", | - |
4025 | fwd_ident(who, where), host, port); | - |
4026 | | - |
4027 | | - |
4028 | | - |
4029 | | - |
4030 | permission_set_add(ssh, who, where, | - |
4031 | local ? host : 0, local ? port : 0, | - |
4032 | local ? NULL : host, NULL, local ? 0 : port, NULL); | - |
4033 | pset->all_permitted = 0; | - |
4034 | } never executed: end of block | 0 |
4035 | | - |
4036 | | - |
4037 | | - |
4038 | | - |
4039 | void | - |
4040 | channel_disable_admin(struct ssh *ssh, int where) | - |
4041 | { | - |
4042 | channel_clear_permission(ssh, FORWARD_ADM, where); | - |
4043 | permission_set_add(ssh, FORWARD_ADM, where, | - |
4044 | NULL, 0, NULL, NULL, 0, NULL); | - |
4045 | } never executed: end of block | 0 |
4046 | | - |
4047 | | - |
4048 | | - |
4049 | | - |
4050 | void | - |
4051 | channel_clear_permission(struct ssh *ssh, int who, int where) | - |
4052 | { | - |
4053 | struct permission **permp; | - |
4054 | u_int *npermp; | - |
4055 | | - |
4056 | permission_set_get_array(ssh, who, where, &permp, &npermp); | - |
4057 | *permp = xrecallocarray(*permp, *npermp, 0, sizeof(**permp)); | - |
4058 | *npermp = 0; | - |
4059 | } never executed: end of block | 0 |
4060 | | - |
4061 | | - |
4062 | | - |
4063 | | - |
4064 | | - |
4065 | | - |
4066 | void | - |
4067 | channel_update_permission(struct ssh *ssh, int idx, int newport) | - |
4068 | { | - |
4069 | struct permission_set *pset = &ssh->chanctxt->local_perms; | - |
4070 | | - |
4071 | if (idx < 0 || (u_int)idx >= pset->num_permitted_user) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4072 | debug("%s: index out of range: %d num_permitted_user %d", | - |
4073 | __func__, idx, pset->num_permitted_user); | - |
4074 | return; never executed: return; | 0 |
4075 | } | - |
4076 | debug("%s allowed port %d for forwarding to host %s port %d", | - |
4077 | newport > 0 ? "Updating" : "Removing", | - |
4078 | newport, | - |
4079 | pset->permitted_user[idx].host_to_connect, | - |
4080 | pset->permitted_user[idx].port_to_connect); | - |
4081 | if (newport <= 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4082 | fwd_perm_clear(&pset->permitted_user[idx]); never executed: fwd_perm_clear(&pset->permitted_user[idx]); | 0 |
4083 | else { | - |
4084 | pset->permitted_user[idx].listen_port = | - |
4085 | (datafellows & SSH_BUG_DYNAMIC_RPORT) ? 0 : newport;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4086 | } never executed: end of block | 0 |
4087 | } | - |
4088 | | - |
4089 | | - |
4090 | int | - |
4091 | permitopen_port(const char *p) | - |
4092 | { | - |
4093 | int port; | - |
4094 | | - |
4095 | if (strcmp(p, "*") == 0) never executed: __result = (((const unsigned char *) (const char *) ( p ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "*" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4096 | return FWD_PERMIT_ANY_PORT; never executed: return 0; | 0 |
4097 | if ((port = a2port(p)) > 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4098 | return port; never executed: return port; | 0 |
4099 | return -1; never executed: return -1; | 0 |
4100 | } | - |
4101 | | - |
4102 | | - |
4103 | static int | - |
4104 | connect_next(struct channel_connect *cctx) | - |
4105 | { | - |
4106 | int sock, saved_errno; | - |
4107 | struct sockaddr_un *sunaddr; | - |
4108 | char ntop[NI_MAXHOST]; | - |
4109 | char strport[MAXIMUM(NI_MAXSERV, sizeof(sunaddr->sun_path))]; | - |
4110 | | - |
4111 | for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4112 | switch (cctx->ai->ai_family) { | - |
4113 | case AF_UNIX: never executed: case 1 : | 0 |
4114 | | - |
4115 | sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr; | - |
4116 | strlcpy(ntop, "unix", sizeof(ntop)); | - |
4117 | strlcpy(strport, sunaddr->sun_path, sizeof(strport)); | - |
4118 | break; never executed: break; | 0 |
4119 | case AF_INET: never executed: case 2 : | 0 |
4120 | case AF_INET6: never executed: case 10 : | 0 |
4121 | if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4122 | ntop, sizeof(ntop), strport, sizeof(strport),TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4123 | NI_NUMERICHOST|NI_NUMERICSERV) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4124 | error("connect_next: getnameinfo failed"); | - |
4125 | continue; never executed: continue; | 0 |
4126 | } | - |
4127 | break; never executed: break; | 0 |
4128 | default: never executed: default: | 0 |
4129 | continue; never executed: continue; | 0 |
4130 | } | - |
4131 | if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4132 | cctx->ai->ai_protocol)) == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4133 | if (cctx->ai->ai_next == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4134 | error("socket: %.100s", strerror(errno)); never executed: error("socket: %.100s", strerror( (*__errno_location ()) )); | 0 |
4135 | else | - |
4136 | verbose("socket: %.100s", strerror(errno)); never executed: verbose("socket: %.100s", strerror( (*__errno_location ()) )); | 0 |
4137 | continue; never executed: continue; | 0 |
4138 | } | - |
4139 | if (set_nonblock(sock) == -1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4140 | fatal("%s: set_nonblock(%d)", __func__, sock); never executed: fatal("%s: set_nonblock(%d)", __func__, sock); | 0 |
4141 | if (connect(sock, cctx->ai->ai_addr,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4142 | cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4143 | debug("connect_next: host %.100s ([%.100s]:%s): " | - |
4144 | "%.100s", cctx->host, ntop, strport, | - |
4145 | strerror(errno)); | - |
4146 | saved_errno = errno; | - |
4147 | close(sock); | - |
4148 | errno = saved_errno; | - |
4149 | continue; never executed: continue; | 0 |
4150 | } | - |
4151 | if (cctx->ai->ai_family != AF_UNIX)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4152 | set_nodelay(sock); never executed: set_nodelay(sock); | 0 |
4153 | debug("connect_next: host %.100s ([%.100s]:%s) " | - |
4154 | "in progress, fd=%d", cctx->host, ntop, strport, sock); | - |
4155 | cctx->ai = cctx->ai->ai_next; | - |
4156 | return sock; never executed: return sock; | 0 |
4157 | } | - |
4158 | return -1; never executed: return -1; | 0 |
4159 | } | - |
4160 | | - |
4161 | static void | - |
4162 | channel_connect_ctx_free(struct channel_connect *cctx) | - |
4163 | { | - |
4164 | free(cctx->host); | - |
4165 | if (cctx->aitop) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4166 | if (cctx->aitop->ai_family == AF_UNIX)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4167 | free(cctx->aitop); never executed: free(cctx->aitop); | 0 |
4168 | else | - |
4169 | freeaddrinfo(cctx->aitop); never executed: freeaddrinfo(cctx->aitop); | 0 |
4170 | } | - |
4171 | memset(cctx, 0, sizeof(*cctx)); | - |
4172 | } never executed: end of block | 0 |
4173 | | - |
4174 | | - |
4175 | | - |
4176 | | - |
4177 | | - |
4178 | static int | - |
4179 | connect_to_helper(struct ssh *ssh, const char *name, int port, int socktype, | - |
4180 | char *ctype, char *rname, struct channel_connect *cctx, | - |
4181 | int *reason, const char **errmsg) | - |
4182 | { | - |
4183 | struct addrinfo hints; | - |
4184 | int gaierr; | - |
4185 | int sock = -1; | - |
4186 | char strport[NI_MAXSERV]; | - |
4187 | | - |
4188 | if (port == PORT_STREAMLOCAL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4189 | struct sockaddr_un *sunaddr; | - |
4190 | struct addrinfo *ai; | - |
4191 | | - |
4192 | if (strlen(name) > sizeof(sunaddr->sun_path)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4193 | error("%.100s: %.100s", name, strerror(ENAMETOOLONG)); | - |
4194 | return -1; never executed: return -1; | 0 |
4195 | } | - |
4196 | | - |
4197 | | - |
4198 | | - |
4199 | | - |
4200 | | - |
4201 | | - |
4202 | ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr)); | - |
4203 | memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr)); | - |
4204 | ai->ai_addr = (struct sockaddr *)(ai + 1); | - |
4205 | ai->ai_addrlen = sizeof(*sunaddr); | - |
4206 | ai->ai_family = AF_UNIX; | - |
4207 | ai->ai_socktype = socktype; | - |
4208 | ai->ai_protocol = PF_UNSPEC; | - |
4209 | sunaddr = (struct sockaddr_un *)ai->ai_addr; | - |
4210 | sunaddr->sun_family = AF_UNIX; | - |
4211 | strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path)); | - |
4212 | cctx->aitop = ai; | - |
4213 | } else { never executed: end of block | 0 |
4214 | memset(&hints, 0, sizeof(hints)); | - |
4215 | hints.ai_family = ssh->chanctxt->IPv4or6; | - |
4216 | hints.ai_socktype = socktype; | - |
4217 | snprintf(strport, sizeof strport, "%d", port); | - |
4218 | if ((gaierr = getaddrinfo(name, strport, &hints, &cctx->aitop))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4219 | != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4220 | if (errmsg != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4221 | *errmsg = ssh_gai_strerror(gaierr); never executed: *errmsg = ssh_gai_strerror(gaierr); | 0 |
4222 | if (reason != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4223 | *reason = SSH2_OPEN_CONNECT_FAILED; never executed: *reason = 2; | 0 |
4224 | error("connect_to %.100s: unknown host (%s)", name, | - |
4225 | ssh_gai_strerror(gaierr)); | - |
4226 | return -1; never executed: return -1; | 0 |
4227 | } | - |
4228 | } never executed: end of block | 0 |
4229 | | - |
4230 | cctx->host = xstrdup(name); | - |
4231 | cctx->port = port; | - |
4232 | cctx->ai = cctx->aitop; | - |
4233 | | - |
4234 | if ((sock = connect_next(cctx)) == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4235 | error("connect to %.100s port %d failed: %s", | - |
4236 | name, port, strerror(errno)); | - |
4237 | return -1; never executed: return -1; | 0 |
4238 | } | - |
4239 | | - |
4240 | return sock; never executed: return sock; | 0 |
4241 | } | - |
4242 | | - |
4243 | | - |
4244 | static Channel * | - |
4245 | connect_to(struct ssh *ssh, const char *host, int port, | - |
4246 | char *ctype, char *rname) | - |
4247 | { | - |
4248 | struct channel_connect cctx; | - |
4249 | Channel *c; | - |
4250 | int sock; | - |
4251 | | - |
4252 | memset(&cctx, 0, sizeof(cctx)); | - |
4253 | sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname, | - |
4254 | &cctx, NULL, NULL); | - |
4255 | if (sock == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4256 | channel_connect_ctx_free(&cctx); | - |
4257 | return NULL; never executed: return ((void *)0) ; | 0 |
4258 | } | - |
4259 | c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, | - |
4260 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); | - |
4261 | c->host_port = port; | - |
4262 | c->path = xstrdup(host); | - |
4263 | c->connect_ctx = cctx; | - |
4264 | | - |
4265 | return c; never executed: return c; | 0 |
4266 | } | - |
4267 | | - |
4268 | | - |
4269 | | - |
4270 | | - |
4271 | | - |
4272 | Channel * | - |
4273 | channel_connect_by_listen_address(struct ssh *ssh, const char *listen_host, | - |
4274 | u_short listen_port, char *ctype, char *rname) | - |
4275 | { | - |
4276 | struct ssh_channels *sc = ssh->chanctxt; | - |
4277 | struct permission_set *pset = &sc->local_perms; | - |
4278 | u_int i; | - |
4279 | struct permission *perm; | - |
4280 | | - |
4281 | for (i = 0; i < pset->num_permitted_user; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4282 | perm = &pset->permitted_user[i]; | - |
4283 | if (open_listen_match_tcpip(perm,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4284 | listen_host, listen_port, 1)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4285 | if (perm->downstream)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4286 | return perm->downstream; never executed: return perm->downstream; | 0 |
4287 | if (perm->port_to_connect == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4288 | return rdynamic_connect_prepare(ssh, never executed: return rdynamic_connect_prepare(ssh, ctype, rname); | 0 |
4289 | ctype, rname); never executed: return rdynamic_connect_prepare(ssh, ctype, rname); | 0 |
4290 | return connect_to(ssh, never executed: return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); | 0 |
4291 | perm->host_to_connect, perm->port_to_connect, never executed: return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); | 0 |
4292 | ctype, rname); never executed: return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); | 0 |
4293 | } | - |
4294 | } never executed: end of block | 0 |
4295 | error("WARNING: Server requests forwarding for unknown listen_port %d", | - |
4296 | listen_port); | - |
4297 | return NULL; never executed: return ((void *)0) ; | 0 |
4298 | } | - |
4299 | | - |
4300 | Channel * | - |
4301 | channel_connect_by_listen_path(struct ssh *ssh, const char *path, | - |
4302 | char *ctype, char *rname) | - |
4303 | { | - |
4304 | struct ssh_channels *sc = ssh->chanctxt; | - |
4305 | struct permission_set *pset = &sc->local_perms; | - |
4306 | u_int i; | - |
4307 | struct permission *perm; | - |
4308 | | - |
4309 | for (i = 0; i < pset->num_permitted_user; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4310 | perm = &pset->permitted_user[i]; | - |
4311 | if (open_listen_match_streamlocal(perm, path)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4312 | return connect_to(ssh, never executed: return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); | 0 |
4313 | perm->host_to_connect, perm->port_to_connect, never executed: return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); | 0 |
4314 | ctype, rname); never executed: return connect_to(ssh, perm->host_to_connect, perm->port_to_connect, ctype, rname); | 0 |
4315 | } | - |
4316 | } never executed: end of block | 0 |
4317 | error("WARNING: Server requests forwarding for unknown path %.100s", | - |
4318 | path); | - |
4319 | return NULL; never executed: return ((void *)0) ; | 0 |
4320 | } | - |
4321 | | - |
4322 | | - |
4323 | Channel * | - |
4324 | channel_connect_to_port(struct ssh *ssh, const char *host, u_short port, | - |
4325 | char *ctype, char *rname, int *reason, const char **errmsg) | - |
4326 | { | - |
4327 | struct ssh_channels *sc = ssh->chanctxt; | - |
4328 | struct permission_set *pset = &sc->local_perms; | - |
4329 | struct channel_connect cctx; | - |
4330 | Channel *c; | - |
4331 | u_int i, permit, permit_adm = 1; | - |
4332 | int sock; | - |
4333 | struct permission *perm; | - |
4334 | | - |
4335 | permit = pset->all_permitted; | - |
4336 | if (!permit) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4337 | for (i = 0; i < pset->num_permitted_user; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4338 | perm = &pset->permitted_user[i]; | - |
4339 | if (open_match(perm, host, port)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4340 | permit = 1; | - |
4341 | break; never executed: break; | 0 |
4342 | } | - |
4343 | } never executed: end of block | 0 |
4344 | } never executed: end of block | 0 |
4345 | | - |
4346 | if (pset->num_permitted_admin > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4347 | permit_adm = 0; | - |
4348 | for (i = 0; i < pset->num_permitted_admin; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4349 | perm = &pset->permitted_admin[i]; | - |
4350 | if (open_match(perm, host, port)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4351 | permit_adm = 1; | - |
4352 | break; never executed: break; | 0 |
4353 | } | - |
4354 | } never executed: end of block | 0 |
4355 | } never executed: end of block | 0 |
4356 | | - |
4357 | if (!permit || !permit_adm) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4358 | logit("Received request to connect to host %.100s port %d, " | - |
4359 | "but the request was denied.", host, port); | - |
4360 | if (reason != NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4361 | *reason = SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED; never executed: *reason = 1; | 0 |
4362 | return NULL; never executed: return ((void *)0) ; | 0 |
4363 | } | - |
4364 | | - |
4365 | memset(&cctx, 0, sizeof(cctx)); | - |
4366 | sock = connect_to_helper(ssh, host, port, SOCK_STREAM, ctype, rname, | - |
4367 | &cctx, reason, errmsg); | - |
4368 | if (sock == -1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4369 | channel_connect_ctx_free(&cctx); | - |
4370 | return NULL; never executed: return ((void *)0) ; | 0 |
4371 | } | - |
4372 | | - |
4373 | c = channel_new(ssh, ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, | - |
4374 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); | - |
4375 | c->host_port = port; | - |
4376 | c->path = xstrdup(host); | - |
4377 | c->connect_ctx = cctx; | - |
4378 | | - |
4379 | return c; never executed: return c; | 0 |
4380 | } | - |
4381 | | - |
4382 | | - |
4383 | Channel * | - |
4384 | channel_connect_to_path(struct ssh *ssh, const char *path, | - |
4385 | char *ctype, char *rname) | - |
4386 | { | - |
4387 | struct ssh_channels *sc = ssh->chanctxt; | - |
4388 | struct permission_set *pset = &sc->local_perms; | - |
4389 | u_int i, permit, permit_adm = 1; | - |
4390 | struct permission *perm; | - |
4391 | | - |
4392 | permit = pset->all_permitted; | - |
4393 | if (!permit) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4394 | for (i = 0; i < pset->num_permitted_user; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4395 | perm = &pset->permitted_user[i]; | - |
4396 | if (open_match(perm, path, PORT_STREAMLOCAL)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4397 | permit = 1; | - |
4398 | break; never executed: break; | 0 |
4399 | } | - |
4400 | } never executed: end of block | 0 |
4401 | } never executed: end of block | 0 |
4402 | | - |
4403 | if (pset->num_permitted_admin > 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4404 | permit_adm = 0; | - |
4405 | for (i = 0; i < pset->num_permitted_admin; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4406 | perm = &pset->permitted_admin[i]; | - |
4407 | if (open_match(perm, path, PORT_STREAMLOCAL)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4408 | permit_adm = 1; | - |
4409 | break; never executed: break; | 0 |
4410 | } | - |
4411 | } never executed: end of block | 0 |
4412 | } never executed: end of block | 0 |
4413 | | - |
4414 | if (!permit || !permit_adm) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4415 | logit("Received request to connect to path %.100s, " | - |
4416 | "but the request was denied.", path); | - |
4417 | return NULL; never executed: return ((void *)0) ; | 0 |
4418 | } | - |
4419 | return connect_to(ssh, path, PORT_STREAMLOCAL, ctype, rname); never executed: return connect_to(ssh, path, -2, ctype, rname); | 0 |
4420 | } | - |
4421 | | - |
4422 | void | - |
4423 | channel_send_window_changes(struct ssh *ssh) | - |
4424 | { | - |
4425 | struct ssh_channels *sc = ssh->chanctxt; | - |
4426 | struct winsize ws; | - |
4427 | int r; | - |
4428 | u_int i; | - |
4429 | | - |
4430 | for (i = 0; i < sc->channels_alloc; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4431 | if (sc->channels[i] == NULL || !sc->channels[i]->client_tty ||TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4432 | sc->channels[i]->type != SSH_CHANNEL_OPEN)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4433 | continue; never executed: continue; | 0 |
4434 | if (ioctl(sc->channels[i]->rfd, TIOCGWINSZ, &ws) < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4435 | continue; never executed: continue; | 0 |
4436 | channel_request_start(ssh, i, "window-change", 0); | - |
4437 | if ((r = sshpkt_put_u32(ssh, (u_int)ws.ws_col)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4438 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_row)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4439 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_xpixel)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4440 | (r = sshpkt_put_u32(ssh, (u_int)ws.ws_ypixel)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4441 | (r = sshpkt_send(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4442 | fatal("%s: channel %u: send window-change: %s", never executed: fatal("%s: channel %u: send window-change: %s", __func__, i, ssh_err(r)); | 0 |
4443 | __func__, i, ssh_err(r)); never executed: fatal("%s: channel %u: send window-change: %s", __func__, i, ssh_err(r)); | 0 |
4444 | } never executed: end of block | 0 |
4445 | } never executed: end of block | 0 |
4446 | | - |
4447 | | - |
4448 | static Channel * | - |
4449 | rdynamic_connect_prepare(struct ssh *ssh, char *ctype, char *rname) | - |
4450 | { | - |
4451 | Channel *c; | - |
4452 | int r; | - |
4453 | | - |
4454 | c = channel_new(ssh, ctype, SSH_CHANNEL_RDYNAMIC_OPEN, -1, -1, -1, | - |
4455 | CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1); | - |
4456 | c->host_port = 0; | - |
4457 | c->path = NULL; | - |
4458 | | - |
4459 | | - |
4460 | | - |
4461 | | - |
4462 | | - |
4463 | if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4464 | (r = sshpkt_put_u32(ssh, c->remote_id)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4465 | (r = sshpkt_put_u32(ssh, c->self)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4466 | (r = sshpkt_put_u32(ssh, c->local_window)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4467 | (r = sshpkt_put_u32(ssh, c->local_maxpacket)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4468 | fatal("%s: channel %i: confirm: %s", __func__, | - |
4469 | c->self, ssh_err(r)); | - |
4470 | } never executed: end of block | 0 |
4471 | return c; never executed: return c; | 0 |
4472 | } | - |
4473 | | - |
4474 | | - |
4475 | static int | - |
4476 | rdynamic_connect_finish(struct ssh *ssh, Channel *c) | - |
4477 | { | - |
4478 | struct channel_connect cctx; | - |
4479 | int sock; | - |
4480 | | - |
4481 | memset(&cctx, 0, sizeof(cctx)); | - |
4482 | sock = connect_to_helper(ssh, c->path, c->host_port, SOCK_STREAM, NULL, | - |
4483 | NULL, &cctx, NULL, NULL); | - |
4484 | if (sock == -1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4485 | channel_connect_ctx_free(&cctx); never executed: channel_connect_ctx_free(&cctx); | 0 |
4486 | else { | - |
4487 | | - |
4488 | c->type = SSH_CHANNEL_RDYNAMIC_FINISH; | - |
4489 | c->connect_ctx = cctx; | - |
4490 | channel_register_fds(ssh, c, sock, sock, -1, 0, 1, 0); | - |
4491 | } never executed: end of block | 0 |
4492 | return sock; never executed: return sock; | 0 |
4493 | } | - |
4494 | | - |
4495 | | - |
4496 | | - |
4497 | | - |
4498 | | - |
4499 | | - |
4500 | | - |
4501 | | - |
4502 | int | - |
4503 | x11_create_display_inet(struct ssh *ssh, int x11_display_offset, | - |
4504 | int x11_use_localhost, int single_connection, | - |
4505 | u_int *display_numberp, int **chanids) | - |
4506 | { | - |
4507 | Channel *nc = NULL; | - |
4508 | int display_number, sock; | - |
4509 | u_short port; | - |
4510 | struct addrinfo hints, *ai, *aitop; | - |
4511 | char strport[NI_MAXSERV]; | - |
4512 | int gaierr, n, num_socks = 0, socks[NUM_SOCKS]; | - |
4513 | | - |
4514 | if (chanids == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4515 | return -1; never executed: return -1; | 0 |
4516 | | - |
4517 | for (display_number = x11_display_offset; | - |
4518 | display_number < MAX_DISPLAYS;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4519 | display_number++) { | - |
4520 | port = 6000 + display_number; | - |
4521 | memset(&hints, 0, sizeof(hints)); | - |
4522 | hints.ai_family = ssh->chanctxt->IPv4or6; | - |
4523 | hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE;TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4524 | hints.ai_socktype = SOCK_STREAM; | - |
4525 | snprintf(strport, sizeof strport, "%d", port); | - |
4526 | if ((gaierr = getaddrinfo(NULL, strport,TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4527 | &hints, &aitop)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4528 | error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr)); | - |
4529 | return -1; never executed: return -1; | 0 |
4530 | } | - |
4531 | for (ai = aitop; ai; ai = ai->ai_next) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4532 | if (ai->ai_family != AF_INET &&TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4533 | ai->ai_family != AF_INET6)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4534 | continue; never executed: continue; | 0 |
4535 | sock = socket(ai->ai_family, ai->ai_socktype, | - |
4536 | ai->ai_protocol); | - |
4537 | if (sock < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4538 | if ((errno != EINVAL) && (errno != EAFNOSUPPORT)TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4539 | #ifdef EPFNOSUPPORT | - |
4540 | && (errno != EPFNOSUPPORT)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4541 | #endif | - |
4542 | ) { | - |
4543 | error("socket: %.100s", strerror(errno)); | - |
4544 | freeaddrinfo(aitop); | - |
4545 | return -1; never executed: return -1; | 0 |
4546 | } else { | - |
4547 | debug("x11_create_display_inet: Socket family %d not supported", | - |
4548 | ai->ai_family); | - |
4549 | continue; never executed: continue; | 0 |
4550 | } | - |
4551 | } | - |
4552 | if (ai->ai_family == AF_INET6)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4553 | sock_set_v6only(sock); never executed: sock_set_v6only(sock); | 0 |
4554 | if (x11_use_localhost)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4555 | set_reuseaddr(sock); never executed: set_reuseaddr(sock); | 0 |
4556 | if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4557 | debug2("%s: bind port %d: %.100s", __func__, | - |
4558 | port, strerror(errno)); | - |
4559 | close(sock); | - |
4560 | for (n = 0; n < num_socks; n++)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4561 | close(socks[n]); never executed: close(socks[n]); | 0 |
4562 | num_socks = 0; | - |
4563 | break; never executed: break; | 0 |
4564 | } | - |
4565 | socks[num_socks++] = sock; | - |
4566 | if (num_socks == NUM_SOCKS)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4567 | break; never executed: break; | 0 |
4568 | } never executed: end of block | 0 |
4569 | freeaddrinfo(aitop); | - |
4570 | if (num_socks > 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4571 | break; never executed: break; | 0 |
4572 | } never executed: end of block | 0 |
4573 | if (display_number >= MAX_DISPLAYS) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4574 | error("Failed to allocate internet-domain X11 display socket."); | - |
4575 | return -1; never executed: return -1; | 0 |
4576 | } | - |
4577 | | - |
4578 | for (n = 0; n < num_socks; n++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4579 | sock = socks[n]; | - |
4580 | if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4581 | error("listen: %.100s", strerror(errno)); | - |
4582 | close(sock); | - |
4583 | return -1; never executed: return -1; | 0 |
4584 | } | - |
4585 | } never executed: end of block | 0 |
4586 | | - |
4587 | | - |
4588 | *chanids = xcalloc(num_socks + 1, sizeof(**chanids)); | - |
4589 | for (n = 0; n < num_socks; n++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4590 | sock = socks[n]; | - |
4591 | nc = channel_new(ssh, "x11 listener", | - |
4592 | SSH_CHANNEL_X11_LISTENER, sock, sock, -1, | - |
4593 | CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, | - |
4594 | 0, "X11 inet listener", 1); | - |
4595 | nc->single_connection = single_connection; | - |
4596 | (*chanids)[n] = nc->self; | - |
4597 | } never executed: end of block | 0 |
4598 | (*chanids)[n] = -1; | - |
4599 | | - |
4600 | | - |
4601 | *display_numberp = display_number; | - |
4602 | return 0; never executed: return 0; | 0 |
4603 | } | - |
4604 | | - |
4605 | static int | - |
4606 | connect_local_xsocket_path(const char *pathname) | - |
4607 | { | - |
4608 | int sock; | - |
4609 | struct sockaddr_un addr; | - |
4610 | | - |
4611 | sock = socket(AF_UNIX, SOCK_STREAM, 0); | - |
4612 | if (sock < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4613 | error("socket: %.100s", strerror(errno)); never executed: error("socket: %.100s", strerror( (*__errno_location ()) )); | 0 |
4614 | memset(&addr, 0, sizeof(addr)); | - |
4615 | addr.sun_family = AF_UNIX; | - |
4616 | strlcpy(addr.sun_path, pathname, sizeof addr.sun_path); | - |
4617 | if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4618 | return sock; never executed: return sock; | 0 |
4619 | close(sock); | - |
4620 | error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); | - |
4621 | return -1; never executed: return -1; | 0 |
4622 | } | - |
4623 | | - |
4624 | static int | - |
4625 | connect_local_xsocket(u_int dnr) | - |
4626 | { | - |
4627 | char buf[1024]; | - |
4628 | snprintf(buf, sizeof buf, _PATH_UNIX_X, dnr); | - |
4629 | return connect_local_xsocket_path(buf); never executed: return connect_local_xsocket_path(buf); | 0 |
4630 | } | - |
4631 | | - |
4632 | #ifdef __APPLE__ | - |
4633 | static int | - |
4634 | is_path_to_xsocket(const char *display, char *path, size_t pathlen) | - |
4635 | { | - |
4636 | struct stat sbuf; | - |
4637 | | - |
4638 | if (strlcpy(path, display, pathlen) >= pathlen) { | - |
4639 | error("%s: display path too long", __func__); | - |
4640 | return 0; | - |
4641 | } | - |
4642 | if (display[0] != '/') | - |
4643 | return 0; | - |
4644 | if (stat(path, &sbuf) == 0) { | - |
4645 | return 1; | - |
4646 | } else { | - |
4647 | char *dot = strrchr(path, '.'); | - |
4648 | if (dot != NULL) { | - |
4649 | *dot = '\0'; | - |
4650 | if (stat(path, &sbuf) == 0) { | - |
4651 | return 1; | - |
4652 | } | - |
4653 | } | - |
4654 | } | - |
4655 | return 0; | - |
4656 | } | - |
4657 | #endif | - |
4658 | | - |
4659 | int | - |
4660 | x11_connect_display(struct ssh *ssh) | - |
4661 | { | - |
4662 | u_int display_number; | - |
4663 | const char *display; | - |
4664 | char buf[1024], *cp; | - |
4665 | struct addrinfo hints, *ai, *aitop; | - |
4666 | char strport[NI_MAXSERV]; | - |
4667 | int gaierr, sock = 0; | - |
4668 | | - |
4669 | | - |
4670 | display = getenv("DISPLAY"); | - |
4671 | if (!display) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4672 | error("DISPLAY not set."); | - |
4673 | return -1; never executed: return -1; | 0 |
4674 | } | - |
4675 | | - |
4676 | | - |
4677 | | - |
4678 | | - |
4679 | | - |
4680 | #ifdef __APPLE__ | - |
4681 | | - |
4682 | { | - |
4683 | char path[PATH_MAX]; | - |
4684 | | - |
4685 | if (is_path_to_xsocket(display, path, sizeof(path))) { | - |
4686 | debug("x11_connect_display: $DISPLAY is launchd"); | - |
4687 | | - |
4688 | | - |
4689 | sock = connect_local_xsocket_path(path); | - |
4690 | if (sock < 0) | - |
4691 | return -1; | - |
4692 | | - |
4693 | | - |
4694 | return sock; | - |
4695 | } | - |
4696 | } | - |
4697 | #endif | - |
4698 | | - |
4699 | | - |
4700 | | - |
4701 | | - |
4702 | if (strncmp(display, "unix:", 5) == 0 || never executed: __result = (((const unsigned char *) (const char *) ( display ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( "unix:" ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4703 | display[0] == ':') {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4704 | | - |
4705 | if (sscanf(strrchr(display, ':') + 1, "%u",TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4706 | &display_number) != 1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4707 | error("Could not parse display number from DISPLAY: " | - |
4708 | "%.100s", display); | - |
4709 | return -1; never executed: return -1; | 0 |
4710 | } | - |
4711 | | - |
4712 | sock = connect_local_xsocket(display_number); | - |
4713 | if (sock < 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4714 | return -1; never executed: return -1; | 0 |
4715 | | - |
4716 | | - |
4717 | return sock; never executed: return sock; | 0 |
4718 | } | - |
4719 | | - |
4720 | | - |
4721 | | - |
4722 | | - |
4723 | strlcpy(buf, display, sizeof(buf)); | - |
4724 | cp = strchr(buf, ':');TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4725 | if (!cp) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4726 | error("Could not find ':' in DISPLAY: %.100s", display); | - |
4727 | return -1; never executed: return -1; | 0 |
4728 | } | - |
4729 | *cp = 0; | - |
4730 | | - |
4731 | | - |
4732 | | - |
4733 | | - |
4734 | if (sscanf(cp + 1, "%u", &display_number) != 1) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4735 | error("Could not parse display number from DISPLAY: %.100s", | - |
4736 | display); | - |
4737 | return -1; never executed: return -1; | 0 |
4738 | } | - |
4739 | | - |
4740 | | - |
4741 | memset(&hints, 0, sizeof(hints)); | - |
4742 | hints.ai_family = ssh->chanctxt->IPv4or6; | - |
4743 | hints.ai_socktype = SOCK_STREAM; | - |
4744 | snprintf(strport, sizeof strport, "%u", 6000 + display_number); | - |
4745 | if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4746 | error("%.100s: unknown host. (%s)", buf, | - |
4747 | ssh_gai_strerror(gaierr)); | - |
4748 | return -1; never executed: return -1; | 0 |
4749 | } | - |
4750 | for (ai = aitop; ai; ai = ai->ai_next) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4751 | | - |
4752 | sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); | - |
4753 | if (sock < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4754 | debug2("socket: %.100s", strerror(errno)); | - |
4755 | continue; never executed: continue; | 0 |
4756 | } | - |
4757 | | - |
4758 | if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4759 | debug2("connect %.100s port %u: %.100s", buf, | - |
4760 | 6000 + display_number, strerror(errno)); | - |
4761 | close(sock); | - |
4762 | continue; never executed: continue; | 0 |
4763 | } | - |
4764 | | - |
4765 | break; never executed: break; | 0 |
4766 | } | - |
4767 | freeaddrinfo(aitop); | - |
4768 | if (!ai) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4769 | error("connect %.100s port %u: %.100s", buf, | - |
4770 | 6000 + display_number, strerror(errno)); | - |
4771 | return -1; never executed: return -1; | 0 |
4772 | } | - |
4773 | set_nodelay(sock); | - |
4774 | return sock; never executed: return sock; | 0 |
4775 | } | - |
4776 | | - |
4777 | | - |
4778 | | - |
4779 | | - |
4780 | | - |
4781 | | - |
4782 | void | - |
4783 | x11_request_forwarding_with_spoofing(struct ssh *ssh, int client_session_id, | - |
4784 | const char *disp, const char *proto, const char *data, int want_reply) | - |
4785 | { | - |
4786 | struct ssh_channels *sc = ssh->chanctxt; | - |
4787 | u_int data_len = (u_int) strlen(data) / 2; | - |
4788 | u_int i, value; | - |
4789 | const char *cp; | - |
4790 | char *new_data; | - |
4791 | int r, screen_number; | - |
4792 | | - |
4793 | if (sc->x11_saved_display == NULL)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4794 | sc->x11_saved_display = xstrdup(disp); never executed: sc->x11_saved_display = xstrdup(disp); | 0 |
4795 | else if (strcmp(disp, sc->x11_saved_display) != 0) { never executed: __result = (((const unsigned char *) (const char *) ( disp ))[3] - __s2[3]); never executed: end of block never executed: end of block never executed: __result = (((const unsigned char *) (const char *) ( sc->x11_saved_display ))[3] - __s2[3]); never executed: end of block never executed: end of block TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4796 | error("x11_request_forwarding_with_spoofing: different " | - |
4797 | "$DISPLAY already forwarded"); | - |
4798 | return; never executed: return; | 0 |
4799 | } | - |
4800 | | - |
4801 | cp = strchr(disp, ':');TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4802 | if (cp)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4803 | cp = strchr(cp, '.'); never executed: cp = (__extension__ (__builtin_constant_p ( '.' ) && !__builtin_constant_p ( cp ) && ( '.' ) == '\0' ? (char *) __rawmemchr ( cp , '.' ) : __builtin_strchr ( cp , '.' ))) ; TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4804 | if (cp)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4805 | screen_number = (u_int)strtonum(cp + 1, 0, 400, NULL); never executed: screen_number = (u_int)strtonum(cp + 1, 0, 400, ((void *)0) ); | 0 |
4806 | else | - |
4807 | screen_number = 0; never executed: screen_number = 0; | 0 |
4808 | | - |
4809 | if (sc->x11_saved_proto == NULL) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4810 | | - |
4811 | sc->x11_saved_proto = xstrdup(proto); | - |
4812 | | - |
4813 | | - |
4814 | sc->x11_saved_data = xmalloc(data_len); | - |
4815 | for (i = 0; i < data_len; i++) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4816 | if (sscanf(data + 2 * i, "%2x", &value) != 1)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4817 | fatal("x11_request_forwarding: bad " never executed: fatal("x11_request_forwarding: bad " "authentication data: %.100s", data); | 0 |
4818 | "authentication data: %.100s", data); never executed: fatal("x11_request_forwarding: bad " "authentication data: %.100s", data); | 0 |
4819 | sc->x11_saved_data[i] = value; | - |
4820 | } never executed: end of block | 0 |
4821 | sc->x11_saved_data_len = data_len; | - |
4822 | | - |
4823 | | - |
4824 | sc->x11_fake_data = xmalloc(data_len); | - |
4825 | arc4random_buf(sc->x11_fake_data, data_len); | - |
4826 | sc->x11_fake_data_len = data_len; | - |
4827 | } never executed: end of block | 0 |
4828 | | - |
4829 | | - |
4830 | new_data = tohex(sc->x11_fake_data, data_len); | - |
4831 | | - |
4832 | | - |
4833 | channel_request_start(ssh, client_session_id, "x11-req", want_reply); | - |
4834 | if ((r = sshpkt_put_u8(ssh, 0)) != 0 || TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4835 | (r = sshpkt_put_cstring(ssh, proto)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4836 | (r = sshpkt_put_cstring(ssh, new_data)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4837 | (r = sshpkt_put_u32(ssh, screen_number)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4838 | (r = sshpkt_send(ssh)) != 0 ||TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4839 | (r = ssh_packet_write_wait(ssh)) != 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
4840 | fatal("%s: send x11-req: %s", __func__, ssh_err(r)); never executed: fatal("%s: send x11-req: %s", __func__, ssh_err(r)); | 0 |
4841 | free(new_data); | - |
4842 | } never executed: end of block | 0 |
| | |