📄 ssh.c
字号:
static int ssh1_rdpkt(Ssh ssh, unsigned char **data, int *datalen){ struct rdpkt1_state_tag *st = &ssh->rdpkt1_state; crBegin(ssh->ssh1_rdpkt_crstate); next_packet: ssh->pktin.type = 0; ssh->pktin.length = 0; for (st->i = st->len = 0; st->i < 4; st->i++) { while ((*datalen) == 0) crReturn(4 - st->i); st->len = (st->len << 8) + **data; (*data)++, (*datalen)--; } st->pad = 8 - (st->len % 8); st->biglen = st->len + st->pad; ssh->pktin.length = st->len - 5; if (st->biglen < 0) { bombout(("Extremely large packet length from server suggests" " data stream corruption")); crStop(0); } if (ssh->pktin.maxlen < st->biglen) { ssh->pktin.maxlen = st->biglen; ssh->pktin.data = sresize(ssh->pktin.data, st->biglen + APIEXTRA, unsigned char); } st->to_read = st->biglen; st->p = ssh->pktin.data; while (st->to_read > 0) { st->chunk = st->to_read; while ((*datalen) == 0) 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]; /* * Log incoming packet, possibly omitting sensitive fields. */ if (ssh->logctx) { int nblanks = 0; struct logblank_t blank; if (ssh->cfg.logomitdata) { int do_blank = FALSE, blank_prefix = 0; /* "Session data" packets - omit the data field */ if ((ssh->pktin.type == SSH1_SMSG_STDOUT_DATA) || (ssh->pktin.type == SSH1_SMSG_STDERR_DATA)) { do_blank = TRUE; blank_prefix = 0; } else if (ssh->pktin.type == SSH1_MSG_CHANNEL_DATA) { do_blank = TRUE; blank_prefix = 4; } if (do_blank) { blank.offset = blank_prefix; blank.len = ssh->pktin.length; blank.type = PKTLOG_OMIT; nblanks = 1; } } log_packet(ssh->logctx, PKT_INCOMING, ssh->pktin.type, ssh1_pkt_type(ssh->pktin.type), ssh->pktin.body, ssh->pktin.length, nblanks, &blank); } 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) { char *buf, *msg; int msglen; ssh_pkt_getstring(ssh, &msg, &msglen); buf = dupprintf("Remote debug message: %.*s", msglen, msg); logevent(buf); sfree(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 *msg; int msglen; ssh_pkt_getstring(ssh, &msg, &msglen); bombout(("Server sent disconnect message:\n\"%.*s\"", msglen, msg)); 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]; /* * Log incoming packet, possibly omitting sensitive fields. */ if (ssh->logctx) { int nblanks = 0; struct logblank_t blank; if (ssh->cfg.logomitdata) { int do_blank = FALSE, blank_prefix = 0; /* "Session data" packets - omit the data field */ if (ssh->pktin.type == SSH2_MSG_CHANNEL_DATA) { do_blank = TRUE; blank_prefix = 4; } else if (ssh->pktin.type == SSH2_MSG_CHANNEL_EXTENDED_DATA) { do_blank = TRUE; blank_prefix = 8; } if (do_blank) { blank.offset = blank_prefix; blank.len = (ssh->pktin.length-6) - blank_prefix; blank.type = PKTLOG_OMIT; nblanks = 1; } } 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, nblanks, &blank); } switch (ssh->pktin.type) { /* * These packets we must handle instantly. */ case SSH2_MSG_DISCONNECT: { /* log reason code in disconnect message */ char *buf, *msg; int nowlen, reason, msglen; reason = ssh_pkt_getuint32(ssh); ssh_pkt_getstring(ssh, &msg, &msglen); 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, msg); 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, *msg; int msglen; int always_display; /* XXX maybe we should actually take notice of this */ always_display = ssh2_pkt_getbool(ssh); ssh_pkt_getstring(ssh, &msg, &msglen); buf = dupprintf("Remote debug message: %.*s", msglen, msg); logevent(buf); sfree(buf); } goto next_packet; /* * 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -