Ejemplo n.º 1
0
// DH鍵を生成する
void dh_gen_key(PTInstVar pvar, DH *dh, int we_need /* bytes */ )
{
	int i;

	dh->priv_key = NULL;

	// 秘密にすべき乱数(X)を生成
	for (i = 0 ; i < 10 ; i++) { // retry counter
		if (dh->priv_key != NULL) {
			BN_clear_free(dh->priv_key);
		}
		dh->priv_key = BN_new();
		if (dh->priv_key == NULL)
			goto error;
		if (BN_rand(dh->priv_key, 2*(we_need*8), 0, 0) == 0)
			goto error;
		if (DH_generate_key(dh) == 0)
			goto error;
		if (dh_pub_is_valid(dh, dh->pub_key))
			break;
	}
	if (i >= 10) {
		goto error;
	}
	return;

error:;
	notify_fatal_error(pvar, "error occurred @ dh_gen_key()", TRUE);

}
Ejemplo n.º 2
0
/* This function does two things:
   -- reads data from the sshd and feeds the SSH protocol packets to ssh.c
   -- copies any available decrypted session data into the application buffer
*/
int PKT_recv(PTInstVar pvar, char FAR * buf, int buflen)
{
	int amount_in_buf = 0;
	BOOL connection_closed = FALSE;

	while (SSH_is_any_payload(pvar) ? buflen > 0 : !connection_closed) {
		if (SSH_is_any_payload(pvar)) {
			/* ssh.c has some session data for us to give to Tera Term. */
			int grabbed = SSH_extract_payload(pvar, buf, buflen);

			amount_in_buf += grabbed;
			buf += grabbed;
			buflen -= grabbed;

		} else if (!pvar->pkt_state.seen_server_ID &&
		           (pvar->pkt_state.seen_newline
		            || pvar->pkt_state.datalen >= 255)) {
			/* We're looking for the initial ID string and either we've seen the
			   terminating newline, or we've exceeded the limit at which we should see
			   a newline. */
			unsigned int i;

			for (i = 0;
			     pvar->pkt_state.buf[i] != '\n'
			     && i < pvar->pkt_state.datalen; i++) {
			}
			if (pvar->pkt_state.buf[i] == '\n') {
				i++;
			}

			// SSHサーバのバージョンチェックを行う
			if (SSH_handle_server_ID(pvar, pvar->pkt_state.buf, i)) {
				pvar->pkt_state.seen_server_ID = 1;

				if (SSHv1(pvar)) {

				} else { // for SSH2(yutaka)
					// send Key Exchange Init
					SSH2_send_kexinit(pvar);
				}

			} else {
				// reset flag to re-read server ID (2008.1.24 yutaka)
				pvar->pkt_state.seen_newline = 0;

			}

			pvar->pkt_state.datastart += i;
			pvar->pkt_state.datalen -= i;

		} else if (pvar->pkt_state.seen_server_ID
		           && pvar->pkt_state.datalen >=
		           (unsigned int) SSH_get_min_packet_size(pvar)) {
			char FAR *data =
				pvar->pkt_state.buf + pvar->pkt_state.datastart;
			uint32 padding;
			uint32 pktsize;
			uint32 total_packet_size;

			//debug_print(10, data, pvar->pkt_state.datalen);

			// SSH2なら暗号化パケットの一部を復号化する。
			if (!pvar->pkt_state.predecrypted_packet) {
				//DEBUG_PRINT_TO_FILE(0, data, pvar->pkt_state.datalen);
				SSH_predecrpyt_packet(pvar, data);

				if (SSHv1(pvar)) {
					pvar->pkt_state.predecrypted_packet = TRUE;
				} else { // for SSH2(yutaka)
					// do nothing
					pvar->pkt_state.predecrypted_packet = TRUE;
				}
			}

			if (SSHv1(pvar)) {
				uint32 realpktsize = get_uint32_MSBfirst(data);

				padding = 8 - (realpktsize % 8);
				pktsize = realpktsize + padding;
			} else {
				// SSH2のパケットは先頭に packet-size(4)+padding(1)+type(1) が続く。
				pktsize = get_uint32_MSBfirst(data);
				padding = (unsigned char) data[4];
			}

			// パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。
			// +4は、SSHペイロードのサイズを格納している部分(int型)。
			total_packet_size = pktsize + 4 + SSH_get_clear_MAC_size(pvar);

			if (total_packet_size <= pvar->pkt_state.datalen) {
				/* the data must be 4 byte aligned. */
				SSH_handle_packet(pvar, data, pktsize, padding);
				pvar->pkt_state.predecrypted_packet = FALSE;

				pvar->pkt_state.datastart += total_packet_size;
				pvar->pkt_state.datalen -= total_packet_size;

			} else if (total_packet_size > PACKET_MAX_SIZE) {
				// 4MBを超える巨大なパケットが届いたら、異常終了する。
				// 実際にはデータ化けで復号失敗時に、誤認識することが多い。
				UTIL_get_lang_msg("MSG_PKT_OVERSIZED_ERROR", pvar,
				                  "Oversized packet received from server; connection will close.");
				notify_fatal_error(pvar, pvar->ts->UIMsg, TRUE);
			} else {
				int amount_read =
					recv_data(pvar, max(total_packet_size, READAMOUNT));

				if (amount_read == SOCKET_ERROR) {
					if (amount_in_buf == 0) {
						return SOCKET_ERROR;
					} else {
						return amount_in_buf;
					}
				} else {
					if (amount_read == 0) {
						connection_closed = TRUE;
					}
				}
			}


		} else {
			// パケットの受信(最大60KB)
			int amount_read;

			if (pvar->pkt_state.seen_server_ID == 0) {
				//amount_read = recv_line_data(pvar);
				amount_read = recv_data(pvar, READAMOUNT);

			} else {
				amount_read = recv_data(pvar, READAMOUNT);

			}

			if (amount_read == SOCKET_ERROR) {
				if (amount_in_buf == 0) {
					return SOCKET_ERROR;
				} else {
					return amount_in_buf;
				}
			} else if (amount_read == 0) {
				connection_closed = TRUE;
			}
		}

		if (pvar->fatal_error) {
			return amount_in_buf;
		}
	}

	if (SSH_is_any_payload(pvar)) {
		PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY,
		            pvar->socket, MAKELPARAM(FD_READ, 0));
	}

	return amount_in_buf;
}