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

📄 ssh.c

📁 远程登陆工具软件源码 用于远程登陆unix
💻 C
📖 第 1 页 / 共 5 页
字号:
}

static void s_wrpkt(Ssh ssh)
{
    int len, backlog;
    len = s_wrpkt_prepare(ssh);
    backlog = sk_write(ssh->s, (char *)ssh->pktout.data, len);
    if (backlog > SSH_MAX_BACKLOG)
	ssh_throttle_all(ssh, 1, backlog);
}

static void s_wrpkt_defer(Ssh ssh)
{
    int len;
    len = s_wrpkt_prepare(ssh);
    if (ssh->deferred_len + len > ssh->deferred_size) {
	ssh->deferred_size = ssh->deferred_len + len + 128;
	ssh->deferred_send_data = sresize(ssh->deferred_send_data,
					  ssh->deferred_size,
					  unsigned char);
    }
    memcpy(ssh->deferred_send_data + ssh->deferred_len, ssh->pktout.data, len);
    ssh->deferred_len += len;
}

/*
 * Construct a packet with the specified contents.
 */
static void construct_packet(Ssh ssh, int pkttype, va_list ap1, va_list ap2)
{
    unsigned char *p, *argp, argchar;
    unsigned long argint;
    int pktlen, argtype, arglen;
    Bignum bn;

    pktlen = 0;
    while ((argtype = va_arg(ap1, int)) != PKT_END) {
	switch (argtype) {
	  case PKT_INT:
	    (void) va_arg(ap1, int);
	    pktlen += 4;
	    break;
	  case PKT_CHAR:
	    (void) va_arg(ap1, int);
	    pktlen++;
	    break;
	  case PKT_DATA:
	    (void) va_arg(ap1, unsigned char *);
	    arglen = va_arg(ap1, int);
	    pktlen += arglen;
	    break;
	  case PKT_STR:
	    argp = va_arg(ap1, unsigned char *);
	    arglen = strlen((char *)argp);
	    pktlen += 4 + arglen;
	    break;
	  case PKT_BIGNUM:
	    bn = va_arg(ap1, Bignum);
	    pktlen += ssh1_bignum_length(bn);
	    break;
	  default:
	    assert(0);
	}
    }

    s_wrpkt_start(ssh, pkttype, pktlen);
    p = ssh->pktout.body;

    while ((argtype = va_arg(ap2, int)) != PKT_END) {
	switch (argtype) {
	  case PKT_INT:
	    argint = va_arg(ap2, int);
	    PUT_32BIT(p, argint);
	    p += 4;
	    break;
	  case PKT_CHAR:
	    argchar = (unsigned char) va_arg(ap2, int);
	    *p = argchar;
	    p++;
	    break;
	  case PKT_DATA:
	    argp = va_arg(ap2, unsigned char *);
	    arglen = va_arg(ap2, int);
	    memcpy(p, argp, arglen);
	    p += arglen;
	    break;
	  case PKT_STR:
	    argp = va_arg(ap2, unsigned char *);
	    arglen = strlen((char *)argp);
	    PUT_32BIT(p, arglen);
	    memcpy(p + 4, argp, arglen);
	    p += 4 + arglen;
	    break;
	  case PKT_BIGNUM:
	    bn = va_arg(ap2, Bignum);
	    p += ssh1_write_bignum(p, bn);
	    break;
	}
    }
}

static void send_packet(Ssh ssh, int pkttype, ...)
{
    va_list ap1, ap2;
    va_start(ap1, pkttype);
    va_start(ap2, pkttype);
    construct_packet(ssh, pkttype, ap1, ap2);
    s_wrpkt(ssh);
}

static void defer_packet(Ssh ssh, int pkttype, ...)
{
    va_list ap1, ap2;
    va_start(ap1, pkttype);
    va_start(ap2, pkttype);
    construct_packet(ssh, pkttype, ap1, ap2);
    s_wrpkt_defer(ssh);
}

static int ssh_versioncmp(char *a, char *b)
{
    char *ae, *be;
    unsigned long av, bv;

    av = strtoul(a, &ae, 10);
    bv = strtoul(b, &be, 10);
    if (av != bv)
	return (av < bv ? -1 : +1);
    if (*ae == '.')
	ae++;
    if (*be == '.')
	be++;
    av = strtoul(ae, &ae, 10);
    bv = strtoul(be, &be, 10);
    if (av != bv)
	return (av < bv ? -1 : +1);
    return 0;
}

/*
 * Utility routines for putting an SSH-protocol `string' and
 * `uint32' into a SHA state.
 */
#include <stdio.h>
static void sha_string(SHA_State * s, void *str, int len)
{
    unsigned char lenblk[4];
    PUT_32BIT(lenblk, len);
    SHA_Bytes(s, lenblk, 4);
    SHA_Bytes(s, str, len);
}

static void sha_uint32(SHA_State * s, unsigned i)
{
    unsigned char intblk[4];
    PUT_32BIT(intblk, i);
    SHA_Bytes(s, intblk, 4);
}

/*
 * SSH2 packet construction functions.
 */
static void ssh2_pkt_ensure(Ssh ssh, int length)
{
    if (ssh->pktout.maxlen < length) {
	ssh->pktout.maxlen = length + 256;
	ssh->pktout.data = sresize(ssh->pktout.data,
				   ssh->pktout.maxlen + APIEXTRA,
				   unsigned char);
	if (!ssh->pktout.data)
	    fatalbox("Out of memory");
    }
}
static void ssh2_pkt_adddata(Ssh ssh, void *data, int len)
{
    ssh->pktout.length += len;
    ssh2_pkt_ensure(ssh, ssh->pktout.length);
    memcpy(ssh->pktout.data + ssh->pktout.length - len, data, len);
}
static void ssh2_pkt_addbyte(Ssh ssh, unsigned char byte)
{
    ssh2_pkt_adddata(ssh, &byte, 1);
}
static void ssh2_pkt_init(Ssh ssh, int pkt_type)
{
    ssh->pktout.length = 5;
    ssh2_pkt_addbyte(ssh, (unsigned char) pkt_type);
}
static void ssh2_pkt_addbool(Ssh ssh, unsigned char value)
{
    ssh2_pkt_adddata(ssh, &value, 1);
}
static void ssh2_pkt_adduint32(Ssh ssh, unsigned long value)
{
    unsigned char x[4];
    PUT_32BIT(x, value);
    ssh2_pkt_adddata(ssh, x, 4);
}
static void ssh2_pkt_addstring_start(Ssh ssh)
{
    ssh2_pkt_adduint32(ssh, 0);
    ssh->pktout.savedpos = ssh->pktout.length;
}
static void ssh2_pkt_addstring_str(Ssh ssh, char *data)
{
    ssh2_pkt_adddata(ssh, data, strlen(data));
    PUT_32BIT(ssh->pktout.data + ssh->pktout.savedpos - 4,
	      ssh->pktout.length - ssh->pktout.savedpos);
}
static void ssh2_pkt_addstring_data(Ssh ssh, char *data, int len)
{
    ssh2_pkt_adddata(ssh, data, len);
    PUT_32BIT(ssh->pktout.data + ssh->pktout.savedpos - 4,
	      ssh->pktout.length - ssh->pktout.savedpos);
}
static void ssh2_pkt_addstring(Ssh ssh, char *data)
{
    ssh2_pkt_addstring_start(ssh);
    ssh2_pkt_addstring_str(ssh, data);
}
static unsigned char *ssh2_mpint_fmt(Bignum b, int *len)
{
    unsigned char *p;
    int i, n = (bignum_bitcount(b) + 7) / 8;
    p = snewn(n + 1, unsigned char);
    if (!p)
	fatalbox("out of memory");
    p[0] = 0;
    for (i = 1; i <= n; i++)
	p[i] = bignum_byte(b, n - i);
    i = 0;
    while (i <= n && p[i] == 0 && (p[i + 1] & 0x80) == 0)
	i++;
    memmove(p, p + i, n + 1 - i);
    *len = n + 1 - i;
    return p;
}
static void ssh2_pkt_addmp(Ssh ssh, Bignum b)
{
    unsigned char *p;
    int len;
    p = ssh2_mpint_fmt(b, &len);
    ssh2_pkt_addstring_start(ssh);
    ssh2_pkt_addstring_data(ssh, (char *)p, len);
    sfree(p);
}

/*
 * Construct an SSH2 final-form packet: compress it, encrypt it,
 * put the MAC on it. Final packet, ready to be sent, is stored in
 * ssh->pktout.data. Total length is returned.
 */
static int ssh2_pkt_construct(Ssh ssh)
{
    int cipherblk, maclen, padding, i;

    if (ssh->logctx)
	log_packet(ssh->logctx, PKT_OUTGOING, ssh->pktout.data[5],
		   ssh2_pkt_type(ssh->pkt_ctx, ssh->pktout.data[5]),
		   ssh->pktout.data + 6, ssh->pktout.length - 6);

    /*
     * Compress packet payload.
     */
    {
	unsigned char *newpayload;
	int newlen;
	if (ssh->cscomp &&
	    ssh->cscomp->compress(ssh->cs_comp_ctx, ssh->pktout.data + 5,
				  ssh->pktout.length - 5,
				  &newpayload, &newlen)) {
	    ssh->pktout.length = 5;
	    ssh2_pkt_adddata(ssh, newpayload, newlen);
	    sfree(newpayload);
	}
    }

    /*
     * Add padding. At least four bytes, and must also bring total
     * length (minus MAC) up to a multiple of the block size.
     */
    cipherblk = ssh->cscipher ? ssh->cscipher->blksize : 8;  /* block size */
    cipherblk = cipherblk < 8 ? 8 : cipherblk;	/* or 8 if blksize < 8 */
    padding = 4;
    padding +=
	(cipherblk - (ssh->pktout.length + padding) % cipherblk) % cipherblk;
    maclen = ssh->csmac ? ssh->csmac->len : 0;
    ssh2_pkt_ensure(ssh, ssh->pktout.length + padding + maclen);
    ssh->pktout.data[4] = padding;
    for (i = 0; i < padding; i++)
	ssh->pktout.data[ssh->pktout.length + i] = random_byte();
    PUT_32BIT(ssh->pktout.data, ssh->pktout.length + padding - 4);
    if (ssh->csmac)
	ssh->csmac->generate(ssh->cs_mac_ctx, ssh->pktout.data,
			     ssh->pktout.length + padding,
			     ssh->v2_outgoing_sequence);
    ssh->v2_outgoing_sequence++;       /* whether or not we MACed */

    if (ssh->cscipher)
	ssh->cscipher->encrypt(ssh->cs_cipher_ctx,
			       ssh->pktout.data, ssh->pktout.length + padding);

    /* Ready-to-send packet starts at ssh->pktout.data. We return length. */
    return ssh->pktout.length + padding + maclen;
}

/*
 * Construct and send an SSH2 packet immediately.
 */
static void ssh2_pkt_send(Ssh ssh)
{
    int len;
    int backlog;
    len = ssh2_pkt_construct(ssh);
    backlog = sk_write(ssh->s, (char *)ssh->pktout.data, len);
    if (backlog > SSH_MAX_BACKLOG)
	ssh_throttle_all(ssh, 1, backlog);
}

/*
 * Construct an SSH2 packet and add it to a deferred data block.
 * Useful for sending multiple packets in a single sk_write() call,
 * to prevent a traffic-analysing listener from being able to work
 * out the length of any particular packet (such as the password
 * packet).
 * 
 * Note that because SSH2 sequence-numbers its packets, this can
 * NOT be used as an m4-style `defer' allowing packets to be
 * constructed in one order and sent in another.
 */
static void ssh2_pkt_defer(Ssh ssh)
{
    int len = ssh2_pkt_construct(ssh);
    if (ssh->deferred_len + len > ssh->deferred_size) {
	ssh->deferred_size = ssh->deferred_len + len + 128;
	ssh->deferred_send_data = sresize(ssh->deferred_send_data,
					  ssh->deferred_size,
					  unsigned char);
    }
    memcpy(ssh->deferred_send_data + ssh->deferred_len, ssh->pktout.data, len);
    ssh->deferred_len += len;
}

/*
 * Send the whole deferred data block constructed by
 * ssh2_pkt_defer() or SSH1's defer_packet().
 */
static void ssh_pkt_defersend(Ssh ssh)
{
    int backlog;
    backlog = sk_write(ssh->s, (char *)ssh->deferred_send_data,
		       ssh->deferred_len);
    ssh->deferred_len = ssh->deferred_size = 0;
    sfree(ssh->deferred_send_data);
    ssh->deferred_send_data = NULL;
    if (backlog > SSH_MAX_BACKLOG)
	ssh_throttle_all(ssh, 1, backlog);
}

#if 0
void bndebug(char *string, Bignum b)
{
    unsigned char *p;
    int i, len;
    p = ssh2_mpint_fmt(b, &len);
    debug(("%s", string));
    for (i = 0; i < len; i++)
	debug((" %02x", p[i]));
    debug(("\n"));
    sfree(p);
}
#endif

static void sha_mpint(SHA_State * s, Bignum b)
{
    unsigned char *p;
    int len;
    p = ssh2_mpint_fmt(b, &len);
    sha_string(s, p, len);
    sfree(p);
}

/*
 * Packet decode functions for both SSH1 and SSH2.
 */
static unsigned long ssh_pkt_getuint32(Ssh ssh)
{
    unsigned long value;
    if (ssh->pktin.length - ssh->pktin.savedpos < 4)
	return 0;		       /* arrgh, no way to decline (FIXME?) */
    value = GET_32BIT(ssh->pktin.body + ssh->pktin.savedpos);
    ssh->pktin.savedpos += 4;
    return value;
}
static int ssh2_pkt_getbool(Ssh ssh)
{
    unsigned long value;
    if (ssh->pktin.length - ssh->pktin.savedpos < 1)
	return 0;		       /* arrgh, no way to decline (FIXME?) */
    value = ssh->pktin.body[ssh->pktin.savedpos] != 0;
    ssh->pktin.savedpos++;
    return value;
}
static void ssh_pkt_getstring(Ssh ssh, char **p, int *length)
{
    int len;
    *p = NULL;
    *length = 0;
    if (ssh->pktin.length - ssh->pktin.savedpos < 4)
	return;
    len = GET_32BIT(ssh->pktin.body + ssh->pktin.savedpos);
    if (len < 0)
	return;
    *length = len;
    ssh->pktin.savedpos += 4;
    if (ssh->pktin.length - ssh->pktin.savedpos < *length)
	return;
    *p = (char *)(ssh->pktin.body + ssh->pktin.savedpos);
    ssh->pktin.savedpos += *length;
}

⌨️ 快捷键说明

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