// 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); }
/* 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; }