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

📄 ssh.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 2-3-4 tree storing channels. */struct ssh_channel {    Ssh ssh;			       /* pointer back to main context */    unsigned remoteid, localid;    int type;    /*     * In SSH1, this value contains four bits:     *      *   1   We have sent SSH1_MSG_CHANNEL_CLOSE.     *   2   We have sent SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.     *   4   We have received SSH1_MSG_CHANNEL_CLOSE.     *   8   We have received SSH1_MSG_CHANNEL_CLOSE_CONFIRMATION.     *      * A channel is completely finished with when all four bits are set.     */    int closes;    union {	struct ssh1_data_channel {	    int throttling;	} v1;	struct ssh2_data_channel {	    bufchain outbuffer;	    unsigned remwindow, remmaxpkt;	    unsigned locwindow;	} v2;    } v;    union {	struct ssh_agent_channel {	    unsigned char *message;	    unsigned char msglen[4];	    unsigned lensofar, totallen;	} a;	struct ssh_x11_channel {	    Socket s;	} x11;	struct ssh_pfd_channel {	    Socket s;	} pfd;    } u;};/* * 2-3-4 tree storing remote->local port forwardings. SSH 1 and SSH * 2 use this structure in different ways, reflecting SSH 2's * altogether saner approach to port forwarding. *  * In SSH 1, you arrange a remote forwarding by sending the server * the remote port number, and the local destination host:port. * When a connection comes in, the server sends you back that * host:port pair, and you connect to it. This is a ready-made * security hole if you're not on the ball: a malicious server * could send you back _any_ host:port pair, so if you trustingly * connect to the address it gives you then you've just opened the * entire inside of your corporate network just by connecting * through it to a dodgy SSH server. Hence, we must store a list of * host:port pairs we _are_ trying to forward to, and reject a * connection request from the server if it's not in the list. *  * In SSH 2, each side of the connection minds its own business and * doesn't send unnecessary information to the other. You arrange a * remote forwarding by sending the server just the remote port * number. When a connection comes in, the server tells you which * of its ports was connected to; and _you_ have to remember what * local host:port pair went with that port number. *  * Hence: in SSH 1 this structure stores host:port pairs we intend * to allow connections to, and is indexed by those host:port * pairs. In SSH 2 it stores a mapping from source port to * destination host:port pair, and is indexed by source port. */struct ssh_rportfwd {    unsigned sport, dport;    char dhost[256];};struct Packet {    long length;    int type;    unsigned char *data;    unsigned char *body;    long savedpos;    long maxlen;};static void ssh1_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt);static void ssh2_protocol(Ssh ssh, unsigned char *in, int inlen, int ispkt);static void ssh_size(void *handle, int width, int height);static void ssh_special(void *handle, Telnet_Special);static int ssh2_try_send(struct ssh_channel *c);static void ssh2_add_channel_data(struct ssh_channel *c, char *buf, int len);static void ssh_throttle_all(Ssh ssh, int enable, int bufsize);static void ssh2_set_window(struct ssh_channel *c, unsigned newwin);static int ssh_sendbuffer(void *handle);static void ssh_do_close(Ssh ssh);static unsigned long ssh_pkt_getuint32(Ssh ssh);static int ssh2_pkt_getbool(Ssh ssh);static void ssh_pkt_getstring(Ssh ssh, char **p, int *length);struct rdpkt1_state_tag {    long len, pad, biglen, to_read;    unsigned long realcrc, gotcrc;    unsigned char *p;    int i;    int chunk;};struct rdpkt2_state_tag {    long len, pad, payload, packetlen, maclen;    int i;    int cipherblk;    unsigned long incoming_sequence;};struct ssh_tag {    const struct plug_function_table *fn;    /* the above field _must_ be first in the structure */    SHA_State exhash, exhashbase;    Socket s;    void *ldisc;    void *logctx;    unsigned char session_key[32];    int v1_compressing;    int v1_remote_protoflags;    int v1_local_protoflags;    int agentfwd_enabled;    int X11_fwd_enabled;    int remote_bugs;    const struct ssh_cipher *cipher;    void *v1_cipher_ctx;    void *crcda_ctx;    const struct ssh2_cipher *cscipher, *sccipher;    void *cs_cipher_ctx, *sc_cipher_ctx;    const struct ssh_mac *csmac, *scmac;    void *cs_mac_ctx, *sc_mac_ctx;    const struct ssh_compress *cscomp, *sccomp;    void *cs_comp_ctx, *sc_comp_ctx;    const struct ssh_kex *kex;    const struct ssh_signkey *hostkey;    unsigned char v2_session_id[20];    void *kex_ctx;    char *savedhost;    int savedport;    int send_ok;    int echoing, editing;    void *frontend;    int ospeed, ispeed;		       /* temporaries */    int term_width, term_height;    tree234 *channels;		       /* indexed by local id */    struct ssh_channel *mainchan;      /* primary session channel */    int exitcode;    tree234 *rportfwds;    enum {	SSH_STATE_PREPACKET,	SSH_STATE_BEFORE_SIZE,	SSH_STATE_INTERMED,	SSH_STATE_SESSION,	SSH_STATE_CLOSED    } state;    int size_needed, eof_needed;    struct Packet pktin;    struct Packet pktout;    unsigned char *deferred_send_data;    int deferred_len, deferred_size;    /*     * State associated with packet logging     */    int pktout_logmode;    int pktout_nblanks;    struct logblank_t *pktout_blanks;    /*     * Gross hack: pscp will try to start SFTP but fall back to     * scp1 if that fails. This variable is the means by which     * scp.c can reach into the SSH code and find out which one it     * got.     */    int fallback_cmd;    /*     * Used for username and password input.     */    char *userpass_input_buffer;    int userpass_input_buflen;    int userpass_input_bufpos;    int userpass_input_echo;    char *portfwd_strptr;    int pkt_ctx;    void *x11auth;    int version;    int v1_throttle_count;    int overall_bufsize;    int throttled_all;    int v1_stdout_throttling;    int v2_outgoing_sequence;    int ssh1_rdpkt_crstate;    int ssh2_rdpkt_crstate;    int do_ssh_init_crstate;    int ssh_gotdata_crstate;    int ssh1_protocol_crstate;    int do_ssh1_login_crstate;    int do_ssh2_transport_crstate;    int do_ssh2_authconn_crstate;    void *do_ssh_init_state;    void *do_ssh1_login_state;    void *do_ssh2_transport_state;    void *do_ssh2_authconn_state;    struct rdpkt1_state_tag rdpkt1_state;    struct rdpkt2_state_tag rdpkt2_state;    void (*protocol) (Ssh ssh, unsigned char *in, int inlen, int ispkt);    int (*s_rdpkt) (Ssh ssh, unsigned char **data, int *datalen);    /*     * We maintain a full _copy_ of a Config structure here, not     * merely a pointer to it. That way, when we're passed a new     * one for reconfiguration, we can check the differences and     * potentially reconfigure port forwardings etc in mid-session.     */    Config cfg;    /*     * Used to transfer data back from async agent callbacks.     */    void *agent_response;    int agent_response_len;    /*     * Text manipulation buffers for port forwarding. These are kept     * here to simplify the state machine code in the protocol     * funtions. We can't put these to stack under Symbian OS (too     * big), and using local variables for the heap allocated buffers     * would be cumbersome since we'd need to free and reallocate them     * around every coroutine call. "One of the PuTTY source files     * contains possibly the worst piece of C preprocessor hackery     * I've ever seen in production code." indeed.     */    char *sports;    char *dports;    char *saddr;    char *host;    /*     * Special code list to be returned from ssh_get_specials(). Placing it     * here avoids makiung it writable static data.     */    struct telnet_special *specials;};#define logevent(s) logevent(ssh->frontend, s)/* logevent, only printf-formatted. */static void logeventf(Ssh ssh, const char *fmt, ...){    va_list ap;    char *buf;    va_start(ap, fmt);    buf = dupvprintf(fmt, ap);    va_end(ap);    logevent(buf);    sfree(buf);}#define bombout(msg) \    do { \        char *text = dupprintf msg; \	ssh_do_close(ssh); \        logevent(text); \        connection_fatal(ssh->frontend, "%s", text); \        sfree(text); \    } while (0)/* Functions to leave bits out of the SSH packet log file. */static void dont_log_password(Ssh ssh, int blanktype){    if (ssh->cfg.logomitpass)	ssh->pktout_logmode = blanktype;}static void dont_log_data(Ssh ssh, int blanktype){    if (ssh->cfg.logomitdata)	ssh->pktout_logmode = blanktype;}static void end_log_omission(Ssh ssh){    ssh->pktout_logmode = PKTLOG_EMIT;}static int ssh_channelcmp(void *av, void *bv){    struct ssh_channel *a = (struct ssh_channel *) av;    struct ssh_channel *b = (struct ssh_channel *) bv;    if (a->localid < b->localid)	return -1;    if (a->localid > b->localid)	return +1;    return 0;}static int ssh_channelfind(void *av, void *bv){    unsigned *a = (unsigned *) av;    struct ssh_channel *b = (struct ssh_channel *) bv;    if (*a < b->localid)	return -1;    if (*a > b->localid)	return +1;    return 0;}static int ssh_rportcmp_ssh1(void *av, void *bv){    struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;    struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;    int i;    if ( (i = strcmp(a->dhost, b->dhost)) != 0)	return i < 0 ? -1 : +1;    if (a->dport > b->dport)	return +1;    if (a->dport < b->dport)	return -1;    return 0;}static int ssh_rportcmp_ssh2(void *av, void *bv){    struct ssh_rportfwd *a = (struct ssh_rportfwd *) av;    struct ssh_rportfwd *b = (struct ssh_rportfwd *) bv;    if (a->sport > b->sport)	return +1;    if (a->sport < b->sport)	return -1;    return 0;}static int alloc_channel_id(Ssh ssh){    const unsigned CHANNEL_NUMBER_OFFSET = 256;    unsigned low, high, mid;    int tsize;    struct ssh_channel *c;    /*     * First-fit allocation of channel numbers: always pick the     * lowest unused one. To do this, binary-search using the     * counted B-tree to find the largest channel ID which is in a     * contiguous sequence from the beginning. (Precisely     * everything in that sequence must have ID equal to its tree     * index plus CHANNEL_NUMBER_OFFSET.)     */    tsize = count234(ssh->channels);    low = UINT_MAX;    high = tsize;    while (high - low > 1) {	mid = (high + low) / 2;	c = index234(ssh->channels, mid);	if (c->localid == mid + CHANNEL_NUMBER_OFFSET)	    low = mid;		       /* this one is fine */	else	    high = mid;		       /* this one is past it */    }    /*     * Now low points to either -1, or the tree index of the     * largest ID in the initial sequence.     */    {	unsigned i = low + 1 + CHANNEL_NUMBER_OFFSET;	assert(NULL == find234(ssh->channels, &i, ssh_channelfind));    }    return low + 1 + CHANNEL_NUMBER_OFFSET;}static void c_write(Ssh ssh, const char *buf, int len){    if ((statics()->flags & FLAG_STDERR)) {	int i;	for (i = 0; i < len; i++)	    if (buf[i] != '\r')		fputc(buf[i], stderr);	return;    }    from_backend(ssh->frontend, 1, buf, len);}static void c_write_untrusted(Ssh ssh, const char *buf, int len){    int i;    for (i = 0; i < len; i++) {	if (buf[i] == '\n')	    c_write(ssh, "\r\n", 2);	else if ((buf[i] & 0x60) || (buf[i] == '\r'))	    c_write(ssh, buf + i, 1);    }}static void c_write_str(Ssh ssh, const char *buf){    c_write(ssh, buf, strlen(buf));}/* * Collect incoming data in the incoming packet buffer. * Decipher and verify the packet when it is completely read. * Drop SSH1_MSG_DEBUG and SSH1_MSG_IGNORE packets. * Update the *data and *datalen variables. * Return the additional nr of bytes needed, or 0 when * a complete packet is available. */

⌨️ 快捷键说明

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