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

📄 ssh.c

📁 一个支持FTP,SFTP的客户端程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	    } else if (st->pktin->type == SSH2_MSG_CHANNEL_EXTENDED_DATA) {
		do_blank = TRUE; blank_prefix = 8;
	    }
	    if (do_blank) {
		blank.offset = blank_prefix;
		blank.len = (st->pktin->length-6) - blank_prefix;
		blank.type = PKTLOG_OMIT;
		nblanks = 1;
	    }
	}
	log_packet(ssh->logctx, PKT_INCOMING, st->pktin->type,
		   ssh2_pkt_type(ssh->pkt_ctx, st->pktin->type),
		   st->pktin->data+6, st->pktin->length-6,
		   nblanks, &blank);
    }*/

    crFinish(st->pktin);
}

static void ssh1_pktout_size(struct Packet *pkt, int len)
{
    int pad, biglen;

    len += 5;			       /* type and CRC */
    pad = 8 - (len % 8);
    biglen = len + pad;

    pkt->length = len - 5;
    if (pkt->maxlen < biglen) {
	pkt->maxlen = biglen;
	pkt->data = sresize(pkt->data, biglen + 4 + APIEXTRA, unsigned char);
    }
    pkt->body = pkt->data + 4 + pad + 1;
}

static struct Packet *s_wrpkt_start(int type, int len)
{
    struct Packet *pkt = ssh_new_packet();
    ssh1_pktout_size(pkt, len);
    pkt->type = type;
    /* Initialise log omission state */
    pkt->nblanks = 0;
    pkt->blanks = NULL;
    return pkt;
}

static int s_wrpkt_prepare(Ssh ssh, struct Packet *pkt)
{
    int pad, biglen, i;
    unsigned long crc;
#ifdef __SC__
    /*
     * XXX various versions of SC (including 8.8.4) screw up the
     * register allocation in this function and use the same register
     * (D6) for len and as a temporary, with predictable results.  The
     * following sledgehammer prevents this.
     */
    volatile
#endif
    int len;

    pkt->body[-1] = pkt->type;

    /* Not used in FileZilla
    if (ssh->logctx)
	log_packet(ssh->logctx, PKT_OUTGOING, pkt->type,
		   ssh1_pkt_type(pkt->type),
		   pkt->body, pkt->length,
		   pkt->nblanks, pkt->blanks);*/
    sfree(pkt->blanks); pkt->blanks = NULL;
    pkt->nblanks = 0;
    
    if (ssh->v1_compressing) {
	unsigned char *compblk;
	int complen;
	zlib_compress_block(ssh->cs_comp_ctx,
			    pkt->body - 1, pkt->length + 1,
			    &compblk, &complen);
	ssh1_pktout_size(pkt, complen - 1);
	memcpy(pkt->body - 1, compblk, complen);
	sfree(compblk);
    }

    len = pkt->length + 5;	       /* type and CRC */
    pad = 8 - (len % 8);
    biglen = len + pad;

    for (i = 0; i < pad; i++)
	pkt->data[i + 4] = random_byte();
    crc = crc32_compute(pkt->data + 4, biglen - 4);
    PUT_32BIT(pkt->data + biglen, crc);
    PUT_32BIT(pkt->data, len);

    if (ssh->cipher)
	ssh->cipher->encrypt(ssh->v1_cipher_ctx, pkt->data + 4, biglen);

    return biglen + 4;
}

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

static void s_wrpkt_defer(Ssh ssh, struct Packet *pkt)
{
    int len;
    len = s_wrpkt_prepare(ssh, pkt);
    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, pkt->data, len);
    ssh->deferred_len += len;
}

/*
 * Construct a packet with the specified contents.
 */
static struct Packet *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;
    struct Packet *pkt;

    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;
	  case PKTT_PASSWORD:
	  case PKTT_DATA:
	  case PKTT_OTHER:
	    /* ignore this pass */
	    break;
	  default:
	    assert(0);
	}
    }

    pkt = s_wrpkt_start(pkttype, pktlen);
    p = pkt->body;

    while ((argtype = va_arg(ap2, int)) != PKT_END) {
	int offset = p - pkt->body, len = 0;
	switch (argtype) {
	  /* Actual fields in the packet */
	  case PKT_INT:
	    argint = va_arg(ap2, int);
	    PUT_32BIT(p, argint);
	    len = 4;
	    break;
	  case PKT_CHAR:
	    argchar = (unsigned char) va_arg(ap2, int);
	    *p = argchar;
	    len = 1;
	    break;
	  case PKT_DATA:
	    argp = va_arg(ap2, unsigned char *);
	    arglen = va_arg(ap2, int);
	    memcpy(p, argp, arglen);
	    len = arglen;
	    break;
	  case PKT_STR:
	    argp = va_arg(ap2, unsigned char *);
	    arglen = strlen((char *)argp);
	    PUT_32BIT(p, arglen);
	    memcpy(p + 4, argp, arglen);
	    len = arglen + 4;
	    break;
	  case PKT_BIGNUM:
	    bn = va_arg(ap2, Bignum);
	    len = ssh1_write_bignum(p, bn);
	    break;
	  /* Tokens for modifications to packet logging */
	  case PKTT_PASSWORD:
	    dont_log_password(ssh, pkt, PKTLOG_BLANK);
	    break;
	  case PKTT_DATA:
	    dont_log_data(ssh, pkt, PKTLOG_OMIT);
	    break;
	  case PKTT_OTHER:
	    end_log_omission(ssh, pkt);
	    break;
	}
	p += len;
	/* Deal with logfile omission, if required. */
	if (len && (pkt->logmode != PKTLOG_EMIT)) {
	    pkt->nblanks++;
	    pkt->blanks = sresize(pkt->blanks, pkt->nblanks,
				  struct logblank_t);
	    pkt->blanks[pkt->nblanks-1].offset = offset;
	    pkt->blanks[pkt->nblanks-1].len    = len;
	    pkt->blanks[pkt->nblanks-1].type   = pkt->logmode;
	}
    }

    return pkt;
}

static void send_packet(Ssh ssh, int pkttype, ...)
{
    struct Packet *pkt;
    va_list ap1, ap2;
    va_start(ap1, pkttype);
    va_start(ap2, pkttype);
    pkt = construct_packet(ssh, pkttype, ap1, ap2);
    va_end(ap2);
    va_end(ap1);
    s_wrpkt(ssh, pkt);
    ssh_free_packet(pkt);
}

static void defer_packet(Ssh ssh, int pkttype, ...)
{
    struct Packet *pkt;
    va_list ap1, ap2;
    va_start(ap1, pkttype);
    va_start(ap2, pkttype);
    pkt = construct_packet(ssh, pkttype, ap1, ap2);
    va_end(ap2);
    va_end(ap1);
    s_wrpkt_defer(ssh, pkt);
    ssh_free_packet(pkt);
}

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(struct Packet *pkt, int length)
{
    if (pkt->maxlen < length) {
	pkt->maxlen = length + 256;
	pkt->data = sresize(pkt->data, pkt->maxlen + APIEXTRA, unsigned char);
    }
}
static void ssh2_pkt_adddata(struct Packet *pkt, void *data, int len)
{
    if (pkt->logmode != PKTLOG_EMIT) {
	pkt->nblanks++;
	pkt->blanks = sresize(pkt->blanks, pkt->nblanks, struct logblank_t);
	pkt->blanks[pkt->nblanks-1].offset = pkt->length - 6;
	pkt->blanks[pkt->nblanks-1].len = len;
	pkt->blanks[pkt->nblanks-1].type = pkt->logmode;
    }
    pkt->length += len;
    ssh2_pkt_ensure(pkt, pkt->length);
    memcpy(pkt->data + pkt->length - len, data, len);
}
static void ssh2_pkt_addbyte(struct Packet *pkt, unsigned char byte)
{
    ssh2_pkt_adddata(pkt, &byte, 1);
}
static struct Packet *ssh2_pkt_init(int pkt_type)
{
    struct Packet *pkt = ssh_new_packet();
    pkt->length = 5;
    pkt->forcepad = 0;
    ssh2_pkt_addbyte(pkt, (unsigned char) pkt_type);
    return pkt;
}
static void ssh2_pkt_addbool(struct Packet *pkt, unsigned char value)
{
    ssh2_pkt_adddata(pkt, &value, 1);
}
static void ssh2_pkt_adduint32(struct Packet *pkt, unsigned long value)
{
    unsigned char x[4];
    PUT_32BIT(x, value);
    ssh2_pkt_adddata(pkt, x, 4);
}
static void ssh2_pkt_addstring_start(struct Packet *pkt)
{
    ssh2_pkt_adduint32(pkt, 0);
    pkt->savedpos = pkt->length;
}
static void ssh2_pkt_addstring_str(struct Packet *pkt, char *data)
{
    ssh2_pkt_adddata(pkt, data, strlen(data));
    PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
}
static void ssh2_pkt_addstring_data(struct Packet *pkt, char *data, int len)
{
    ssh2_pkt_adddata(pkt, data, len);
    PUT_32BIT(pkt->data + pkt->savedpos - 4, pkt->length - pkt->savedpos);
}
static void ssh2_pkt_addstring(struct Packet *pkt, char *data)
{
    ssh2_pkt_addstring_start(pkt);
    ssh2_pkt_addstring_str(pkt, 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(struct Packet *pkt, Bignum b)
{
    unsigned char *p;
    int len;
    p = ssh2_mpint_fmt(b, &len);
    ssh2_pkt_addstring_start(pkt);
    ssh2_pkt_addstring_data(pkt, (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
 * pkt->data. Total length is returned.
 */
static int ssh2_pkt_construct(Ssh ssh, struct Packet *pkt)
{
    int cipherblk, maclen, padding, i;

    /* Not used in FileZilla
    if (ssh->logctx)
	log_packet(ssh->logctx, PKT_OUTGOING, pkt->data[5],
		   ssh2_pkt_type(ssh->pkt_ctx, pkt->data[5]),
		   pkt->data + 6, pkt->length - 6,
		   pkt->nblanks, pkt->blanks);*/
    sfree(pkt->blanks); pkt->blanks = NULL;
    pkt->nblanks = 0;

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

    /*
     * Add padding. At least four bytes, and must also bring total

⌨️ 快捷键说明

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