Develop and Download Open Source Software

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9048 - (show annotations) (download) (as text)
Wed Dec 16 12:24:13 2020 UTC (3 years, 2 months ago) by nmaya
File MIME type: text/x-csrc
File size: 13846 byte(s)
ソースファイルの著作権表記の "最後の発行の年" を削除

ticket #40996
1 /*
2 * Copyright (C) 2004- TeraTerm Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 //
29 // buffer.c
30 //
31
32 #include <winsock2.h>
33 #include <malloc.h>
34 #include "buffer.h"
35 #include "ttxssh.h"
36 #include "util.h"
37 #include <openssl/bn.h>
38 #include <openssl/ec.h>
39 #include <zlib.h>
40
41 // �o�b�t�@���I�t�Z�b�g�����������A���������������������������B
42 // Tera Term(TTSSH)�I���W�i�������B
43 void buffer_rewind(buffer_t *buf)
44 {
45 buf->offset = 0;
46 }
47
48 void buffer_clear(buffer_t *buf)
49 {
50 buf->offset = 0;
51 buf->len = 0;
52 }
53
54 buffer_t *buffer_init(void)
55 {
56 void *ptr;
57 buffer_t *buf;
58 unsigned int size = 4096;
59
60 buf = malloc(sizeof(buffer_t));
61 ptr = malloc(size);
62 if (buf && ptr) {
63 memset(buf, 0, sizeof(buffer_t));
64 memset(ptr, 0, size);
65 buf->buf = ptr;
66 buf->maxlen = size;
67 buf->len = 0;
68 buf->offset = 0;
69
70 } else {
71 ptr = NULL; *(char *)ptr = 0;
72 }
73
74 return (buf);
75 }
76
77 void buffer_free(buffer_t * buf)
78 {
79 if (buf != NULL) {
80 // �Z�L�����e�B���� (2006.8.3 yutaka)
81 int len = buffer_len(buf);
82 SecureZeroMemory(buf->buf, len);
83 free(buf->buf);
84 free(buf);
85 }
86 }
87
88 // �o�b�t�@�������g�����s���B
89 // return: �g���O���o�b�t�@�|�C���^�[
90 void *buffer_append_space(buffer_t * buf, size_t size)
91 {
92 unsigned int n;
93 unsigned int newlen;
94 void *p;
95
96 n = buf->offset + size;
97 if (n < buf->maxlen) {
98 //
99 } else {
100 // �o�b�t�@�����������������[�����B(2005.7.2 yutaka)
101 newlen = buf->maxlen + size + BUFFER_INCREASE_MARGIN;
102 if (newlen > BUFFER_SIZE_MAX) {
103 goto panic;
104 }
105 buf->buf = realloc(buf->buf, newlen);
106 if (buf->buf == NULL)
107 goto panic;
108 buf->maxlen = newlen;
109 }
110
111 p = buf->buf + buf->offset;
112 //buf->offset += size;
113 buf->len = buf->offset + size;
114
115 return (p);
116
117 panic:
118 abort();
119 return (NULL);
120 }
121
122 int buffer_append(buffer_t * buf, char *ptr, int size)
123 {
124 unsigned int n;
125 int ret = -1;
126 unsigned int newlen;
127
128 for (;;) {
129 n = buf->offset + size;
130 if (n < buf->maxlen) {
131 memcpy(buf->buf + buf->offset, ptr, size);
132 buf->offset += size;
133 buf->len = buf->offset;
134 ret = 0;
135 break;
136
137 } else {
138 // �o�b�t�@�����������������[�����B(2005.7.2 yutaka)
139 newlen = buf->maxlen + size + BUFFER_INCREASE_MARGIN;
140 if (newlen > BUFFER_SIZE_MAX) {
141 goto panic;
142 }
143 buf->buf = realloc(buf->buf, newlen);
144 if (buf->buf == NULL)
145 goto panic;
146 buf->maxlen = newlen;
147 }
148 }
149
150 return (ret);
151
152 panic:
153 abort();
154 return (ret);
155 }
156
157 int buffer_append_length(buffer_t * msg, char *ptr, int size)
158 {
159 char buf[4];
160 int val;
161 int ret = -1;
162
163 val = htonl(size);
164 memcpy(buf, &val, sizeof(val));
165 ret = buffer_append(msg, buf, sizeof(buf));
166 if (ptr != NULL) {
167 ret = buffer_append(msg, ptr, size);
168 }
169
170 return (ret);
171 }
172
173 void buffer_put_raw(buffer_t *msg, char *ptr, int size)
174 {
175 int ret = -1;
176
177 ret = buffer_append(msg, ptr, size);
178 }
179
180 int buffer_get_ret(buffer_t *msg, void *buf, size_t len)
181 {
182 if (len > msg->len - msg->offset) {
183 // TODO: �G���[����
184 OutputDebugPrintf("buffer_get_ret: trying to get more bytes %u than in buffer %u",
185 len, msg->len - msg->offset);
186 return (-1);
187 }
188 memcpy(buf, msg->buf + msg->offset, len);
189 msg->offset += len;
190 return (0);
191 }
192
193 int buffer_get_int_ret(unsigned int *ret, buffer_t *msg)
194 {
195 unsigned char buf[4];
196
197 if (buffer_get_ret(msg, (char *) buf, 4) == -1)
198 return (-1);
199 if (ret != NULL)
200 *ret = get_uint32(buf);
201 return (0);
202 }
203
204 unsigned int buffer_get_int(buffer_t *msg)
205 {
206 unsigned int ret = 0;
207
208 if (buffer_get_int_ret(&ret, msg) == -1) {
209 // TODO: �G���[����
210 logprintf(LOG_LEVEL_ERROR, "buffer_get_int: buffer error");
211 }
212 return (ret);
213 }
214
215 int buffer_get_char_ret(char *ret, buffer_t *msg)
216 {
217 if (buffer_get_ret(msg, ret, 1) == -1)
218 return (-1);
219 return (0);
220 }
221
222 int buffer_get_char(buffer_t *msg)
223 {
224 char ch;
225
226 if (buffer_get_char_ret(&ch, msg) == -1) {
227 // TODO: �G���[����
228 OutputDebugPrintf("buffer_get_char: buffer error");
229 }
230 return (unsigned char)ch;
231 }
232
233 // getting string buffer.
234 // NOTE: You should free the return pointer if it's unused.
235 // (2005.6.26 yutaka)
236 char *buffer_get_string(char **data_ptr, int *buflen_ptr)
237 {
238 char *data = *data_ptr;
239 char *ptr;
240 unsigned int buflen;
241
242 buflen = get_uint32_MSBfirst(data);
243 data += 4;
244 // buflen == 0�����������A'\0'�����m�����Adata_ptr���i���A���^�[�������B
245 // if (buflen <= 0)
246 // return NULL;
247
248 ptr = malloc(buflen + 1);
249 if (ptr == NULL) {
250 logprintf(LOG_LEVEL_ERROR, "%s: malloc failed.", __FUNCTION__);
251 if (buflen_ptr != NULL)
252 *buflen_ptr = 0;
253 return NULL;
254 }
255 memcpy(ptr, data, buflen);
256 ptr[buflen] = '\0'; // null-terminate
257 data += buflen;
258
259 *data_ptr = data;
260 if (buflen_ptr != NULL)
261 *buflen_ptr = buflen;
262
263 return(ptr);
264 }
265
266 // buffer_get_string() �� buffer_t ���B�{������������ OpenSSH �X�^�C���B
267 // NOTE: You should free the return pointer if it's unused.
268 void *buffer_get_string_msg(buffer_t *msg, int *buflen_ptr)
269 {
270 char *data, *olddata;
271 void *ret = NULL;
272 int off;
273 int len, datalen;
274
275 // Check size
276 len = buffer_remain_len(msg);
277 if (len < 4)
278 goto error;
279
280 data = olddata = buffer_tail_ptr(msg);
281 datalen = get_uint32_MSBfirst(data);
282 if (len - 4 < datalen)
283 goto error;
284
285 ret = buffer_get_string(&data, buflen_ptr);
286 off = data - olddata;
287 msg->offset += off;
288
289 error:;
290 return (ret);
291 }
292
293 void buffer_put_string(buffer_t *msg, char *ptr, int size)
294 {
295 char buf[4];
296 int val;
297 int ret = -1;
298
299 // �u�T�C�Y�{�������v�����������B�T�C�Y��4byte��big-endian�B
300 val = htonl(size);
301 memcpy(buf, &val, sizeof(val));
302 ret = buffer_append(msg, buf, sizeof(buf));
303 if (ptr != NULL) {
304 ret = buffer_append(msg, ptr, size);
305 }
306 }
307
308 void buffer_put_cstring(buffer_t *msg, char *ptr)
309 {
310 buffer_put_string(msg, ptr, strlen(ptr));
311 }
312
313 void buffer_put_char(buffer_t *msg, int value)
314 {
315 char ch = value;
316
317 buffer_append(msg, &ch, 1);
318 }
319
320 void buffer_put_padding(buffer_t *msg, int size)
321 {
322 char ch = ' ';
323 int i;
324
325 for (i = 0 ; i < size ; i++) {
326 buffer_append(msg, &ch, 1);
327 }
328 }
329
330 void buffer_put_int(buffer_t *msg, int value)
331 {
332 char buf[4];
333
334 set_uint32_MSBfirst(buf, value);
335 buffer_append(msg, buf, sizeof(buf));
336 }
337
338 int buffer_len(buffer_t *msg)
339 {
340 return (msg->len);
341 }
342
343 // ���������������������c�����T�C�Y�������B�{������������ OpenSSH �X�^�C���B
344 int buffer_remain_len(buffer_t *msg)
345 {
346 return (msg->len - msg->offset);
347 }
348
349 // buffer_append() �� buffer_append_space() �����b�Z�[�W�o�b�t�@���������s�����A
350 // ������ realloc() �������o�b�t�@�|�C���^���������������������������B
351 // ���b�Z�[�W�o�b�t�@���|�C���^���������������A�o�b�t�@������������������
352 // �s�����������ABOF���������B
353 char *buffer_ptr(buffer_t *msg)
354 {
355 return (msg->buf);
356 }
357
358 char *buffer_tail_ptr(buffer_t *msg)
359 {
360 return (char *)(msg->buf + msg->offset);
361 }
362
363 int buffer_overflow_verify(buffer_t *msg, int len)
364 {
365 if (msg->offset + len > msg->maxlen) {
366 return -1; // error
367 }
368 return 0; // no problem
369 }
370
371 // for SSH1
372 void buffer_put_bignum(buffer_t *buffer, BIGNUM *value)
373 {
374 unsigned int bits, bin_size;
375 unsigned char *buf;
376 int oi;
377 char msg[2];
378
379 bits = BN_num_bits(value);
380 bin_size = (bits + 7) / 8;
381 buf = malloc(bin_size);
382 if (buf == NULL) {
383 *buf = 0;
384 goto error;
385 }
386
387 buf[0] = '\0';
388 /* Get the value of in binary */
389 oi = BN_bn2bin(value, buf);
390 if (oi != bin_size) {
391 goto error;
392 }
393
394 /* Store the number of bits in the buffer in two bytes, msb first. */
395 set_ushort16_MSBfirst(msg, bits);
396 buffer_append(buffer, msg, 2);
397
398 /* Store the binary data. */
399 buffer_append(buffer, (char *)buf, oi);
400
401 error:
402 free(buf);
403 }
404
405 // for SSH2
406 void buffer_put_bignum2(buffer_t *msg, BIGNUM *value)
407 {
408 unsigned int bytes;
409 unsigned char *buf;
410 int oi;
411 unsigned int hasnohigh = 0;
412
413 bytes = BN_num_bytes(value) + 1; /* extra padding byte */
414 buf = malloc(bytes);
415 if (buf == NULL) {
416 *buf = 0;
417 goto error;
418 }
419
420 buf[0] = '\0';
421 /* Get the value of in binary */
422 oi = BN_bn2bin(value, buf+1);
423 hasnohigh = (buf[1] & 0x80) ? 0 : 1;
424 buffer_put_string(msg, buf+hasnohigh, bytes-hasnohigh);
425 //memset(buf, 0, bytes);
426
427 error:
428 free(buf);
429 }
430
431 void buffer_get_bignum2(char **data, BIGNUM *value)
432 {
433 char *buf = *data;
434 int len;
435
436 len = get_uint32_MSBfirst(buf);
437 buf += 4;
438 BN_bin2bn(buf, len, value);
439 buf += len;
440
441 *data = buf;
442 }
443
444 void buffer_get_bignum2_msg(buffer_t *msg, BIGNUM *value)
445 {
446 char *data, *olddata;
447 int off;
448
449 data = olddata = buffer_tail_ptr(msg);
450 buffer_get_bignum2(&data, value);
451 off = data - olddata;
452 msg->offset += off;
453 }
454
455 void buffer_get_bignum_SECSH(buffer_t *buffer, BIGNUM *value)
456 {
457 char *buf;
458 unsigned int bits, bytes;
459
460 bits = buffer_get_int(buffer);
461 bytes = (bits + 7) / 8;
462
463 if ((buffer->len - buffer->offset) < bytes) {
464 return;
465 }
466 buf = buffer->buf + buffer->offset;
467 if ((*buf & 0x80) != 0) {
468 char *tmp = (char *)malloc(bytes + 1);
469 tmp[0] = '\0';
470 memcpy(tmp + 1, buf, bytes);
471 BN_bin2bn(tmp, bytes + 1, value);
472 free(tmp);
473 }
474 else {
475 BN_bin2bn(buf, bytes, value);
476 }
477
478 buffer->offset += bytes;
479 }
480
481 void buffer_put_ecpoint(buffer_t *msg, const EC_GROUP *curve, const EC_POINT *point)
482 {
483 unsigned char *buf = NULL;
484 size_t len;
485 BN_CTX *bnctx;
486
487 /* Determine length */
488 bnctx = BN_CTX_new();
489 len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
490 NULL, 0, bnctx);
491 /* Convert */
492 buf = malloc(len);
493 if (buf == NULL) {
494 *buf = 0;
495 goto error;
496 }
497 if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
498 buf, len, bnctx) != len) {
499 goto error;
500 }
501 /* Append */
502 buffer_put_string(msg, buf, len);
503
504 error:
505 free(buf);
506 BN_CTX_free(bnctx);
507 }
508
509 void buffer_get_ecpoint(char **data, const EC_GROUP *curve, EC_POINT *point)
510 {
511 char *buf = *data;
512 size_t len;
513 BN_CTX *bnctx;
514
515 bnctx = BN_CTX_new();
516
517 len = get_uint32_MSBfirst(buf);
518 buf += 4;
519 EC_POINT_oct2point(curve, point, buf, len, bnctx);
520 buf += len;
521
522 *data = buf;
523
524 BN_CTX_free(bnctx);
525 }
526
527 void buffer_get_ecpoint_msg(buffer_t *msg, const EC_GROUP *curve, EC_POINT *point)
528 {
529 char *data, *olddata;
530 int off;
531
532 data = olddata = buffer_tail_ptr(msg);
533 buffer_get_ecpoint(&data, curve, point);
534 off = data - olddata;
535 msg->offset += off;
536 }
537
538 void buffer_dump(FILE *fp, buffer_t *buf)
539 {
540 int i;
541 char *ch = buffer_ptr(buf);
542
543 for (i = 0 ; i < buffer_len(buf) ; i++) {
544 fprintf(fp, "%02x", ch[i] & 0xff);
545 if (i % 16 == 15)
546 fprintf(fp, "\n");
547 else if (i % 2 == 1)
548 fprintf(fp, " ");
549 }
550 fprintf(fp, "\n");
551 }
552
553 // �o�b�t�@���I�t�Z�b�g���i�����B
554 void buffer_consume(buffer_t *buf, size_t shift_byte)
555 {
556 if (shift_byte > buf->len - buf->offset) {
557 // TODO: fatal error
558 } else {
559 buf->offset += shift_byte;
560 // len�����������B
561 }
562 }
563
564 // �o�b�t�@���������k�������B
565 void buffer_consume_end(buffer_t *buf, size_t shift_byte)
566 {
567 if (shift_byte > buf->len - buf->offset) {
568 // TODO: fatal error
569 } else {
570 buf->len -= shift_byte;
571 // offset�����������B
572 }
573 }
574
575
576 // �p�P�b�g�����k
577 int buffer_compress(z_stream *zstream, char *payload, int len, buffer_t *compbuf)
578 {
579 unsigned char buf[4096];
580 int status;
581
582 // input buffer
583 zstream->next_in = payload;
584 zstream->avail_in = len;
585
586 do {
587 // output buffer
588 zstream->next_out = buf;
589 zstream->avail_out = sizeof(buf);
590
591 // �o�b�t�@�����k�����B���k�������A�t���T�C�Y�������������������l�����������B
592 status = deflate(zstream, Z_PARTIAL_FLUSH);
593 if (status == Z_OK) {
594 buffer_append(compbuf, buf, sizeof(buf) - zstream->avail_out);
595 } else {
596 return -1; // error
597 }
598 } while (zstream->avail_out == 0);
599
600 return 0; // success
601 }
602
603 // �p�P�b�g���W�J
604 int buffer_decompress(z_stream *zstream, char *payload, int len, buffer_t *compbuf)
605 {
606 unsigned char buf[4096];
607 int status;
608
609 // input buffer
610 zstream->next_in = payload;
611 zstream->avail_in = len;
612
613 do {
614 // output buffer
615 zstream->next_out = buf;
616 zstream->avail_out = sizeof(buf);
617
618 // �o�b�t�@���W�J�����B
619 status = inflate(zstream, Z_PARTIAL_FLUSH);
620 if (status == Z_OK) {
621 buffer_append(compbuf, buf, sizeof(buf) - zstream->avail_out);
622
623 } else if (status == Z_OK) {
624 break;
625
626 } else {
627 return -1; // error
628 }
629 } while (zstream->avail_out == 0);
630
631 return 0; // success
632 }

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