From 99c73b377a45d3e008e73cca9073dc006e1cfaae Mon Sep 17 00:00:00 2001 From: Ben Lindstrom Date: Sat, 5 May 2001 04:09:47 +0000 Subject: [PATCH] - markus@cvs.openbsd.org 2001/05/04 23:47:34 [channels.c channels.h clientloop.c nchan.c nchan.h serverloop.c ssh.c] move to Channel **channels (instead of Channel *channels), fixes realloc problems. channel_new now returns a Channel *, favour Channel * over channel id. remove old channel_allocate interface. --- ChangeLog | 7 +- channels.c | 365 ++++++++++++++++++++++++++++----------------------- channels.h | 22 ++-- clientloop.c | 60 +++++---- nchan.c | 10 +- nchan.h | 4 +- serverloop.c | 40 +++--- ssh.c | 18 +-- 8 files changed, 297 insertions(+), 229 deletions(-) diff --git a/ChangeLog b/ChangeLog index 559347b09..e665f1204 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,11 @@ [channels.c] channel_new() reallocs channels[], we cannot use Channel *c after calling channel_new(), XXX fix this in the future... + - markus@cvs.openbsd.org 2001/05/04 23:47:34 + [channels.c channels.h clientloop.c nchan.c nchan.h serverloop.c ssh.c] + move to Channel **channels (instead of Channel *channels), fixes realloc + problems. channel_new now returns a Channel *, favour Channel * over + channel id. remove old channel_allocate interface. 20010504 - OpenBSD CVS Sync @@ -5337,4 +5342,4 @@ - Wrote replacements for strlcpy and mkdtemp - Released 1.0pre1 -$Id: ChangeLog,v 1.1198 2001/05/04 22:40:28 mouring Exp $ +$Id: ChangeLog,v 1.1199 2001/05/05 04:09:47 mouring Exp $ diff --git a/channels.c b/channels.c index 503a81450..2bb0e9851 100644 --- a/channels.c +++ b/channels.c @@ -40,7 +40,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: channels.c,v 1.112 2001/05/04 14:34:34 markus Exp $"); +RCSID("$OpenBSD: channels.c,v 1.113 2001/05/04 23:47:33 markus Exp $"); #include #include @@ -72,18 +72,17 @@ RCSID("$OpenBSD: channels.c,v 1.112 2001/05/04 14:34:34 markus Exp $"); * Pointer to an array containing all allocated channels. The array is * dynamically extended as needed. */ -static Channel *channels = NULL; +static Channel **channels = NULL; /* * Size of the channel array. All slots of the array must always be - * initialized (at least the type field); unused slots are marked with type - * SSH_CHANNEL_FREE. + * initialized (at least the type field); unused slots set to NULL */ static int channels_alloc = 0; /* * Maximum file descriptor value used in any of the channels. This is - * updated in channel_allocate. + * updated in channel_new. */ static int channel_max_fd = 0; @@ -150,12 +149,13 @@ Channel * channel_lookup(int id) { Channel *c; + if (id < 0 || id > channels_alloc) { log("channel_lookup: %d: bad id", id); return NULL; } - c = &channels[id]; - if (c->type == SSH_CHANNEL_FREE) { + c = channels[id]; + if (c == NULL) { log("channel_lookup: %d: bad id: channel free", id); return NULL; } @@ -212,7 +212,7 @@ channel_register_fds(Channel *c, int rfd, int wfd, int efd, * remote_name to be freed. */ -int +Channel * channel_new(char *ctype, int type, int rfd, int wfd, int efd, int window, int maxpack, int extusage, char *remote_name, int nonblock) { @@ -223,9 +223,9 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, if (channels_alloc == 0) { chan_init(); channels_alloc = 10; - channels = xmalloc(channels_alloc * sizeof(Channel)); + channels = xmalloc(channels_alloc * sizeof(Channel *)); for (i = 0; i < channels_alloc; i++) - channels[i].type = SSH_CHANNEL_FREE; + channels[i] = NULL; /* * Kludge: arrange a call to channel_stop_listening if we * terminate with fatal(). @@ -234,7 +234,7 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, } /* Try to find a free slot where to put the new channel. */ for (found = -1, i = 0; i < channels_alloc; i++) - if (channels[i].type == SSH_CHANNEL_FREE) { + if (channels[i] == NULL) { /* Found a free slot. */ found = i; break; @@ -244,12 +244,12 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, found = channels_alloc; channels_alloc += 10; debug2("channel: expanding %d", channels_alloc); - channels = xrealloc(channels, channels_alloc * sizeof(Channel)); + channels = xrealloc(channels, channels_alloc * sizeof(Channel *)); for (i = found; i < channels_alloc; i++) - channels[i].type = SSH_CHANNEL_FREE; + channels[i] = NULL; } - /* Initialize and return new channel number. */ - c = &channels[found]; + /* Initialize and return new channel. */ + c = channels[found] = xmalloc(sizeof(Channel)); buffer_init(&c->input); buffer_init(&c->output); buffer_init(&c->extended); @@ -272,15 +272,8 @@ channel_new(char *ctype, int type, int rfd, int wfd, int efd, c->dettach_user = NULL; c->input_filter = NULL; debug("channel %d: new [%s]", found, remote_name); - return found; + return c; } -/* old interface XXX */ -int -channel_allocate(int type, int sock, char *remote_name) -{ - return channel_new("", type, sock, sock, -1, 0, 0, 0, remote_name, 1); -} - /* Close all channel fd/socket. */ @@ -308,18 +301,16 @@ channel_close_fds(Channel *c) /* Free the channel and close its fd/socket. */ void -channel_free(int id) +channel_free(Channel *c) { - Channel *c = channel_lookup(id); - char *s = channel_open_message(); + char *s; - if (c == NULL) - packet_disconnect("channel free: bad local channel %d", id); - debug("channel_free: channel %d: status: %s", id, s); + s = channel_open_message(); + debug("channel_free: channel %d: status: %s", c->self, s); xfree(s); if (c->dettach_user != NULL) { - debug("channel_free: channel %d: dettaching channel user", id); + debug("channel_free: channel %d: dettaching channel user", c->self); c->dettach_user(c->self, NULL); } if (c->sock != -1) @@ -328,11 +319,12 @@ channel_free(int id) buffer_free(&c->input); buffer_free(&c->output); buffer_free(&c->extended); - c->type = SSH_CHANNEL_FREE; if (c->remote_name) { xfree(c->remote_name); c->remote_name = NULL; } + channels[c->self] = NULL; + xfree(c); } /* @@ -428,7 +420,7 @@ void channel_pre_output_draining(Channel *c, fd_set * readset, fd_set * writeset) { if (buffer_len(&c->output) == 0) - channel_free(c->self); + chan_mark_dead(c); else FD_SET(c->sock, writeset); } @@ -640,7 +632,7 @@ channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset) break; } if (ret < 0) { - channel_free(c->self); + chan_mark_dead(c); } else if (ret == 0) { debug2("channel %d: pre_dynamic: need more", c->self); /* need more */ @@ -656,8 +648,9 @@ channel_pre_dynamic(Channel *c, fd_set * readset, fd_set * writeset) void channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) { + Channel *nc; struct sockaddr addr; - int newsock, newch, oldch; + int newsock; socklen_t addrlen; char buf[16384], *remote_ipaddr; int remote_port; @@ -675,16 +668,19 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) snprintf(buf, sizeof buf, "X11 connection from %.200s port %d", remote_ipaddr, remote_port); - oldch = c->self; - newch = channel_new("x11", + nc = channel_new("accepted x11 socket", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, xstrdup(buf), 1); - c = channel_lookup(oldch); + if (nc == NULL) { + close(newsock); + xfree(remote_ipaddr); + return; + } if (compat20) { packet_start(SSH2_MSG_CHANNEL_OPEN); packet_put_cstring("x11"); - packet_put_int(newch); + packet_put_int(nc->self); packet_put_int(c->local_window_max); packet_put_int(c->local_maxpacket); /* originator ipaddr and port */ @@ -697,7 +693,7 @@ channel_post_x11_listener(Channel *c, fd_set * readset, fd_set * writeset) packet_send(); } else { packet_start(SSH_SMSG_X11_OPEN); - packet_put_int(newch); + packet_put_int(nc->self); if (have_hostname_in_open) packet_put_string(buf, strlen(buf)); packet_send(); @@ -764,7 +760,7 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) { Channel *nc; struct sockaddr addr; - int newsock, newch, nextstate, oldch; + int newsock, nextstate; socklen_t addrlen; char *rtype; @@ -784,16 +780,13 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) error("accept: %.100s", strerror(errno)); return; } - oldch = c->self; - newch = channel_new(rtype, + nc = channel_new(rtype, nextstate, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, xstrdup(rtype), 1); - - c = channel_lookup(oldch); - nc = channel_lookup(newch); if (nc == NULL) { - error("xxx: no new channel:"); + error("channel_post_port_listener: no new channel:"); + close(newsock); return; } nc->listening_port = c->listening_port; @@ -812,8 +805,9 @@ channel_post_port_listener(Channel *c, fd_set * readset, fd_set * writeset) void channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) { + Channel *nc; + int newsock; struct sockaddr addr; - int newsock, newch, oldch; socklen_t addrlen; if (FD_ISSET(c->sock, readset)) { @@ -823,21 +817,23 @@ channel_post_auth_listener(Channel *c, fd_set * readset, fd_set * writeset) error("accept from auth socket: %.100s", strerror(errno)); return; } - oldch = c->self; - newch = channel_new("accepted auth socket", + nc = channel_new("accepted auth socket", SSH_CHANNEL_OPENING, newsock, newsock, -1, c->local_window_max, c->local_maxpacket, 0, xstrdup("accepted auth socket"), 1); - c = channel_lookup(oldch); + if (nc == NULL) { + error("channel_post_auth_listener: channel_new failed"); + close(newsock); + } if (compat20) { packet_start(SSH2_MSG_CHANNEL_OPEN); packet_put_cstring("auth-agent@openssh.com"); - packet_put_int(newch); + packet_put_int(nc->self); packet_put_int(c->local_window_max); packet_put_int(c->local_maxpacket); } else { packet_start(SSH_SMSG_AGENT_OPEN); - packet_put_int(newch); + packet_put_int(nc->self); } packet_send(); } @@ -881,7 +877,7 @@ channel_handle_rfd(Channel *c, fd_set * readset, fd_set * writeset) c->self, c->rfd, len); if (c->type != SSH_CHANNEL_OPEN) { debug("channel %d: not open", c->self); - channel_free(c->self); + chan_mark_dead(c); return -1; } else if (compat13) { buffer_consume(&c->output, buffer_len(&c->output)); @@ -920,7 +916,7 @@ channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) if (len <= 0) { if (c->type != SSH_CHANNEL_OPEN) { debug("channel %d: not open", c->self); - channel_free(c->self); + chan_mark_dead(c); return -1; } else if (compat13) { buffer_consume(&c->output, buffer_len(&c->output)); @@ -1138,13 +1134,12 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) did_init = 1; } for (i = 0; i < channels_alloc; i++) { - c = &channels[i]; - if (c->type == SSH_CHANNEL_FREE) + c = channels[i]; + if (c == NULL) continue; if (ftab[c->type] == NULL) continue; (*ftab[c->type])(c, readset, writeset); - c = &channels[i]; /* XXX realloc */ if (chan_is_dead(c)) { /* * we have to remove the fd's from the select mask @@ -1161,7 +1156,7 @@ channel_handler(chan_fn *ftab[], fd_set * readset, fd_set * writeset) if (c->extended_usage == CHAN_EXTENDED_WRITE) FD_CLR(c->efd, writeset); } - channel_free(c->self); + channel_free(c); } } } @@ -1207,7 +1202,10 @@ channel_output_poll() Channel *c; for (i = 0; i < channels_alloc; i++) { - c = &channels[i]; + + c = channels[i]; + if (c == NULL) + continue; /* We are only interested in channels that can have buffered incoming data. */ if (compat13) { @@ -1391,8 +1389,8 @@ channel_not_very_much_buffered_data() Channel *c; for (i = 0; i < channels_alloc; i++) { - c = &channels[i]; - if (c->type == SSH_CHANNEL_OPEN) { + c = channels[i]; + if (c != NULL && c->type == SSH_CHANNEL_OPEN) { if (!compat20 && buffer_len(&c->input) > packet_get_maxsize()) { debug("channel %d: big input buffer %d", c->self, buffer_len(&c->input)); @@ -1486,7 +1484,7 @@ channel_input_close_confirmation(int type, int plen, void *ctxt) if (c->type != SSH_CHANNEL_CLOSED) packet_disconnect("Received close confirmation for " "non-closed channel %d (type %d).", id, c->type); - channel_free(c->self); + channel_free(c); } void @@ -1554,7 +1552,7 @@ channel_input_open_failure(int type, int plen, void *ctxt) xfree(lang); } /* Free the channel. This will also close the socket. */ - channel_free(id); + channel_free(c); } void @@ -1615,21 +1613,26 @@ void channel_stop_listening() { int i; + Channel *c; + for (i = 0; i < channels_alloc; i++) { - switch (channels[i].type) { - case SSH_CHANNEL_AUTH_SOCKET: - close(channels[i].sock); - unlink(channels[i].path); - channel_free(i); - break; - case SSH_CHANNEL_PORT_LISTENER: - case SSH_CHANNEL_RPORT_LISTENER: - case SSH_CHANNEL_X11_LISTENER: - close(channels[i].sock); - channel_free(i); - break; - default: - break; + c = channels[i]; + if (c != NULL) { + switch (c->type) { + case SSH_CHANNEL_AUTH_SOCKET: + close(c->sock); + unlink(c->path); + channel_free(c); + break; + case SSH_CHANNEL_PORT_LISTENER: + case SSH_CHANNEL_RPORT_LISTENER: + case SSH_CHANNEL_X11_LISTENER: + close(c->sock); + channel_free(c); + break; + default: + break; + } } } } @@ -1643,9 +1646,10 @@ void channel_close_all() { int i; + for (i = 0; i < channels_alloc; i++) - if (channels[i].type != SSH_CHANNEL_FREE) - channel_close_fds(&channels[i]); + if (channels[i] != NULL) + channel_close_fds(channels[i]); } /* Returns true if any channel is still open. */ @@ -1653,10 +1657,14 @@ channel_close_all() int channel_still_open() { - u_int i; - for (i = 0; i < channels_alloc; i++) - switch (channels[i].type) { - case SSH_CHANNEL_FREE: + int i; + Channel *c; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; + if (c == NULL) + continue; + switch (c->type) { case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: @@ -1679,9 +1687,10 @@ channel_still_open() fatal("cannot happen: OUT_DRAIN"); return 1; default: - fatal("channel_still_open: bad channel type %d", channels[i].type); + fatal("channel_still_open: bad channel type %d", c->type); /* NOTREACHED */ } + } return 0; } @@ -1690,12 +1699,16 @@ channel_still_open() int channel_find_open() { - u_int i; - for (i = 0; i < channels_alloc; i++) - switch (channels[i].type) { + int i; + Channel *c; + + for (i = 0; i < channels_alloc; i++) { + c = channels[i]; + if (c == NULL) + continue; + switch (c->type) { case SSH_CHANNEL_CLOSED: case SSH_CHANNEL_DYNAMIC: - case SSH_CHANNEL_FREE: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: @@ -1713,9 +1726,10 @@ channel_find_open() fatal("cannot happen: OUT_DRAIN"); return i; default: - fatal("channel_find_open: bad channel type %d", channels[i].type); + fatal("channel_find_open: bad channel type %d", c->type); /* NOTREACHED */ } + } return -1; } @@ -1730,16 +1744,18 @@ char * channel_open_message() { Buffer buffer; + Channel *c; + char buf[1024], *cp; int i; - char buf[512], *cp; buffer_init(&buffer); snprintf(buf, sizeof buf, "The following connections are open:\r\n"); buffer_append(&buffer, buf, strlen(buf)); for (i = 0; i < channels_alloc; i++) { - Channel *c = &channels[i]; + c = channels[i]; + if (c == NULL) + continue; switch (c->type) { - case SSH_CHANNEL_FREE: case SSH_CHANNEL_X11_LISTENER: case SSH_CHANNEL_PORT_LISTENER: case SSH_CHANNEL_RPORT_LISTENER: @@ -1797,7 +1813,8 @@ channel_request_forwarding( const char *host_to_connect, u_short port_to_connect, int gateway_ports, int remote_fwd) { - int success, ch, sock, on = 1, ctype; + Channel *c; + int success, sock, on = 1, ctype; struct addrinfo hints, *ai, *aitop; char ntop[NI_MAXHOST], strport[NI_MAXSERV]; const char *host; @@ -1813,7 +1830,7 @@ channel_request_forwarding( ctype =SSH_CHANNEL_PORT_LISTENER; } - if (strlen(host) > sizeof(channels[0].path) - 1) { + if (strlen(host) > SSH_CHANNEL_PATH_LEN - 1) { error("Forward host name too long."); return success; } @@ -1874,12 +1891,17 @@ channel_request_forwarding( continue; } /* Allocate a channel number for the socket. */ - ch = channel_new("port listener", ctype, sock, sock, -1, + c = channel_new("port listener", ctype, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("port listener"), 1); - strlcpy(channels[ch].path, host, sizeof(channels[ch].path)); - channels[ch].host_port = port_to_connect; - channels[ch].listening_port = listen_port; + if (c == NULL) { + error("channel_request_forwarding: channel_new failed"); + close(sock); + continue; + } + strlcpy(c->path, host, sizeof(c->path)); + c->host_port = port_to_connect; + c->listening_port = listen_port; success = 1; } if (success == 0) @@ -2116,11 +2138,12 @@ channel_connect_to(const char *host, u_short port) void channel_input_port_open(int type, int plen, void *ctxt) { + Channel *c = NULL; u_short host_port; char *host, *originator_string; - int remote_channel, sock = -1, newch; + int remote_id, sock = -1; - remote_channel = packet_get_int(); + remote_id = packet_get_int(); host = packet_get_string(NULL); host_port = packet_get_int(); @@ -2132,20 +2155,26 @@ channel_input_port_open(int type, int plen, void *ctxt) packet_done(); sock = channel_connect_to(host, host_port); if (sock != -1) { - newch = channel_allocate(SSH_CHANNEL_CONNECTING, - sock, originator_string); - channels[newch].remote_id = remote_channel; - + c = channel_new("connected socket", + SSH_CHANNEL_CONNECTING, sock, sock, -1, 0, 0, 0, + originator_string, 1); + if (c == NULL) { + error("channel_input_port_open: channel_new failed"); + close(sock); + } else { + c->remote_id = remote_id; + } + } + if (c == NULL) { + packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); + packet_put_int(remote_id); + } else { /*XXX delay answer? */ packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remote_channel); - packet_put_int(newch); - packet_send(); - } else { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_channel); - packet_send(); + packet_put_int(remote_id); + packet_put_int(c->self); } + packet_send(); xfree(host); } @@ -2430,46 +2459,45 @@ x11_connect_display(void) void x11_input_open(int type, int plen, void *ctxt) { - int remote_channel, sock = 0, newch; + Channel *c = NULL; + int remote_id, sock = 0; char *remote_host; - u_int remote_len; - - /* Get remote channel number. */ - remote_channel = packet_get_int(); - - /* Get remote originator name. */ - if (have_hostname_in_open) { - remote_host = packet_get_string(&remote_len); - remote_len += 4; - } else { - remote_host = xstrdup("unknown (remote did not supply name)"); - remote_len = 0; - } debug("Received X11 open request."); - packet_integrity_check(plen, 4 + remote_len, SSH_SMSG_X11_OPEN); + + remote_id = packet_get_int(); + if (have_hostname_in_open) { + remote_host = packet_get_string(NULL); + } else { + remote_host = xstrdup("unknown (remote did not supply name)"); + } + packet_done(); /* Obtain a connection to the real X display. */ sock = x11_connect_display(); - if (sock == -1) { + if (sock != -1) { + /* Allocate a channel for this connection. */ + c = channel_new("connected x11 socket", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, 0, 0, 0, + remote_host, 1); + if (c == NULL) { + error("x11_input_open: channel_new failed"); + close(sock); + } else { + c->remote_id = remote_id; + } + } + if (c == NULL) { /* Send refusal to the remote host. */ packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remote_channel); - packet_send(); + packet_put_int(remote_id); } else { - /* Allocate a channel for this connection. */ - newch = channel_allocate( - (x11_saved_proto == NULL) ? - SSH_CHANNEL_OPEN : SSH_CHANNEL_X11_OPEN, - sock, remote_host); - channels[newch].remote_id = remote_channel; - /* Send a confirmation to the remote host. */ packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remote_channel); - packet_put_int(newch); - packet_send(); + packet_put_int(remote_id); + packet_put_int(c->self); } + packet_send(); } /* dummy protocol handler that denies SSH-1 requests (agent/x11) */ @@ -2602,7 +2630,8 @@ cleanup_socket(void) int auth_input_request_forwarding(struct passwd * pw) { - int sock, newch; + Channel *nc; + int sock; struct sockaddr_un sunaddr; if (auth_get_socket_name() != NULL) @@ -2657,13 +2686,16 @@ auth_input_request_forwarding(struct passwd * pw) packet_disconnect("listen: %.100s", strerror(errno)); /* Allocate a channel for the authentication agent socket. */ - newch = channel_new("auth socket", + nc = channel_new("auth socket", SSH_CHANNEL_AUTH_SOCKET, sock, sock, -1, CHAN_X11_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, xstrdup("auth socket"), 1); - - strlcpy(channels[newch].path, channel_forwarded_auth_socket_name, - sizeof(channels[newch].path)); + if (nc == NULL) { + error("auth_input_request_forwarding: channel_new failed"); + close(sock); + return 0; + } + strlcpy(nc->path, channel_forwarded_auth_socket_name, sizeof(nc->path)); return 1; } @@ -2672,13 +2704,14 @@ auth_input_request_forwarding(struct passwd * pw) void auth_input_open_request(int type, int plen, void *ctxt) { - int remch, sock, newch; + Channel *c = NULL; + int remote_id, sock; char *dummyname; packet_integrity_check(plen, 4, type); /* Read the remote channel number from the message. */ - remch = packet_get_int(); + remote_id = packet_get_int(); /* * Get a connection to the local authentication agent (this may again @@ -2692,28 +2725,26 @@ auth_input_open_request(int type, int plen, void *ctxt) * because authentication forwarding is only enabled if we have an * agent. */ - if (sock < 0) { - packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); - packet_put_int(remch); - packet_send(); - return; + if (sock >= 0) { + dummyname = xstrdup("authentication agent connection"); + c = channel_new("", SSH_CHANNEL_OPEN, sock, sock, -1, 0, 0, 0, dummyname, 1); + if (c == NULL) { + error("auth_input_open_request: channel_new failed"); + close(sock); + } else { + c->remote_id = remote_id; + } + } + if (c == NULL) { + packet_start(SSH_MSG_CHANNEL_OPEN_FAILURE); + packet_put_int(remote_id); + } else { + /* Send a confirmation to the remote host. */ + debug("Forwarding authentication connection."); + packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); + packet_put_int(remote_id); + packet_put_int(c->self); } - debug("Forwarding authentication connection."); - - /* - * Dummy host name. This will be freed when the channel is freed; it - * will still be valid in the packet_put_string below since the - * channel cannot yet be freed at that point. - */ - dummyname = xstrdup("authentication agent connection"); - - newch = channel_allocate(SSH_CHANNEL_OPEN, sock, dummyname); - channels[newch].remote_id = remch; - - /* Send a confirmation to the remote host. */ - packet_start(SSH_MSG_CHANNEL_OPEN_CONFIRMATION); - packet_put_int(remch); - packet_put_int(newch); packet_send(); } diff --git a/channels.h b/channels.h index bf70a8f21..6739b2214 100644 --- a/channels.h +++ b/channels.h @@ -32,7 +32,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: channels.h,v 1.31 2001/04/13 22:46:53 beck Exp $"); */ +/* RCSID("$OpenBSD: channels.h,v 1.32 2001/05/04 23:47:33 markus Exp $"); */ #ifndef CHANNELS_H #define CHANNELS_H @@ -40,7 +40,6 @@ #include "buffer.h" /* Definitions for channel types. */ -#define SSH_CHANNEL_FREE 0 /* This channel is free (unused). */ #define SSH_CHANNEL_X11_LISTENER 1 /* Listening for inet X11 conn. */ #define SSH_CHANNEL_PORT_LISTENER 2 /* Listening on a port. */ #define SSH_CHANNEL_OPENING 3 /* waiting for confirmation */ @@ -56,8 +55,10 @@ #define SSH_CHANNEL_DYNAMIC 13 #define SSH_CHANNEL_MAX_TYPE 14 +#define SSH_CHANNEL_PATH_LEN 30 + /* - * Data structure for channel data. This is iniailized in channel_allocate + * Data structure for channel data. This is initialized in channel_new * and cleared in channel_free. */ struct Channel; @@ -84,8 +85,8 @@ struct Channel { Buffer output; /* data received over encrypted connection for * send on socket */ Buffer extended; - char path[200]; /* path for unix domain sockets, or host name - * for forwards */ + char path[SSH_CHANNEL_PATH_LEN]; + /* path for unix domain sockets, or host name for forwards */ int listening_port; /* port being listened for forwards */ int host_port; /* remote port to connect for forwards */ char *remote_name; /* remote hostname */ @@ -132,10 +133,6 @@ void channel_register_filter(int id, channel_filter_fn *fn); void channel_cancel_cleanup(int id); Channel *channel_lookup(int id); -int -channel_new(char *ctype, int type, int rfd, int wfd, int efd, - int window, int maxpack, int extended_usage, char *remote_name, - int nonblock); void channel_set_fds(int id, int rfd, int wfd, int efd, int extusage, int nonblock); @@ -162,10 +159,13 @@ void channel_set_options(int hostname_in_open); * must have been allocated with xmalloc; this will free it when the channel * is freed. */ -int channel_allocate(int type, int sock, char *remote_name); +Channel * +channel_new(char *ctype, int type, int rfd, int wfd, int efd, + int window, int maxpack, int extended_usage, char *remote_name, + int nonblock); /* Free the channel and close its socket. */ -void channel_free(int channel); +void channel_free(Channel *c); /* * Allocate/update select bitmasks and add any bits relevant to channels in diff --git a/clientloop.c b/clientloop.c index d76189738..2bc5b54aa 100644 --- a/clientloop.c +++ b/clientloop.c @@ -59,7 +59,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: clientloop.c,v 1.66 2001/04/29 19:16:52 markus Exp $"); +RCSID("$OpenBSD: clientloop.c,v 1.67 2001/05/04 23:47:34 markus Exp $"); #include "ssh.h" #include "ssh1.h" @@ -1027,7 +1027,7 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) Channel* c = NULL; char *listen_address, *originator_address; int listen_port, originator_port; - int sock, newch; + int sock; /* Get rest of the packet */ listen_address = packet_get_string(NULL); @@ -1040,12 +1040,18 @@ client_request_forwarded_tcpip(const char *request_type, int rchan) listen_address, listen_port, originator_address, originator_port); sock = channel_connect_by_listen_adress(listen_port); - if (sock >= 0) { - newch = channel_new("forwarded-tcpip", - SSH_CHANNEL_CONNECTING, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, - xstrdup(originator_address), 1); - c = channel_lookup(newch); + if (sock < 0) { + xfree(originator_address); + xfree(listen_address); + return NULL; + } + c = channel_new("forwarded-tcpip", + SSH_CHANNEL_CONNECTING, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, + xstrdup(originator_address), 1); + if (c == NULL) { + error("client_request_forwarded_tcpip: channel_new failed"); + close(sock); } xfree(originator_address); xfree(listen_address); @@ -1058,7 +1064,7 @@ client_request_x11(const char *request_type, int rchan) Channel *c = NULL; char *originator; int originator_port; - int sock, newch; + int sock; if (!options.forward_x11) { error("Warning: ssh server tried X11 forwarding."); @@ -1076,15 +1082,18 @@ client_request_x11(const char *request_type, int rchan) /* XXX check permission */ debug("client_request_x11: request from %s %d", originator, originator_port); - sock = x11_connect_display(); - if (sock >= 0) { - newch = channel_new("x11", - SSH_CHANNEL_X11_OPEN, sock, sock, -1, - CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, - xstrdup("x11"), 1); - c = channel_lookup(newch); - } xfree(originator); + sock = x11_connect_display(); + if (sock < 0) + return NULL; + c = channel_new("x11", + SSH_CHANNEL_X11_OPEN, sock, sock, -1, + CHAN_TCP_WINDOW_DEFAULT, CHAN_X11_PACKET_DEFAULT, 0, + xstrdup("x11"), 1); + if (c == NULL) { + error("client_request_x11: channel_new failed"); + close(sock); + } return c; } @@ -1092,7 +1101,7 @@ Channel* client_request_agent(const char *request_type, int rchan) { Channel *c = NULL; - int sock, newch; + int sock; if (!options.forward_agent) { error("Warning: ssh server tried agent forwarding."); @@ -1100,12 +1109,15 @@ client_request_agent(const char *request_type, int rchan) return NULL; } sock = ssh_get_authentication_socket(); - if (sock >= 0) { - newch = channel_new("authentication agent connection", - SSH_CHANNEL_OPEN, sock, sock, -1, - CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, - xstrdup("authentication agent connection"), 1); - c = channel_lookup(newch); + if (sock < 0) + return NULL; + c = channel_new("authentication agent connection", + SSH_CHANNEL_OPEN, sock, sock, -1, + CHAN_X11_WINDOW_DEFAULT, CHAN_TCP_WINDOW_DEFAULT, 0, + xstrdup("authentication agent connection"), 1); + if (c == NULL) { + error("client_request_agent: channel_new failed"); + close(sock); } return c; } diff --git a/nchan.c b/nchan.c index 77e4ef486..f4606e07f 100644 --- a/nchan.c +++ b/nchan.c @@ -23,7 +23,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: nchan.c,v 1.23 2001/02/28 08:54:55 markus Exp $"); +RCSID("$OpenBSD: nchan.c,v 1.24 2001/05/04 23:47:34 markus Exp $"); #include "ssh1.h" #include "ssh2.h" @@ -391,9 +391,17 @@ chan_send_close2(Channel *c) /* shared */ +void +chan_mark_dead(Channel *c) +{ + c->flags |= CHAN_DEAD; +} + int chan_is_dead(Channel *c) { + if (c->flags & CHAN_DEAD) + return 1; if (c->istate != CHAN_INPUT_CLOSED || c->ostate != CHAN_OUTPUT_CLOSED) return 0; if (!compat20) { diff --git a/nchan.h b/nchan.h index 623ecccc3..db04973f4 100644 --- a/nchan.h +++ b/nchan.h @@ -22,7 +22,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* RCSID("$OpenBSD: nchan.h,v 1.10 2001/02/28 08:54:55 markus Exp $"); */ +/* RCSID("$OpenBSD: nchan.h,v 1.11 2001/05/04 23:47:34 markus Exp $"); */ #ifndef NCHAN_H #define NCHAN_H @@ -69,6 +69,7 @@ #define CHAN_CLOSE_SENT 0x01 #define CHAN_CLOSE_RCVD 0x02 +#define CHAN_DEAD 0x04 /* Channel EVENTS */ @@ -85,6 +86,7 @@ extern chan_event_fn *chan_write_failed; extern chan_event_fn *chan_obuf_empty; int chan_is_dead(Channel * c); +void chan_mark_dead(Channel * c); void chan_init_iostates(Channel * c); void chan_init(void); diff --git a/serverloop.c b/serverloop.c index 2ca892e5d..5b3135564 100644 --- a/serverloop.c +++ b/serverloop.c @@ -35,7 +35,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: serverloop.c,v 1.63 2001/04/29 19:16:52 markus Exp $"); +RCSID("$OpenBSD: serverloop.c,v 1.64 2001/05/04 23:47:34 markus Exp $"); #include "xmalloc.h" #include "packet.h" @@ -801,7 +801,8 @@ server_input_window_size(int type, int plen, void *ctxt) Channel * server_request_direct_tcpip(char *ctype) { - int sock, newch; + Channel *c; + int sock; char *target, *originator; int target_port, originator_port; @@ -820,16 +821,20 @@ server_request_direct_tcpip(char *ctype) xfree(originator); if (sock < 0) return NULL; - newch = channel_new(ctype, SSH_CHANNEL_CONNECTING, + c = channel_new(ctype, SSH_CHANNEL_CONNECTING, sock, sock, -1, CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 0, xstrdup("direct-tcpip"), 1); - return (newch >= 0) ? channel_lookup(newch) : NULL; + if (c == NULL) { + error("server_request_direct_tcpip: channel_new failed"); + close(sock); + } + return c; } Channel * server_request_session(char *ctype) { - int newch; + Channel *c; debug("input_session_request"); packet_done(); @@ -839,19 +844,22 @@ server_request_session(char *ctype) * SSH_CHANNEL_LARVAL. Additionally, a callback for handling all * CHANNEL_REQUEST messages is registered. */ - newch = channel_new(ctype, SSH_CHANNEL_LARVAL, - -1, -1, -1, 0, CHAN_SES_PACKET_DEFAULT, + c = channel_new(ctype, SSH_CHANNEL_LARVAL, + -1, -1, -1, /*window size*/0, CHAN_SES_PACKET_DEFAULT, 0, xstrdup("server-session"), 1); - if (session_open(newch) == 1) { - channel_register_callback(newch, SSH2_MSG_CHANNEL_REQUEST, - session_input_channel_req, (void *)0); - channel_register_cleanup(newch, session_close_by_channel); - return channel_lookup(newch); - } else { - debug("session open failed, free channel %d", newch); - channel_free(newch); + if (c == NULL) { + error("server_request_session: channel_new failed"); + return NULL; } - return NULL; + if (session_open(c->self) != 1) { + debug("session open failed, free channel %d", c->self); + channel_free(c); + return NULL; + } + channel_register_callback(c->self, SSH2_MSG_CHANNEL_REQUEST, + session_input_channel_req, (void *)0); + channel_register_cleanup(c->self, session_close_by_channel); + return c; } void diff --git a/ssh.c b/ssh.c index 0ba69be53..c2932582f 100644 --- a/ssh.c +++ b/ssh.c @@ -39,7 +39,7 @@ */ #include "includes.h" -RCSID("$OpenBSD: ssh.c,v 1.117 2001/04/30 11:18:52 markus Exp $"); +RCSID("$OpenBSD: ssh.c,v 1.118 2001/05/04 23:47:34 markus Exp $"); #include #include @@ -1058,8 +1058,8 @@ ssh_session2_callback(int id, void *arg) int ssh_session2_command(void) { - int id, window, packetmax; - int in, out, err; + Channel *c; + int window, packetmax, in, out, err; if (stdin_null_flag) { in = open(_PATH_DEVNULL, O_RDONLY); @@ -1086,18 +1086,20 @@ ssh_session2_command(void) window *= 2; packetmax *=2; } - id = channel_new( + c = channel_new( "session", SSH_CHANNEL_OPENING, in, out, err, window, packetmax, CHAN_EXTENDED_WRITE, xstrdup("client-session"), /*nonblock*/0); + if (c == NULL) + fatal("ssh_session2_command: channel_new failed"); -debug("channel_new: %d", id); + debug3("ssh_session2_command: channel_new: %d", c->self); - channel_open(id); - channel_register_callback(id, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, + channel_open(c->self); + channel_register_callback(c->self, SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, ssh_session2_callback, (void *)0); - return id; + return c->self; } int