~ubuntu-branches/ubuntu/lucid/openssh/lucid

« back to all changes in this revision

Viewing changes to channels.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2008-09-30 23:09:58 UTC
  • mfrom: (1.13.3 upstream) (29 hardy)
  • mto: This revision was merged to the branch mainline in revision 43.
  • Revision ID: james.westby@ubuntu.com-20080930230958-o6vsgn8c4mm959s0
Tags: 1:5.1p1-3
* Remove unnecessary ssh-vulnkey output in non-verbose mode when no
  compromised or unknown keys were found (closes: #496495).
* Configure with --disable-strip; dh_strip will deal with stripping
  binaries and will honour DEB_BUILD_OPTIONS (thanks, Bernhard R. Link;
  closes: #498681).
* Fix handling of zero-length server banners (thanks, Tomas Mraz; closes:
  #497026).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $OpenBSD: channels.c,v 1.268 2007/01/03 03:01:40 stevesk Exp $ */
 
1
/* $OpenBSD: channels.c,v 1.286 2008/07/16 11:52:19 djm Exp $ */
2
2
/*
3
3
 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4
4
 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
61
61
#include <unistd.h>
62
62
#include <stdarg.h>
63
63
 
 
64
#include "openbsd-compat/sys-queue.h"
64
65
#include "xmalloc.h"
65
66
#include "ssh.h"
66
67
#include "ssh1.h"
164
165
/* helper */
165
166
static void port_open_helper(Channel *c, char *rtype);
166
167
 
 
168
/* non-blocking connect helpers */
 
169
static int connect_next(struct channel_connect *);
 
170
static void channel_connect_ctx_free(struct channel_connect *);
 
171
 
167
172
/* -- channel core */
168
173
 
169
174
Channel *
216
221
 */
217
222
static void
218
223
channel_register_fds(Channel *c, int rfd, int wfd, int efd,
219
 
    int extusage, int nonblock)
 
224
    int extusage, int nonblock, int is_tty)
220
225
{
221
226
        /* Update the maximum file descriptor value. */
222
227
        channel_max_fd = MAX(channel_max_fd, rfd);
232
237
        c->efd = efd;
233
238
        c->extended_usage = extusage;
234
239
 
235
 
        /* XXX ugly hack: nonblock is only set by the server */
236
 
        if (nonblock && isatty(c->rfd)) {
 
240
        if ((c->isatty = is_tty) != 0)
237
241
                debug2("channel %d: rfd %d isatty", c->self, c->rfd);
238
 
                c->isatty = 1;
239
 
                if (!isatty(c->wfd)) {
240
 
                        error("channel %d: wfd %d is not a tty?",
241
 
                            c->self, c->wfd);
242
 
                }
243
 
        } else {
244
 
                c->isatty = 0;
245
 
        }
246
 
        c->wfd_isatty = isatty(c->wfd);
 
242
        c->wfd_isatty = is_tty || isatty(c->wfd);
247
243
 
248
244
        /* enable nonblocking mode */
249
245
        if (nonblock) {
303
299
        c->ostate = CHAN_OUTPUT_OPEN;
304
300
        c->istate = CHAN_INPUT_OPEN;
305
301
        c->flags = 0;
306
 
        channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
 
302
        channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, 0);
307
303
        c->self = found;
308
304
        c->type = type;
309
305
        c->ctype = ctype;
319
315
        c->single_connection = 0;
320
316
        c->detach_user = NULL;
321
317
        c->detach_close = 0;
322
 
        c->confirm = NULL;
323
 
        c->confirm_ctx = NULL;
 
318
        c->open_confirm = NULL;
 
319
        c->open_confirm_ctx = NULL;
324
320
        c->input_filter = NULL;
325
321
        c->output_filter = NULL;
 
322
        c->filter_ctx = NULL;
 
323
        c->filter_cleanup = NULL;
 
324
        TAILQ_INIT(&c->status_confirms);
326
325
        debug("channel %d: new [%s]", found, remote_name);
327
326
        return c;
328
327
}
379
378
{
380
379
        char *s;
381
380
        u_int i, n;
 
381
        struct channel_confirm *cc;
382
382
 
383
383
        for (n = 0, i = 0; i < channels_alloc; i++)
384
384
                if (channels[i])
402
402
                xfree(c->remote_name);
403
403
                c->remote_name = NULL;
404
404
        }
 
405
        while ((cc = TAILQ_FIRST(&c->status_confirms)) != NULL) {
 
406
                if (cc->abandon_cb != NULL)
 
407
                        cc->abandon_cb(c, cc->ctx);
 
408
                TAILQ_REMOVE(&c->status_confirms, cc, entry);
 
409
                bzero(cc, sizeof(*cc));
 
410
                xfree(cc);
 
411
        }
 
412
        if (c->filter_cleanup != NULL && c->filter_ctx != NULL)
 
413
                c->filter_cleanup(c->self, c->filter_ctx);
405
414
        channels[c->self] = NULL;
406
415
        xfree(c);
407
416
}
660
669
}
661
670
 
662
671
void
663
 
channel_register_confirm(int id, channel_callback_fn *fn, void *ctx)
 
672
channel_register_status_confirm(int id, channel_confirm_cb *cb,
 
673
    channel_confirm_abandon_cb *abandon_cb, void *ctx)
 
674
{
 
675
        struct channel_confirm *cc;
 
676
        Channel *c;
 
677
 
 
678
        if ((c = channel_lookup(id)) == NULL)
 
679
                fatal("channel_register_expect: %d: bad id", id);
 
680
 
 
681
        cc = xmalloc(sizeof(*cc));
 
682
        cc->cb = cb;
 
683
        cc->abandon_cb = abandon_cb;
 
684
        cc->ctx = ctx;
 
685
        TAILQ_INSERT_TAIL(&c->status_confirms, cc, entry);
 
686
}
 
687
 
 
688
void
 
689
channel_register_open_confirm(int id, channel_callback_fn *fn, void *ctx)
664
690
{
665
691
        Channel *c = channel_lookup(id);
666
692
 
667
693
        if (c == NULL) {
668
 
                logit("channel_register_comfirm: %d: bad id", id);
 
694
                logit("channel_register_open_comfirm: %d: bad id", id);
669
695
                return;
670
696
        }
671
 
        c->confirm = fn;
672
 
        c->confirm_ctx = ctx;
 
697
        c->open_confirm = fn;
 
698
        c->open_confirm_ctx = ctx;
673
699
}
674
700
 
675
701
void
700
726
 
701
727
void
702
728
channel_register_filter(int id, channel_infilter_fn *ifn,
703
 
    channel_outfilter_fn *ofn)
 
729
    channel_outfilter_fn *ofn, channel_filter_cleanup_fn *cfn, void *ctx)
704
730
{
705
731
        Channel *c = channel_lookup(id);
706
732
 
710
736
        }
711
737
        c->input_filter = ifn;
712
738
        c->output_filter = ofn;
 
739
        c->filter_ctx = ctx;
 
740
        c->filter_cleanup = cfn;
713
741
}
714
742
 
715
743
void
716
744
channel_set_fds(int id, int rfd, int wfd, int efd,
717
 
    int extusage, int nonblock, u_int window_max)
 
745
    int extusage, int nonblock, int is_tty, u_int window_max)
718
746
{
719
747
        Channel *c = channel_lookup(id);
720
748
 
721
749
        if (c == NULL || c->type != SSH_CHANNEL_LARVAL)
722
750
                fatal("channel_activate for non-larval channel %d.", id);
723
 
        channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);
 
751
        channel_register_fds(c, rfd, wfd, efd, extusage, nonblock, is_tty);
724
752
        c->type = SSH_CHANNEL_OPEN;
725
753
        c->local_window = c->local_window_max = window_max;
726
754
        packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
788
816
                }
789
817
        }
790
818
        /** XXX check close conditions, too */
791
 
        if (compat20 && c->efd != -1) {
 
819
        if (compat20 && c->efd != -1 && 
 
820
            !(c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED)) {
792
821
                if (c->extended_usage == CHAN_EXTENDED_WRITE &&
793
822
                    buffer_len(&c->extended) > 0)
794
823
                        FD_SET(c->efd, writeset);
1181
1210
channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
1182
1211
{
1183
1212
        Channel *nc;
1184
 
        struct sockaddr addr;
 
1213
        struct sockaddr_storage addr;
1185
1214
        int newsock;
1186
1215
        socklen_t addrlen;
1187
1216
        char buf[16384], *remote_ipaddr;
1190
1219
        if (FD_ISSET(c->sock, readset)) {
1191
1220
                debug("X11 connection requested.");
1192
1221
                addrlen = sizeof(addr);
1193
 
                newsock = accept(c->sock, &addr, &addrlen);
 
1222
                newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1194
1223
                if (c->single_connection) {
1195
1224
                        debug2("single_connection: closing X11 listener.");
1196
1225
                        channel_close_fd(&c->sock);
1307
1336
channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1308
1337
{
1309
1338
        Channel *nc;
1310
 
        struct sockaddr addr;
 
1339
        struct sockaddr_storage addr;
1311
1340
        int newsock, nextstate;
1312
1341
        socklen_t addrlen;
1313
1342
        char *rtype;
1331
1360
                }
1332
1361
 
1333
1362
                addrlen = sizeof(addr);
1334
 
                newsock = accept(c->sock, &addr, &addrlen);
 
1363
                newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1335
1364
                if (newsock < 0) {
1336
1365
                        error("accept: %.100s", strerror(errno));
1337
1366
                        return;
1366
1395
{
1367
1396
        Channel *nc;
1368
1397
        int newsock;
1369
 
        struct sockaddr addr;
 
1398
        struct sockaddr_storage addr;
1370
1399
        socklen_t addrlen;
1371
1400
 
1372
1401
        if (FD_ISSET(c->sock, readset)) {
1373
1402
                addrlen = sizeof(addr);
1374
 
                newsock = accept(c->sock, &addr, &addrlen);
 
1403
                newsock = accept(c->sock, (struct sockaddr *)&addr, &addrlen);
1375
1404
                if (newsock < 0) {
1376
1405
                        error("accept from auth socket: %.100s", strerror(errno));
1377
1406
                        return;
1398
1427
static void
1399
1428
channel_post_connecting(Channel *c, fd_set *readset, fd_set *writeset)
1400
1429
{
1401
 
        int err = 0;
 
1430
        int err = 0, sock;
1402
1431
        socklen_t sz = sizeof(err);
1403
1432
 
1404
1433
        if (FD_ISSET(c->sock, writeset)) {
1407
1436
                        error("getsockopt SO_ERROR failed");
1408
1437
                }
1409
1438
                if (err == 0) {
1410
 
                        debug("channel %d: connected", c->self);
 
1439
                        debug("channel %d: connected to %s port %d",
 
1440
                            c->self, c->connect_ctx.host, c->connect_ctx.port);
 
1441
                        channel_connect_ctx_free(&c->connect_ctx);
1411
1442
                        c->type = SSH_CHANNEL_OPEN;
1412
1443
                        if (compat20) {
1413
1444
                                packet_start(SSH2_MSG_CHANNEL_OPEN_CONFIRMATION);
1421
1452
                                packet_put_int(c->self);
1422
1453
                        }
1423
1454
                } else {
1424
 
                        debug("channel %d: not connected: %s",
 
1455
                        debug("channel %d: connection failed: %s",
1425
1456
                            c->self, strerror(err));
 
1457
                        /* Try next address, if any */
 
1458
                        if ((sock = connect_next(&c->connect_ctx)) > 0) {
 
1459
                                close(c->sock);
 
1460
                                c->sock = c->rfd = c->wfd = sock;
 
1461
                                channel_max_fd = channel_find_maxfd();
 
1462
                                return;
 
1463
                        }
 
1464
                        /* Exhausted all addresses */
 
1465
                        error("connect_to %.100s port %d: failed.",
 
1466
                            c->connect_ctx.host, c->connect_ctx.port);
 
1467
                        channel_connect_ctx_free(&c->connect_ctx);
1426
1468
                        if (compat20) {
1427
1469
                                packet_start(SSH2_MSG_CHANNEL_OPEN_FAILURE);
1428
1470
                                packet_put_int(c->remote_id);
1452
1494
        if (c->rfd != -1 && (force || FD_ISSET(c->rfd, readset))) {
1453
1495
                errno = 0;
1454
1496
                len = read(c->rfd, buf, sizeof(buf));
1455
 
                if (len < 0 && (errno == EINTR || (errno == EAGAIN && !force)))
 
1497
                if (len < 0 && (errno == EINTR ||
 
1498
                    ((errno == EAGAIN || errno == EWOULDBLOCK) && !force)))
1456
1499
                        return 1;
1457
1500
#ifndef PTY_ZEROREAD
1458
1501
                if (len <= 0) {
1523
1566
                        c->local_consumed += dlen + 4;
1524
1567
                        len = write(c->wfd, buf, dlen);
1525
1568
                        xfree(data);
1526
 
                        if (len < 0 && (errno == EINTR || errno == EAGAIN))
 
1569
                        if (len < 0 && (errno == EINTR || errno == EAGAIN ||
 
1570
                            errno == EWOULDBLOCK))
1527
1571
                                return 1;
1528
1572
                        if (len <= 0) {
1529
1573
                                if (c->type != SSH_CHANNEL_OPEN)
1541
1585
#endif
1542
1586
 
1543
1587
                len = write(c->wfd, buf, dlen);
1544
 
                if (len < 0 && (errno == EINTR || errno == EAGAIN))
 
1588
                if (len < 0 &&
 
1589
                    (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
1545
1590
                        return 1;
1546
1591
                if (len <= 0) {
1547
1592
                        if (c->type != SSH_CHANNEL_OPEN) {
1593
1638
                            buffer_len(&c->extended));
1594
1639
                        debug2("channel %d: written %d to efd %d",
1595
1640
                            c->self, len, c->efd);
1596
 
                        if (len < 0 && (errno == EINTR || errno == EAGAIN))
 
1641
                        if (len < 0 && (errno == EINTR || errno == EAGAIN ||
 
1642
                            errno == EWOULDBLOCK))
1597
1643
                                return 1;
1598
1644
                        if (len <= 0) {
1599
1645
                                debug2("channel %d: closing write-efd %d",
1608
1654
                        len = read(c->efd, buf, sizeof(buf));
1609
1655
                        debug2("channel %d: read %d from efd %d",
1610
1656
                            c->self, len, c->efd);
1611
 
                        if (len < 0 && (errno == EINTR ||
1612
 
                            (errno == EAGAIN && !c->detach_close)))
 
1657
                        if (len < 0 && (errno == EINTR || ((errno == EAGAIN ||
 
1658
                            errno == EWOULDBLOCK) && !c->detach_close)))
1613
1659
                                return 1;
1614
1660
                        if (len <= 0) {
1615
1661
                                debug2("channel %d: closing read-efd %d",
1633
1679
        /* Monitor control fd to detect if the slave client exits */
1634
1680
        if (c->ctl_fd != -1 && FD_ISSET(c->ctl_fd, readset)) {
1635
1681
                len = read(c->ctl_fd, buf, sizeof(buf));
1636
 
                if (len < 0 && (errno == EINTR || errno == EAGAIN))
 
1682
                if (len < 0 &&
 
1683
                    (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
1637
1684
                        return 1;
1638
1685
                if (len <= 0) {
1639
1686
                        debug2("channel %d: ctl read<=0", c->self);
1657
1704
{
1658
1705
        if (c->type == SSH_CHANNEL_OPEN &&
1659
1706
            !(c->flags & (CHAN_CLOSE_SENT|CHAN_CLOSE_RCVD)) &&
1660
 
            c->local_window < c->local_window_max/2 &&
 
1707
            ((c->local_window_max - c->local_window >
 
1708
            c->local_maxpacket*3) ||
 
1709
            c->local_window < c->local_window_max/2) &&
1661
1710
            c->local_consumed > 0) {
1662
1711
                packet_start(SSH2_MSG_CHANNEL_WINDOW_ADJUST);
1663
1712
                packet_put_int(c->remote_id);
2010
2059
                return;
2011
2060
 
2012
2061
        /* Get the data. */
2013
 
        data = packet_get_string(&data_len);
 
2062
        data = packet_get_string_ptr(&data_len);
2014
2063
 
2015
2064
        /*
2016
2065
         * Ignore data for protocol > 1.3 if output end is no longer open.
2024
2073
                        c->local_window -= data_len;
2025
2074
                        c->local_consumed += data_len;
2026
2075
                }
2027
 
                xfree(data);
2028
2076
                return;
2029
2077
        }
2030
2078
 
2036
2084
                if (data_len > c->local_window) {
2037
2085
                        logit("channel %d: rcvd too much data %d, win %d",
2038
2086
                            c->self, data_len, c->local_window);
2039
 
                        xfree(data);
2040
2087
                        return;
2041
2088
                }
2042
2089
                c->local_window -= data_len;
2043
2090
        }
2044
 
        packet_check_eom();
2045
2091
        if (c->datagram)
2046
2092
                buffer_put_string(&c->output, data, data_len);
2047
2093
        else
2048
2094
                buffer_append(&c->output, data, data_len);
2049
 
        xfree(data);
 
2095
        packet_check_eom();
2050
2096
}
2051
2097
 
2052
2098
/* ARGSUSED */
2210
2256
        if (compat20) {
2211
2257
                c->remote_window = packet_get_int();
2212
2258
                c->remote_maxpacket = packet_get_int();
2213
 
                if (c->confirm) {
 
2259
                if (c->open_confirm) {
2214
2260
                        debug2("callback start");
2215
 
                        c->confirm(c->self, c->confirm_ctx);
 
2261
                        c->open_confirm(c->self, c->open_confirm_ctx);
2216
2262
                        debug2("callback done");
2217
2263
                }
2218
2264
                debug2("channel %d: open confirm rwindow %u rmax %u", c->self,
2301
2347
        Channel *c = NULL;
2302
2348
        u_short host_port;
2303
2349
        char *host, *originator_string;
2304
 
        int remote_id, sock = -1;
 
2350
        int remote_id;
2305
2351
 
2306
2352
        remote_id = packet_get_int();
2307
2353
        host = packet_get_string(NULL);
2313
2359
                originator_string = xstrdup("unknown (remote did not supply name)");
2314
2360
        }
2315
2361
        packet_check_eom();
2316
 
        sock = channel_connect_to(host, host_port);
2317
 
        if (sock != -1) {
2318
 
                c = channel_new("connected socket",
2319
 
                    SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0,
2320
 
                    originator_string, 1);
2321
 
                c->remote_id = remote_id;
2322
 
        }
 
2362
        c = channel_connect_to(host, host_port,
 
2363
            "connected socket", originator_string);
2323
2364
        xfree(originator_string);
2324
 
        if (c == NULL) {
2325
 
                packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
2326
 
                packet_put_int(remote_id);
2327
 
                packet_send();
2328
 
        }
2329
2365
        xfree(host);
2330
 
}
2331
 
 
 
2366
        if (c == NULL) {
 
2367
                packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE);
 
2368
                packet_put_int(remote_id);
 
2369
                packet_send();
 
2370
        } else
 
2371
                c->remote_id = remote_id;
 
2372
}
 
2373
 
 
2374
/* ARGSUSED */
 
2375
void
 
2376
channel_input_status_confirm(int type, u_int32_t seq, void *ctxt)
 
2377
{
 
2378
        Channel *c;
 
2379
        struct channel_confirm *cc;
 
2380
        int remote_id;
 
2381
 
 
2382
        /* Reset keepalive timeout */
 
2383
        keep_alive_timeouts = 0;
 
2384
 
 
2385
        remote_id = packet_get_int();
 
2386
        packet_check_eom();
 
2387
 
 
2388
        debug2("channel_input_confirm: type %d id %d", type, remote_id);
 
2389
 
 
2390
        if ((c = channel_lookup(remote_id)) == NULL) {
 
2391
                logit("channel_input_success_failure: %d: unknown", remote_id);
 
2392
                return;
 
2393
        }       
 
2394
        ;
 
2395
        if ((cc = TAILQ_FIRST(&c->status_confirms)) == NULL)
 
2396
                return;
 
2397
        cc->cb(type, c, cc->ctx);
 
2398
        TAILQ_REMOVE(&c->status_confirms, cc, entry);
 
2399
        bzero(cc, sizeof(*cc));
 
2400
        xfree(cc);
 
2401
}
2332
2402
 
2333
2403
/* -- tcp forwarding */
2334
2404
 
2383
2453
                        wildcard = 1;
2384
2454
        } else if (gateway_ports || is_client) {
2385
2455
                if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2386
 
                    strcmp(listen_addr, "0.0.0.0") == 0) ||
 
2456
                    strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
2387
2457
                    *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
2388
2458
                    (!is_client && gateway_ports == 1))
2389
2459
                        wildcard = 1;
2407
2477
                if (addr == NULL) {
2408
2478
                        /* This really shouldn't happen */
2409
2479
                        packet_disconnect("getaddrinfo: fatal error: %s",
2410
 
                            gai_strerror(r));
 
2480
                            ssh_gai_strerror(r));
2411
2481
                } else {
2412
2482
                        error("channel_setup_fwd_listener: "
2413
 
                            "getaddrinfo(%.64s): %s", addr, gai_strerror(r));
 
2483
                            "getaddrinfo(%.64s): %s", addr,
 
2484
                            ssh_gai_strerror(r));
2414
2485
                }
2415
2486
                return 0;
2416
2487
        }
2715
2786
        num_adm_permitted_opens = 0;
2716
2787
}
2717
2788
 
2718
 
/* return socket to remote host, port */
 
2789
void
 
2790
channel_print_adm_permitted_opens(void)
 
2791
{
 
2792
        int i;
 
2793
 
 
2794
        for (i = 0; i < num_adm_permitted_opens; i++)
 
2795
                if (permitted_adm_opens[i].host_to_connect != NULL)
 
2796
                        printf(" %s:%d", permitted_adm_opens[i].host_to_connect,
 
2797
                            permitted_adm_opens[i].port_to_connect);
 
2798
}
 
2799
 
 
2800
/* Try to start non-blocking connect to next host in cctx list */
2719
2801
static int
2720
 
connect_to(const char *host, u_short port)
 
2802
connect_next(struct channel_connect *cctx)
2721
2803
{
2722
 
        struct addrinfo hints, *ai, *aitop;
 
2804
        int sock, saved_errno;
2723
2805
        char ntop[NI_MAXHOST], strport[NI_MAXSERV];
2724
 
        int gaierr;
2725
 
        int sock = -1;
2726
2806
 
2727
 
        memset(&hints, 0, sizeof(hints));
2728
 
        hints.ai_family = IPv4or6;
2729
 
        hints.ai_socktype = SOCK_STREAM;
2730
 
        snprintf(strport, sizeof strport, "%d", port);
2731
 
        if ((gaierr = getaddrinfo(host, strport, &hints, &aitop)) != 0) {
2732
 
                error("connect_to %.100s: unknown host (%s)", host,
2733
 
                    gai_strerror(gaierr));
2734
 
                return -1;
2735
 
        }
2736
 
        for (ai = aitop; ai; ai = ai->ai_next) {
2737
 
                if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
 
2807
        for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
 
2808
                if (cctx->ai->ai_family != AF_INET &&
 
2809
                    cctx->ai->ai_family != AF_INET6)
2738
2810
                        continue;
2739
 
                if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2740
 
                    strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2741
 
                        error("connect_to: getnameinfo failed");
 
2811
                if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
 
2812
                    ntop, sizeof(ntop), strport, sizeof(strport),
 
2813
                    NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
 
2814
                        error("connect_next: getnameinfo failed");
2742
2815
                        continue;
2743
2816
                }
2744
 
                sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
2745
 
                if (sock < 0) {
2746
 
                        if (ai->ai_next == NULL)
 
2817
                if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
 
2818
                    cctx->ai->ai_protocol)) == -1) {
 
2819
                        if (cctx->ai->ai_next == NULL)
2747
2820
                                error("socket: %.100s", strerror(errno));
2748
2821
                        else
2749
2822
                                verbose("socket: %.100s", strerror(errno));
2751
2824
                }
2752
2825
                if (set_nonblock(sock) == -1)
2753
2826
                        fatal("%s: set_nonblock(%d)", __func__, sock);
2754
 
                if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0 &&
2755
 
                    errno != EINPROGRESS) {
2756
 
                        error("connect_to %.100s port %s: %.100s", ntop, strport,
 
2827
                if (connect(sock, cctx->ai->ai_addr,
 
2828
                    cctx->ai->ai_addrlen) == -1 && errno != EINPROGRESS) {
 
2829
                        debug("connect_next: host %.100s ([%.100s]:%s): "
 
2830
                            "%.100s", cctx->host, ntop, strport,
2757
2831
                            strerror(errno));
 
2832
                        saved_errno = errno;
2758
2833
                        close(sock);
 
2834
                        errno = saved_errno;
2759
2835
                        continue;       /* fail -- try next */
2760
2836
                }
2761
 
                break; /* success */
2762
 
 
2763
 
        }
2764
 
        freeaddrinfo(aitop);
2765
 
        if (!ai) {
2766
 
                error("connect_to %.100s port %d: failed.", host, port);
2767
 
                return -1;
2768
 
        }
2769
 
        /* success */
2770
 
        set_nodelay(sock);
2771
 
        return sock;
2772
 
}
2773
 
 
2774
 
int
2775
 
channel_connect_by_listen_address(u_short listen_port)
 
2837
                debug("connect_next: host %.100s ([%.100s]:%s) "
 
2838
                    "in progress, fd=%d", cctx->host, ntop, strport, sock);
 
2839
                cctx->ai = cctx->ai->ai_next;
 
2840
                set_nodelay(sock);
 
2841
                return sock;
 
2842
        }
 
2843
        return -1;
 
2844
}
 
2845
 
 
2846
static void
 
2847
channel_connect_ctx_free(struct channel_connect *cctx)
 
2848
{
 
2849
        xfree(cctx->host);
 
2850
        if (cctx->aitop)
 
2851
                freeaddrinfo(cctx->aitop);
 
2852
        bzero(cctx, sizeof(*cctx));
 
2853
        cctx->host = NULL;
 
2854
        cctx->ai = cctx->aitop = NULL;
 
2855
}
 
2856
 
 
2857
/* Return CONNECTING channel to remote host, port */
 
2858
static Channel *
 
2859
connect_to(const char *host, u_short port, char *ctype, char *rname)
 
2860
{
 
2861
        struct addrinfo hints;
 
2862
        int gaierr;
 
2863
        int sock = -1;
 
2864
        char strport[NI_MAXSERV];
 
2865
        struct channel_connect cctx;
 
2866
        Channel *c;
 
2867
 
 
2868
        memset(&cctx, 0, sizeof(cctx));
 
2869
        memset(&hints, 0, sizeof(hints));
 
2870
        hints.ai_family = IPv4or6;
 
2871
        hints.ai_socktype = SOCK_STREAM;
 
2872
        snprintf(strport, sizeof strport, "%d", port);
 
2873
        if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) {
 
2874
                error("connect_to %.100s: unknown host (%s)", host,
 
2875
                    ssh_gai_strerror(gaierr));
 
2876
                return NULL;
 
2877
        }
 
2878
 
 
2879
        cctx.host = xstrdup(host);
 
2880
        cctx.port = port;
 
2881
        cctx.ai = cctx.aitop;
 
2882
 
 
2883
        if ((sock = connect_next(&cctx)) == -1) {
 
2884
                error("connect to %.100s port %d failed: %s",
 
2885
                    host, port, strerror(errno));
 
2886
                channel_connect_ctx_free(&cctx);
 
2887
                return NULL;
 
2888
        }
 
2889
        c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1,
 
2890
            CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, rname, 1);
 
2891
        c->connect_ctx = cctx;
 
2892
        return c;
 
2893
}
 
2894
 
 
2895
Channel *
 
2896
channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname)
2776
2897
{
2777
2898
        int i;
2778
2899
 
2779
 
        for (i = 0; i < num_permitted_opens; i++)
 
2900
        for (i = 0; i < num_permitted_opens; i++) {
2780
2901
                if (permitted_opens[i].host_to_connect != NULL &&
2781
 
                    permitted_opens[i].listen_port == listen_port)
 
2902
                    permitted_opens[i].listen_port == listen_port) {
2782
2903
                        return connect_to(
2783
2904
                            permitted_opens[i].host_to_connect,
2784
 
                            permitted_opens[i].port_to_connect);
 
2905
                            permitted_opens[i].port_to_connect, ctype, rname);
 
2906
                }
 
2907
        }
2785
2908
        error("WARNING: Server requests forwarding for unknown listen_port %d",
2786
2909
            listen_port);
2787
 
        return -1;
 
2910
        return NULL;
2788
2911
}
2789
2912
 
2790
2913
/* Check if connecting to that port is permitted and connect. */
2791
 
int
2792
 
channel_connect_to(const char *host, u_short port)
 
2914
Channel *
 
2915
channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
2793
2916
{
2794
2917
        int i, permit, permit_adm = 1;
2795
2918
 
2815
2938
        if (!permit || !permit_adm) {
2816
2939
                logit("Received request to connect to host %.100s port %d, "
2817
2940
                    "but the request was denied.", host, port);
2818
 
                return -1;
 
2941
                return NULL;
2819
2942
        }
2820
 
        return connect_to(host, port);
 
2943
        return connect_to(host, port, ctype, rname);
2821
2944
}
2822
2945
 
2823
2946
void
2872
2995
                hints.ai_socktype = SOCK_STREAM;
2873
2996
                snprintf(strport, sizeof strport, "%d", port);
2874
2997
                if ((gaierr = getaddrinfo(NULL, strport, &hints, &aitop)) != 0) {
2875
 
                        error("getaddrinfo: %.100s", gai_strerror(gaierr));
 
2998
                        error("getaddrinfo: %.100s", ssh_gai_strerror(gaierr));
2876
2999
                        return -1;
2877
3000
                }
2878
3001
                for (ai = aitop; ai; ai = ai->ai_next) {
2902
3025
                                        error("setsockopt IPV6_V6ONLY: %.100s", strerror(errno));
2903
3026
                        }
2904
3027
#endif
2905
 
                        channel_set_reuseaddr(sock);
 
3028
                        if (x11_use_localhost)
 
3029
                                channel_set_reuseaddr(sock);
2906
3030
                        if (bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) {
2907
3031
                                debug2("bind port %d: %.100s", port, strerror(errno));
2908
3032
                                close(sock);
2909
3033
 
2910
 
                                if (ai->ai_next)
2911
 
                                        continue;
2912
 
 
2913
3034
                                for (n = 0; n < num_socks; n++) {
2914
3035
                                        close(socks[n]);
2915
3036
                                }
2917
3038
                                break;
2918
3039
                        }
2919
3040
                        socks[num_socks++] = sock;
2920
 
#ifndef DONT_TRY_OTHER_AF
2921
3041
                        if (num_socks == NUM_SOCKS)
2922
3042
                                break;
2923
 
#else
2924
 
                        if (x11_use_localhost) {
2925
 
                                if (num_socks == NUM_SOCKS)
2926
 
                                        break;
2927
 
                        } else {
2928
 
                                break;
2929
 
                        }
2930
 
#endif
2931
3043
                }
2932
3044
                freeaddrinfo(aitop);
2933
3045
                if (num_socks > 0)
3049
3161
        hints.ai_socktype = SOCK_STREAM;
3050
3162
        snprintf(strport, sizeof strport, "%u", 6000 + display_number);
3051
3163
        if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) {
3052
 
                error("%.100s: unknown host. (%s)", buf, gai_strerror(gaierr));
 
3164
                error("%.100s: unknown host. (%s)", buf,
 
3165
                ssh_gai_strerror(gaierr));
3053
3166
                return -1;
3054
3167
        }
3055
3168
        for (ai = aitop; ai; ai = ai->ai_next) {