⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 channels.c

📁 C++编写
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Author: Tatu Ylonen <ylo@cs.hut.fi> * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland *                    All rights reserved * This file contains functions for generic socket connection forwarding. * There is also code for initiating connection forwarding for X11 connections, * arbitrary tcp/ip connections, and the authentication agent connection. * * As far as I am concerned, the code I have written for this software * can be used freely for any purpose.  Any derived versions of this * software must be clearly marked as such, and if the derived work is * incompatible with the protocol description in the RFC file, it must be * called by a name other than "ssh" or "Secure Shell". * * SSH2 support added by Markus Friedl. * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl.  All rights reserved. * Copyright (c) 1999 Dug Song.  All rights reserved. * Copyright (c) 1999 Theo de Raadt.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "includes.h"RCSID("$OpenBSD: channels.c,v 1.187 2003/03/05 22:33:43 markus Exp $");#include "ssh.h"#include "ssh1.h"#include "ssh2.h"#include "packet.h"#include "xmalloc.h"#include "log.h"#include "misc.h"#include "channels.h"#include "compat.h"#include "canohost.h"#include "key.h"#include "authfd.h"#include "pathnames.h"/* -- channel core *//* * Pointer to an array containing all allocated channels.  The array is * dynamically extended as needed. */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 set to NULL */static int channels_alloc = 0;/* * Maximum file descriptor value used in any of the channels.  This is * updated in channel_new. */static int channel_max_fd = 0;/* -- tcp forwarding *//* * Data structure for storing which hosts are permitted for forward requests. * The local sides of any remote forwards are stored in this array to prevent * a corrupt remote server from accessing arbitrary TCP/IP ports on our local * network (which might be behind a firewall). */typedef struct {	char *host_to_connect;		/* Connect to 'host'. */	u_short port_to_connect;	/* Connect to 'port'. */	u_short listen_port;		/* Remote side should listen port number. */} ForwardPermission;/* List of all permitted host/port pairs to connect. */static ForwardPermission permitted_opens[SSH_MAX_FORWARDS_PER_DIRECTION];/* Number of permitted host/port pairs in the array. */static int num_permitted_opens = 0;/* * If this is true, all opens are permitted.  This is the case on the server * on which we have to trust the client anyway, and the user could do * anything after logging in anyway. */static int all_opens_permitted = 0;/* -- X11 forwarding *//* Maximum number of fake X11 displays to try. */#define MAX_DISPLAYS  1000/* Saved X11 authentication protocol name. */static char *x11_saved_proto = NULL;/* Saved X11 authentication data.  This is the real data. */static char *x11_saved_data = NULL;static u_int x11_saved_data_len = 0;/* * Fake X11 authentication data.  This is what the server will be sending us; * we should replace any occurrences of this by the real data. */static char *x11_fake_data = NULL;static u_int x11_fake_data_len;/* -- agent forwarding */#define	NUM_SOCKS	10/* AF_UNSPEC or AF_INET or AF_INET6 */static int IPv4or6 = AF_UNSPEC;/* helper */static void port_open_helper(Channel *c, char *rtype);/* -- channel core */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 == NULL) {		log("channel_lookup: %d: bad id: channel free", id);		return NULL;	}	return c;}/* * Register filedescriptors for a channel, used when allocating a channel or * when the channel consumer/producer is ready, e.g. shell exec'd */static voidchannel_register_fds(Channel *c, int rfd, int wfd, int efd,    int extusage, int nonblock){	/* Update the maximum file descriptor value. */	channel_max_fd = MAX(channel_max_fd, rfd);	channel_max_fd = MAX(channel_max_fd, wfd);	channel_max_fd = MAX(channel_max_fd, efd);	/* XXX set close-on-exec -markus */	c->rfd = rfd;	c->wfd = wfd;	c->sock = (rfd == wfd) ? rfd : -1;	c->efd = efd;	c->extended_usage = extusage;	/* XXX ugly hack: nonblock is only set by the server */	if (nonblock && isatty(c->rfd)) {		debug("channel %d: rfd %d isatty", c->self, c->rfd);		c->isatty = 1;		if (!isatty(c->wfd)) {			error("channel %d: wfd %d is not a tty?",			    c->self, c->wfd);		}	} else {		c->isatty = 0;	}	/* enable nonblocking mode */	if (nonblock) {		if (rfd != -1)			set_nonblock(rfd);		if (wfd != -1)			set_nonblock(wfd);		if (efd != -1)			set_nonblock(efd);	}}/* * Allocate a new channel object and set its type and socket. This will cause * remote_name to be freed. */Channel *channel_new(char *ctype, int type, int rfd, int wfd, int efd,    u_int window, u_int maxpack, int extusage, char *remote_name, int nonblock){	int i, found;	Channel *c;	/* Do initial allocation if this is the first call. */	if (channels_alloc == 0) {		channels_alloc = 10;		channels = xmalloc(channels_alloc * sizeof(Channel *));		for (i = 0; i < channels_alloc; i++)			channels[i] = NULL;		fatal_add_cleanup((void (*) (void *)) channel_free_all, NULL);	}	/* Try to find a free slot where to put the new channel. */	for (found = -1, i = 0; i < channels_alloc; i++)		if (channels[i] == NULL) {			/* Found a free slot. */			found = i;			break;		}	if (found == -1) {		/* There are no free slots.  Take last+1 slot and expand the array.  */		found = channels_alloc;		channels_alloc += 10;		if (channels_alloc > 10000)			fatal("channel_new: internal error: channels_alloc %d "			    "too big.", channels_alloc);		debug2("channel: expanding %d", channels_alloc);		channels = xrealloc(channels, channels_alloc * sizeof(Channel *));		for (i = found; i < channels_alloc; i++)			channels[i] = NULL;	}	/* Initialize and return new channel. */	c = channels[found] = xmalloc(sizeof(Channel));	memset(c, 0, sizeof(Channel));	buffer_init(&c->input);	buffer_init(&c->output);	buffer_init(&c->extended);	c->ostate = CHAN_OUTPUT_OPEN;	c->istate = CHAN_INPUT_OPEN;	c->flags = 0;	channel_register_fds(c, rfd, wfd, efd, extusage, nonblock);	c->self = found;	c->type = type;	c->ctype = ctype;	c->local_window = window;	c->local_window_max = window;	c->local_consumed = 0;	c->local_maxpacket = maxpack;	c->remote_id = -1;	c->remote_name = remote_name;	c->remote_window = 0;	c->remote_maxpacket = 0;	c->force_drain = 0;	c->single_connection = 0;	c->detach_user = NULL;	c->confirm = NULL;	c->input_filter = NULL;	debug("channel %d: new [%s]", found, remote_name);	return c;}static intchannel_find_maxfd(void){	int i, max = 0;	Channel *c;	for (i = 0; i < channels_alloc; i++) {		c = channels[i];		if (c != NULL) {			max = MAX(max, c->rfd);			max = MAX(max, c->wfd);			max = MAX(max, c->efd);		}	}	return max;}intchannel_close_fd(int *fdp){	int ret = 0, fd = *fdp;	if (fd != -1) {		ret = close(fd);		*fdp = -1;		if (fd == channel_max_fd)			channel_max_fd = channel_find_maxfd();	}	return ret;}/* Close all channel fd/socket. */static voidchannel_close_fds(Channel *c){	debug3("channel_close_fds: channel %d: r %d w %d e %d",	    c->self, c->rfd, c->wfd, c->efd);	channel_close_fd(&c->sock);	channel_close_fd(&c->rfd);	channel_close_fd(&c->wfd);	channel_close_fd(&c->efd);}/* Free the channel and close its fd/socket. */voidchannel_free(Channel *c){	char *s;	int i, n;	for (n = 0, i = 0; i < channels_alloc; i++)		if (channels[i])			n++;	debug("channel_free: channel %d: %s, nchannels %d", c->self,	    c->remote_name ? c->remote_name : "???", n);	s = channel_open_message();	debug3("channel_free: status: %s", s);	xfree(s);	if (c->sock != -1)		shutdown(c->sock, SHUT_RDWR);	channel_close_fds(c);	buffer_free(&c->input);	buffer_free(&c->output);	buffer_free(&c->extended);	if (c->remote_name) {		xfree(c->remote_name);		c->remote_name = NULL;	}	channels[c->self] = NULL;	xfree(c);}voidchannel_free_all(void){	int i;	for (i = 0; i < channels_alloc; i++)		if (channels[i] != NULL)			channel_free(channels[i]);}/* * Closes the sockets/fds of all channels.  This is used to close extra file * descriptors after a fork. */voidchannel_close_all(void){	int i;	for (i = 0; i < channels_alloc; i++)		if (channels[i] != NULL)			channel_close_fds(channels[i]);}/* * Stop listening to channels. */voidchannel_stop_listening(void){	int i;	Channel *c;	for (i = 0; i < channels_alloc; i++) {		c = channels[i];		if (c != NULL) {			switch (c->type) {			case SSH_CHANNEL_AUTH_SOCKET:			case SSH_CHANNEL_PORT_LISTENER:			case SSH_CHANNEL_RPORT_LISTENER:			case SSH_CHANNEL_X11_LISTENER:				channel_close_fd(&c->sock);				channel_free(c);				break;			}		}	}}/* * Returns true if no channel has too much buffered data, and false if one or * more channel is overfull. */intchannel_not_very_much_buffered_data(void){	u_int i;	Channel *c;	for (i = 0; i < channels_alloc; i++) {		c = channels[i];		if (c != NULL && c->type == SSH_CHANNEL_OPEN) {#if 0			if (!compat20 &&			    buffer_len(&c->input) > packet_get_maxsize()) {				debug2("channel %d: big input buffer %d",				    c->self, buffer_len(&c->input));				return 0;			}#endif			if (buffer_len(&c->output) > packet_get_maxsize()) {				debug2("channel %d: big output buffer %d > %d",				    c->self, buffer_len(&c->output),				    packet_get_maxsize());				return 0;			}		}	}	return 1;}/* Returns true if any channel is still open. */intchannel_still_open(void){	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:		case SSH_CHANNEL_CLOSED:		case SSH_CHANNEL_AUTH_SOCKET:		case SSH_CHANNEL_DYNAMIC:		case SSH_CHANNEL_CONNECTING:		case SSH_CHANNEL_ZOMBIE:			continue;		case SSH_CHANNEL_LARVAL:			if (!compat20)				fatal("cannot happen: SSH_CHANNEL_LARVAL");			continue;		case SSH_CHANNEL_OPENING:		case SSH_CHANNEL_OPEN:		case SSH_CHANNEL_X11_OPEN:			return 1;		case SSH_CHANNEL_INPUT_DRAINING:		case SSH_CHANNEL_OUTPUT_DRAINING:			if (!compat13)				fatal("cannot happen: OUT_DRAIN");			return 1;		default:			fatal("channel_still_open: bad channel type %d", c->type);			/* NOTREACHED */		}	}	return 0;}/* Returns the id of an open channel suitable for keepaliving */intchannel_find_open(void){	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_X11_LISTENER:		case SSH_CHANNEL_PORT_LISTENER:		case SSH_CHANNEL_RPORT_LISTENER:		case SSH_CHANNEL_OPENING:		case SSH_CHANNEL_CONNECTING:		case SSH_CHANNEL_ZOMBIE:			continue;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -