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

📄 ssh.c

📁 远程登陆工具软件源码 用于远程登陆unix
💻 C
📖 第 1 页 / 共 5 页
字号:
	    crReturn(st->to_read);
	if (st->chunk > (*datalen))
	    st->chunk = (*datalen);
	memcpy(st->p, *data, st->chunk);
	*data += st->chunk;
	*datalen -= st->chunk;
	st->p += st->chunk;
	st->to_read -= st->chunk;
    }

    if (ssh->cipher && detect_attack(ssh->crcda_ctx, ssh->pktin.data,
				     st->biglen, NULL)) {
        bombout(("Network attack (CRC compensation) detected!"));
        crStop(0);
    }

    if (ssh->cipher)
	ssh->cipher->decrypt(ssh->v1_cipher_ctx, ssh->pktin.data, st->biglen);

    st->realcrc = crc32_compute(ssh->pktin.data, st->biglen - 4);
    st->gotcrc = GET_32BIT(ssh->pktin.data + st->biglen - 4);
    if (st->gotcrc != st->realcrc) {
	bombout(("Incorrect CRC received on packet"));
	crStop(0);
    }

    ssh->pktin.body = ssh->pktin.data + st->pad + 1;
    ssh->pktin.savedpos = 0;

    if (ssh->v1_compressing) {
	unsigned char *decompblk;
	int decomplen;
	if (!zlib_decompress_block(ssh->sc_comp_ctx,
				   ssh->pktin.body - 1, ssh->pktin.length + 1,
				   &decompblk, &decomplen)) {
	    bombout(("Zlib decompression encountered invalid data"));
	    crStop(0);
	}

	if (ssh->pktin.maxlen < st->pad + decomplen) {
	    ssh->pktin.maxlen = st->pad + decomplen;
	    ssh->pktin.data = sresize(ssh->pktin.data,
				      ssh->pktin.maxlen + APIEXTRA,
				      unsigned char);
	    ssh->pktin.body = ssh->pktin.data + st->pad + 1;
	}

	memcpy(ssh->pktin.body - 1, decompblk, decomplen);
	sfree(decompblk);
	ssh->pktin.length = decomplen - 1;
    }

    ssh->pktin.type = ssh->pktin.body[-1];

    if (ssh->logctx)
	log_packet(ssh->logctx,
		   PKT_INCOMING, ssh->pktin.type,
		   ssh1_pkt_type(ssh->pktin.type),
		   ssh->pktin.body, ssh->pktin.length);

    if (ssh->pktin.type == SSH1_SMSG_STDOUT_DATA ||
	ssh->pktin.type == SSH1_SMSG_STDERR_DATA ||
	ssh->pktin.type == SSH1_MSG_DEBUG ||
	ssh->pktin.type == SSH1_SMSG_AUTH_TIS_CHALLENGE ||
	ssh->pktin.type == SSH1_SMSG_AUTH_CCARD_CHALLENGE) {
	long stringlen = GET_32BIT(ssh->pktin.body);
	if (stringlen + 4 != ssh->pktin.length) {
	    bombout(("Received data packet with bogus string length"));
	    crStop(0);
	}
    }

    if (ssh->pktin.type == SSH1_MSG_DEBUG) {
	/* log debug message */
	char buf[512];
	int stringlen = GET_32BIT(ssh->pktin.body);
	strcpy(buf, "Remote debug message: ");
	if (stringlen > 480)
	    stringlen = 480;
	memcpy(buf + 8, ssh->pktin.body + 4, stringlen);
	buf[8 + stringlen] = '\0';
	logevent(buf);
	goto next_packet;
    } else if (ssh->pktin.type == SSH1_MSG_IGNORE) {
	/* do nothing */
	goto next_packet;
    }

    if (ssh->pktin.type == SSH1_MSG_DISCONNECT) {
	/* log reason code in disconnect message */
	char buf[256];
	unsigned msglen = GET_32BIT(ssh->pktin.body);
	unsigned nowlen;
	strcpy(buf, "Remote sent disconnect: ");
	nowlen = strlen(buf);
	if (msglen > sizeof(buf) - nowlen - 1)
	    msglen = sizeof(buf) - nowlen - 1;
	memcpy(buf + nowlen, ssh->pktin.body + 4, msglen);
	buf[nowlen + msglen] = '\0';
	/* logevent(buf); (this is now done within the bombout macro) */
	bombout(("Server sent disconnect message:\n\"%s\"", buf+nowlen));
	crStop(0);
    }

    crFinish(0);
}

static int ssh2_rdpkt(Ssh ssh, unsigned char **data, int *datalen)
{
    struct rdpkt2_state_tag *st = &ssh->rdpkt2_state;

    crBegin(ssh->ssh2_rdpkt_crstate);

  next_packet:
    ssh->pktin.type = 0;
    ssh->pktin.length = 0;
    if (ssh->sccipher)
	st->cipherblk = ssh->sccipher->blksize;
    else
	st->cipherblk = 8;
    if (st->cipherblk < 8)
	st->cipherblk = 8;

    if (ssh->pktin.maxlen < st->cipherblk) {
	ssh->pktin.maxlen = st->cipherblk;
	ssh->pktin.data = sresize(ssh->pktin.data, st->cipherblk + APIEXTRA,
				  unsigned char);
    }

    /*
     * Acquire and decrypt the first block of the packet. This will
     * contain the length and padding details.
     */
    for (st->i = st->len = 0; st->i < st->cipherblk; st->i++) {
	while ((*datalen) == 0)
	    crReturn(st->cipherblk - st->i);
	ssh->pktin.data[st->i] = *(*data)++;
	(*datalen)--;
    }

    if (ssh->sccipher)
	ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
			       ssh->pktin.data, st->cipherblk);

    /*
     * Now get the length and padding figures.
     */
    st->len = GET_32BIT(ssh->pktin.data);
    st->pad = ssh->pktin.data[4];

    /*
     * _Completely_ silly lengths should be stomped on before they
     * do us any more damage.
     */
    if (st->len < 0 || st->pad < 0 || st->len + st->pad < 0) {
	bombout(("Incoming packet was garbled on decryption"));
	crStop(0);
    }

    /*
     * This enables us to deduce the payload length.
     */
    st->payload = st->len - st->pad - 1;

    ssh->pktin.length = st->payload + 5;

    /*
     * So now we can work out the total packet length.
     */
    st->packetlen = st->len + 4;
    st->maclen = ssh->scmac ? ssh->scmac->len : 0;

    /*
     * Adjust memory allocation if packet is too big.
     */
    if (ssh->pktin.maxlen < st->packetlen + st->maclen) {
	ssh->pktin.maxlen = st->packetlen + st->maclen;
	ssh->pktin.data = sresize(ssh->pktin.data,
				  ssh->pktin.maxlen + APIEXTRA,
				  unsigned char);
    }

    /*
     * Read and decrypt the remainder of the packet.
     */
    for (st->i = st->cipherblk; st->i < st->packetlen + st->maclen;
	 st->i++) {
	while ((*datalen) == 0)
	    crReturn(st->packetlen + st->maclen - st->i);
	ssh->pktin.data[st->i] = *(*data)++;
	(*datalen)--;
    }
    /* Decrypt everything _except_ the MAC. */
    if (ssh->sccipher)
	ssh->sccipher->decrypt(ssh->sc_cipher_ctx,
			       ssh->pktin.data + st->cipherblk,
			       st->packetlen - st->cipherblk);

    /*
     * Check the MAC.
     */
    if (ssh->scmac
	&& !ssh->scmac->verify(ssh->sc_mac_ctx, ssh->pktin.data, st->len + 4,
			       st->incoming_sequence)) {
	bombout(("Incorrect MAC received on packet"));
	crStop(0);
    }
    st->incoming_sequence++;	       /* whether or not we MACed */

    /*
     * Decompress packet payload.
     */
    {
	unsigned char *newpayload;
	int newlen;
	if (ssh->sccomp &&
	    ssh->sccomp->decompress(ssh->sc_comp_ctx,
				    ssh->pktin.data + 5, ssh->pktin.length - 5,
				    &newpayload, &newlen)) {
	    if (ssh->pktin.maxlen < newlen + 5) {
		ssh->pktin.maxlen = newlen + 5;
		ssh->pktin.data = sresize(ssh->pktin.data,
					  ssh->pktin.maxlen + APIEXTRA,
					  unsigned char);
	    }
	    ssh->pktin.length = 5 + newlen;
	    memcpy(ssh->pktin.data + 5, newpayload, newlen);
	    sfree(newpayload);
	}
    }

    ssh->pktin.savedpos = 6;
    ssh->pktin.body = ssh->pktin.data;
    ssh->pktin.type = ssh->pktin.data[5];

    if (ssh->logctx)
	log_packet(ssh->logctx, PKT_INCOMING, ssh->pktin.type,
		   ssh2_pkt_type(ssh->pkt_ctx, ssh->pktin.type),
		   ssh->pktin.data+6, ssh->pktin.length-6);

    switch (ssh->pktin.type) {
        /*
         * These packets we must handle instantly.
         */
      case SSH2_MSG_DISCONNECT:
        {
            /* log reason code in disconnect message */
            char *buf;
	    int nowlen;
            int reason = GET_32BIT(ssh->pktin.data + 6);
            unsigned msglen = GET_32BIT(ssh->pktin.data + 10);

            if (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) {
                buf = dupprintf("Received disconnect message (%s)",
				ssh2_disconnect_reasons[reason]);
            } else {
                buf = dupprintf("Received disconnect message (unknown"
				" type %d)", reason);
            }
            logevent(buf);
	    sfree(buf);
            buf = dupprintf("Disconnection message text: %n%.*s",
			    &nowlen, msglen, ssh->pktin.data + 14);
            logevent(buf);
            bombout(("Server sent disconnect message\ntype %d (%s):\n\"%s\"",
                     reason,
                     (reason > 0 && reason < lenof(ssh2_disconnect_reasons)) ?
                     ssh2_disconnect_reasons[reason] : "unknown",
                     buf+nowlen));
	    sfree(buf);
            crStop(0);
        }
        break;
      case SSH2_MSG_IGNORE:
	goto next_packet;
      case SSH2_MSG_DEBUG:
	{
	    /* log the debug message */
	    char buf[512];
	    /* int display = ssh->pktin.body[6]; */
	    int stringlen = GET_32BIT(ssh->pktin.data+7);
	    int prefix;
	    strcpy(buf, "Remote debug message: ");
	    prefix = strlen(buf);
	    if (stringlen > (int)(sizeof(buf)-prefix-1))
		stringlen = sizeof(buf)-prefix-1;
	    memcpy(buf + prefix, ssh->pktin.data + 11, stringlen);
	    buf[prefix + stringlen] = '\0';
	    logevent(buf);
	}
        goto next_packet;              /* FIXME: print the debug message */

        /*
         * These packets we need do nothing about here.
         */
      case SSH2_MSG_UNIMPLEMENTED:
      case SSH2_MSG_SERVICE_REQUEST:
      case SSH2_MSG_SERVICE_ACCEPT:
      case SSH2_MSG_KEXINIT:
      case SSH2_MSG_NEWKEYS:
      case SSH2_MSG_KEXDH_INIT:
      case SSH2_MSG_KEXDH_REPLY:
      /* case SSH2_MSG_KEX_DH_GEX_REQUEST: duplicate case value */
      /* case SSH2_MSG_KEX_DH_GEX_GROUP: duplicate case value */
      case SSH2_MSG_KEX_DH_GEX_INIT:
      case SSH2_MSG_KEX_DH_GEX_REPLY:
      case SSH2_MSG_USERAUTH_REQUEST:
      case SSH2_MSG_USERAUTH_FAILURE:
      case SSH2_MSG_USERAUTH_SUCCESS:
      case SSH2_MSG_USERAUTH_BANNER:
      case SSH2_MSG_USERAUTH_PK_OK:
      /* case SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: duplicate case value */
      /* case SSH2_MSG_USERAUTH_INFO_REQUEST: duplicate case value */
      case SSH2_MSG_USERAUTH_INFO_RESPONSE:
      case SSH2_MSG_GLOBAL_REQUEST:
      case SSH2_MSG_REQUEST_SUCCESS:
      case SSH2_MSG_REQUEST_FAILURE:
      case SSH2_MSG_CHANNEL_OPEN:
      case SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
      case SSH2_MSG_CHANNEL_OPEN_FAILURE:
      case SSH2_MSG_CHANNEL_WINDOW_ADJUST:
      case SSH2_MSG_CHANNEL_DATA:
      case SSH2_MSG_CHANNEL_EXTENDED_DATA:
      case SSH2_MSG_CHANNEL_EOF:
      case SSH2_MSG_CHANNEL_CLOSE:
      case SSH2_MSG_CHANNEL_REQUEST:
      case SSH2_MSG_CHANNEL_SUCCESS:
      case SSH2_MSG_CHANNEL_FAILURE:
        break;

        /*
         * For anything else we send SSH2_MSG_UNIMPLEMENTED.
         */
      default:
	ssh2_pkt_init(ssh, SSH2_MSG_UNIMPLEMENTED);
	ssh2_pkt_adduint32(ssh, st->incoming_sequence - 1);
	ssh2_pkt_send(ssh);
        break;
    }

    crFinish(0);
}

static void ssh1_pktout_size(Ssh ssh, int len)
{
    int pad, biglen;

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

    ssh->pktout.length = len - 5;
    if (ssh->pktout.maxlen < biglen) {
	ssh->pktout.maxlen = biglen;
#ifdef MSCRYPTOAPI
	/* Allocate enough buffer space for extra block
	 * for MS CryptEncrypt() */
	ssh->pktout.data = sresize(ssh->pktout.data, biglen + 12,
				   unsigned char);
#else
	ssh->pktout.data = sresize(ssh->pktout.data, biglen + 4,
				   unsigned char);
#endif
    }
    ssh->pktout.body = ssh->pktout.data + 4 + pad + 1;
}

static void s_wrpkt_start(Ssh ssh, int type, int len)
{
    ssh1_pktout_size(ssh, len);
    ssh->pktout.type = type;
}

static int s_wrpkt_prepare(Ssh ssh)
{
    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;

    ssh->pktout.body[-1] = ssh->pktout.type;

    if (ssh->logctx)
	log_packet(ssh->logctx, PKT_OUTGOING, ssh->pktout.type,
		   ssh1_pkt_type(ssh->pktout.type),
		   ssh->pktout.body, ssh->pktout.length);

    if (ssh->v1_compressing) {
	unsigned char *compblk;
	int complen;
	zlib_compress_block(ssh->cs_comp_ctx,
			    ssh->pktout.body - 1, ssh->pktout.length + 1,
			    &compblk, &complen);
	ssh1_pktout_size(ssh, complen - 1);
	memcpy(ssh->pktout.body - 1, compblk, complen);
	sfree(compblk);
    }

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

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

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

    return biglen + 4;

⌨️ 快捷键说明

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