Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/ttssh2/ttxssh/pkt.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10618 - (show annotations) (download) (as text)
Fri Mar 3 15:15:16 2023 UTC (12 months ago) by zmatsuo
File MIME type: text/x-csrc
File size: 11696 byte(s)
ttxsshで tttset.UIMsg[] ではなく TInstVar.UIMsg[] を使用するよう修正

- lng(i18n)用文字列領域
- ttxssh 以外は tttset.UIMsg[] を使用しなくなった
  - Unicode(wchar_t)版動的な文字列取得に切り替えた
  - tttset.UIMsg[] は ANSI(char) 文字列
- プラグイン用ワーク内に TInstVar.UIMsg[] を新設した
1 /*
2 * Copyright (c) 1998-2001, Robert O'Callahan
3 * (C) 2004- TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 This code is copyright (C) 1998-1999 Robert O'Callahan.
32 See LICENSE.TXT for the license.
33 */
34
35 #include "ttxssh.h"
36 #include "util.h"
37 #include "pkt.h"
38
39 #define READAMOUNT CHAN_SES_WINDOW_DEFAULT
40
41 void PKT_init(PTInstVar pvar)
42 {
43 buf_create(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);
44 pvar->pkt_state.datastart = 0;
45 pvar->pkt_state.datalen = 0;
46 pvar->pkt_state.seen_server_ID = FALSE;
47 pvar->pkt_state.seen_newline = FALSE;
48 pvar->pkt_state.predecrypted_packet = FALSE;
49 }
50
51 /* Read some data, leave no more than up_to_amount bytes in the buffer,
52 return the number of bytes read or -1 on error or blocking. */
53 static int recv_data(PTInstVar pvar, unsigned long up_to_amount)
54 {
55 int amount_read;
56
57 /* Shuffle data to the start of the buffer */
58 if (pvar->pkt_state.datastart != 0) {
59 memmove(pvar->pkt_state.buf,
60 pvar->pkt_state.buf + pvar->pkt_state.datastart,
61 pvar->pkt_state.datalen);
62 pvar->pkt_state.datastart = 0;
63 }
64
65 buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen, up_to_amount);
66
67 _ASSERT(pvar->pkt_state.buf != NULL);
68
69 amount_read = (pvar->Precv) (pvar->socket,
70 pvar->pkt_state.buf + pvar->pkt_state.datalen,
71 up_to_amount - pvar->pkt_state.datalen,
72 0);
73
74 if (amount_read > 0) {
75 /* Update seen_newline if necessary */
76 if (!pvar->pkt_state.seen_server_ID && !pvar->pkt_state.seen_newline) {
77 int i;
78
79 for (i = 0; i < amount_read; i++) {
80 if (pvar->pkt_state.buf[pvar->pkt_state.datalen + i] == '\n') {
81 pvar->pkt_state.seen_newline = 1;
82 }
83 }
84 }
85 pvar->pkt_state.datalen += amount_read;
86 }
87
88 return amount_read;
89 }
90
91 // ���s�R�[�h���o��������������
92 static int recv_line_data(PTInstVar pvar)
93 {
94 int amount_read;
95 char buf[256];
96 size_t up_to_amount = sizeof(buf);
97 int i;
98
99 /* Shuffle data to the start of the buffer */
100 if (pvar->pkt_state.datastart != 0) {
101 memmove(pvar->pkt_state.buf,
102 pvar->pkt_state.buf + pvar->pkt_state.datastart,
103 pvar->pkt_state.datalen);
104 pvar->pkt_state.datastart = 0;
105 }
106
107 buf_ensure_size(&pvar->pkt_state.buf, &pvar->pkt_state.buflen, up_to_amount);
108
109 for (i = 0 ; i < (int)up_to_amount ; i++) {
110 amount_read = (pvar->Precv) (pvar->socket, &buf[i], 1, 0);
111 if (amount_read != 1) {
112 return 0; // error
113 }
114
115 pvar->pkt_state.datalen += amount_read;
116
117 if (buf[i] == '\n') { // 0x0a
118 buf[i+1] = 0;
119 break;
120 }
121 }
122 amount_read = i + 1; // ���������T�C�Y�iLF�������j
123 memcpy(pvar->pkt_state.buf, buf, amount_read);
124
125 pvar->pkt_state.seen_newline = 1;
126
127 return amount_read;
128 }
129
130 /* This function does two things:
131 -- reads data from the sshd and feeds the SSH protocol packets to ssh.c
132 -- copies any available decrypted session data into the application buffer
133 */
134 int PKT_recv(PTInstVar pvar, char *buf, int buflen)
135 {
136 int amount_in_buf = 0;
137 BOOL connection_closed = FALSE;
138
139 while (SSH_is_any_payload(pvar) ? buflen > 0 : !connection_closed) {
140 if (SSH_is_any_payload(pvar)) {
141 /* ssh.c has some session data for us to give to Tera Term. */
142 int grabbed = SSH_extract_payload(pvar, buf, buflen);
143
144 amount_in_buf += grabbed;
145 buf += grabbed;
146 buflen -= grabbed;
147 }
148 else if (!pvar->pkt_state.seen_server_ID && (pvar->pkt_state.seen_newline || pvar->pkt_state.datalen >= 255)) {
149 /*
150 * We're looking for the initial ID string and either we've seen the
151 * terminating newline, or we've exceeded the limit at which we should see a newline.
152 */
153 unsigned int i;
154
155 for (i = 0; pvar->pkt_state.buf[i] != '\n' && i < pvar->pkt_state.datalen; i++) {
156 }
157 if (pvar->pkt_state.buf[i] == '\n') {
158 i++;
159 }
160
161 // SSH�T�[�o���o�[�W�����`�F�b�N���s��
162 if (SSH_handle_server_ID(pvar, pvar->pkt_state.buf, i)) {
163 pvar->pkt_state.seen_server_ID = 1;
164
165 if (SSHv2(pvar)) {
166 // send Key Exchange Init
167 SSH2_send_kexinit(pvar);
168 }
169 } else {
170 // reset flag to re-read server ID (2008.1.24 yutaka)
171 pvar->pkt_state.seen_newline = 0;
172 }
173
174 pvar->pkt_state.datastart += i;
175 pvar->pkt_state.datalen -= i;
176 }
177 else if (pvar->pkt_state.seen_server_ID && pvar->pkt_state.datalen >= SSH_get_min_packet_size(pvar)) {
178 char *data = pvar->pkt_state.buf + pvar->pkt_state.datastart;
179 uint32 padding_size = 0;
180 uint32 pktsize = 0;
181 uint32 total_packet_size;
182 struct Mac *mac = &pvar->ssh2_keys[MODE_IN].mac;
183 struct Enc *enc = &pvar->ssh2_keys[MODE_IN].enc;
184 int authlen = 0, aadlen = 0;
185
186 if (SSHv2(pvar)) {
187 /*
188 * pktsize
189 * uint32 packet_length
190 * ��
191 * byte padding_length
192 * byte[n1] payload; n1 = packet_length - padding_length - 1
193 * byte[n2] random padding; n2 = padding_length
194 * �����������v��
195 * byte[m] mac (Message Authentication Code - MAC); m = mac_length
196 * �����������������B
197 * cf. RFC 4253 6. Binary Packet Protocol
198 */
199
200 if (enc && enc->auth_len > 0) {
201 authlen = enc->auth_len;
202 }
203
204 /*
205 * | | lead 4 bytes are encrypted | aadlen |
206 * Encryption type
207 * enc->auth_len > 0 | AEAD | AES-GCM ... no | 4 | (2)
208 * | | chacha20-poly1305 ... yes | 4 | (1) (2)
209 * enc->auth_len == 0 | not AEAD | depends on MAC type | <- |
210 * MAC type
211 * mac->etm == true | EtM | no | 4 |
212 * mac->etm == false | E&M | yes | 0 |
213 * (1) lead 4 bytes are encrypted separately from main part.
214 * (2) implicit MAC type of AEAD is EtM
215 */
216 /*
217 * aadlen: Additional Authenticated Data Length
218 * MAC �������������f�[�^�����������������������A"MAC �������������f�[�^������"���T�C�Y
219 * ���������� packet_length ���Auint32 (4�o�C�g)
220 *
221 * - ������ MAC ���� (E&M) �����p�P�b�g������������������������������ aadlen �� 0 �������B
222 * - EtM ������ MAC �� AEAD �� AES-GCM �����A�p�P�b�g��������������������������
223 * aadlen �� 4 �������B
224 * - AEAD �� chacha20-poly1305 �����p�P�b�g�����������������������AMAC �������������f�[�^
225 * ������������������������ aadlen �� 4 �������B
226 *
227 */
228 if ((mac && mac->etm) || authlen > 0) {
229 aadlen = 4;
230 }
231
232 if (authlen > 0 &&
233 pvar->cc[MODE_IN]->cipher->id == SSH2_CIPHER_CHACHAPOLY) {
234 /*
235 * AEAD �� chacha20-poly1305 �����p�P�b�g�����������������������������B
236 * ���������������������������Adata �������������������������B
237 */
238 chachapoly_get_length(pvar->cc[MODE_IN]->cp_ctx, &pktsize,
239 pvar->ssh_state.receiver_sequence_number,
240 data, pvar->pkt_state.datalen);
241 }
242 else if (authlen == 0 &&
243 aadlen == 0 &&
244 !pvar->pkt_state.predecrypted_packet && aadlen == 0) {
245 /*
246 * AEAD ������ E&M (aadlen �� 0) �������A�����������������p�P�b�g����
247 * �m���K�v���L�������A������ 1 �u���b�N�������O�����������B
248 */
249 SSH_predecrypt_packet(pvar, data);
250 pvar->pkt_state.predecrypted_packet = TRUE;
251
252 pktsize = get_uint32_MSBfirst(data);
253 }
254 else {
255 /*
256 * EtM ������ MAC ���AAEAD �� AES-GCM ���������������������������B
257 */
258 pktsize = get_uint32_MSBfirst(data);
259 }
260 }
261 else {
262 pktsize = get_uint32_MSBfirst(data);
263 }
264
265 if (SSHv1(pvar)) {
266 // SSH1 �����p�P�b�g�����l���� padding �����������������������B
267 // ���� padding ���������������p�P�b�g���������������A�p�P�b�g�����l�����v�Z�����B
268 padding_size = 8 - (pktsize % 8);
269
270 // ���~�������� pktsize �� padding_size ���l�������������������O���������������B
271 pktsize += padding_size;
272 }
273
274 // �p�P�b�g(TCP�y�C���[�h)���S�����T�C�Y���A
275 // 4�i�p�P�b�g�����T�C�Y�j+�p�P�b�g���i+MAC���T�C�Y�j�������B
276 total_packet_size = 4 + pktsize + SSH_get_authdata_size(pvar, MODE_IN);
277
278 if (total_packet_size <= pvar->pkt_state.datalen) {
279 // ���M�����f�[�^���\���L���������p�P�b�g�����������s��
280 if (SSHv1(pvar)) {
281 // SSH1 �� EtM ������ (�������� MAC �������� CRC ���g��)
282 SSH1_handle_packet(pvar, data, pktsize, padding_size);
283 }
284 else {
285 // SSH2 �����������_���� padding ���������������������������������������A
286 // padding �����n�������A�K�v���������������������������B
287 SSH2_handle_packet(pvar, data, pktsize, aadlen, authlen);
288 }
289
290 pvar->pkt_state.predecrypted_packet = FALSE;
291 pvar->pkt_state.datastart += total_packet_size;
292 pvar->pkt_state.datalen -= total_packet_size;
293
294 }
295 else if (total_packet_size > PACKET_MAX_SIZE) {
296 // �p�P�b�g�������������������������I�������B
297 // �����������������v�����������s���p�P�b�g���������������������������B
298 UTIL_get_lang_msg("MSG_PKT_OVERSIZED_ERROR", pvar,
299 "Oversized packet received from server; connection will close.");
300 notify_fatal_error(pvar, pvar->UIMsg, TRUE);
301 }
302 else {
303 int amount_read = recv_data(pvar, max(total_packet_size, READAMOUNT));
304
305 if (amount_read == SOCKET_ERROR) {
306 if (amount_in_buf == 0) {
307 return SOCKET_ERROR;
308 } else {
309 return amount_in_buf;
310 }
311 } else {
312 if (amount_read == 0) {
313 connection_closed = TRUE;
314 }
315 }
316 }
317 } else {
318 // �p�P�b�g�����M
319 int amount_read;
320
321 amount_read = recv_data(pvar, READAMOUNT);
322
323 if (amount_read == SOCKET_ERROR) {
324 if (amount_in_buf == 0) {
325 return SOCKET_ERROR;
326 } else {
327 return amount_in_buf;
328 }
329 } else if (amount_read == 0) {
330 connection_closed = TRUE;
331 }
332 }
333
334 if (pvar->fatal_error) {
335 return amount_in_buf;
336 }
337 }
338
339 if (SSH_is_any_payload(pvar)) {
340 PostMessage(pvar->NotificationWindow, WM_USER_COMMNOTIFY, pvar->socket, MAKELPARAM(FD_READ, 0));
341 }
342
343 return amount_in_buf;
344 }
345
346 void PKT_end(PTInstVar pvar)
347 {
348 buf_destroy(&pvar->pkt_state.buf, &pvar->pkt_state.buflen);
349 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26