Open-Source-Software-Entwicklung und Downloads

Browse Subversion Repository

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3003 - (show annotations) (download) (as text)
Mon Aug 20 14:21:57 2007 UTC (16 years, 9 months ago) by maya
Original Path: ttssh2/trunk/ttxssh/buffer.c
File MIME type: text/x-csrc
File size: 6416 byte(s)
インデントを変更した。

1 //
2 // buffer.c
3 //
4
5 #include <winsock2.h>
6 #include <malloc.h>
7 #include "buffer.h"
8 #include "ttxssh.h"
9 #include "util.h"
10 #include <openssl/bn.h>
11 #include <zlib.h>
12
13 void buffer_clear(buffer_t *buf)
14 {
15 buf->offset = 0;
16 buf->len = 0;
17 }
18
19 buffer_t *buffer_init(void)
20 {
21 void *ptr;
22 buffer_t *buf;
23 int size = 4096;
24
25 buf = malloc(sizeof(buffer_t));
26 ptr = malloc(size);
27 if (buf && ptr) {
28 memset(buf, 0, sizeof(buffer_t));
29 memset(ptr, 0, size);
30 buf->buf = ptr;
31 buf->maxlen = size;
32 buf->len = 0;
33 buf->offset = 0;
34
35 } else {
36 ptr = NULL; *(char *)ptr = 0;
37 }
38
39 return (buf);
40 }
41
42 void buffer_free(buffer_t * buf)
43 {
44 if (buf != NULL) {
45 // セキュリティ対策 (2006.8.3 yutaka)
46 int len = buffer_len(buf);
47 memset(buf->buf, 'x', len);
48 free(buf->buf);
49 free(buf);
50 }
51 }
52
53 int buffer_append(buffer_t * buf, char *ptr, int size)
54 {
55 int n;
56 int ret = -1;
57 int newlen;
58
59 for (;;) {
60 n = buf->offset + size;
61 if (n < buf->maxlen) {
62 memcpy(buf->buf + buf->offset, ptr, size);
63 buf->offset += size;
64 buf->len = buf->offset;
65 ret = 0;
66 break;
67
68 } else {
69 // バッファが足りないので補充する。(2005.7.2 yutaka)
70 newlen = buf->maxlen + size + 32*1024;
71 if (newlen > 0xa00000) { // 1MB over is not supported
72 goto panic;
73 }
74 buf->buf = realloc(buf->buf, newlen);
75 if (buf->buf == NULL)
76 goto panic;
77 buf->maxlen = newlen;
78 }
79 }
80
81 return (ret);
82
83 panic:
84 {
85 char *p = NULL;
86 *p = 0; // application fault
87 }
88
89 return (ret);
90 }
91
92 int buffer_append_length(buffer_t * msg, char *ptr, int size)
93 {
94 char buf[4];
95 int val;
96 int ret = -1;
97
98 val = htonl(size);
99 memcpy(buf, &val, sizeof(val));
100 ret = buffer_append(msg, buf, sizeof(buf));
101 if (ptr != NULL) {
102 ret = buffer_append(msg, ptr, size);
103 }
104
105 return (ret);
106 }
107
108 // getting string buffer.
109 // NOTE: You should free the return pointer if it's unused.
110 // (2005.6.26 yutaka)
111 char *buffer_get_string(char **data_ptr, int *buflen_ptr)
112 {
113 char *data = *data_ptr;
114 char *ptr;
115 int buflen;
116
117 buflen = get_uint32_MSBfirst(data);
118 data += 4;
119 if (buflen <= 0)
120 return NULL;
121
122 ptr = malloc(buflen + 1);
123 if (ptr == NULL) {
124 if (buflen_ptr != NULL)
125 *buflen_ptr = 0;
126 return NULL;
127 }
128 memcpy(ptr, data, buflen);
129 ptr[buflen] = '\0'; // null-terminate
130 data += buflen;
131
132 *data_ptr = data;
133 if (buflen_ptr != NULL)
134 *buflen_ptr = buflen;
135
136 return(ptr);
137 }
138
139 void buffer_put_string(buffer_t *msg, char *ptr, int size)
140 {
141 char buf[4];
142 int val;
143 int ret = -1;
144
145 // 「サイズ+文字列」で書き込む。サイズは4byteのbig-endian。
146 val = htonl(size);
147 memcpy(buf, &val, sizeof(val));
148 ret = buffer_append(msg, buf, sizeof(buf));
149 if (ptr != NULL) {
150 ret = buffer_append(msg, ptr, size);
151 }
152 }
153
154 void buffer_put_char(buffer_t *msg, int value)
155 {
156 char ch = value;
157
158 buffer_append(msg, &ch, 1);
159 }
160
161 void buffer_put_padding(buffer_t *msg, int size)
162 {
163 char ch = ' ';
164 int i;
165
166 for (i = 0 ; i < size ; i++) {
167 buffer_append(msg, &ch, 1);
168 }
169 }
170
171 void buffer_put_int(buffer_t *msg, int value)
172 {
173 char buf[4];
174
175 set_uint32_MSBfirst(buf, value);
176 buffer_append(msg, buf, sizeof(buf));
177 }
178
179 int buffer_len(buffer_t *msg)
180 {
181 return (msg->len);
182 }
183
184 char *buffer_ptr(buffer_t *msg)
185 {
186 return (msg->buf);
187 }
188
189 char *buffer_tail_ptr(buffer_t *msg)
190 {
191 return (char *)(msg->buf + msg->offset);
192 }
193
194 int buffer_overflow_verify(buffer_t *msg, int len)
195 {
196 if (msg->offset + len > msg->maxlen) {
197 return -1; // error
198 }
199 return 0; // no problem
200 }
201
202 // for SSH1
203 void buffer_put_bignum(buffer_t *buffer, BIGNUM *value)
204 {
205 unsigned int bits, bin_size;
206 unsigned char *buf;
207 int oi;
208 char msg[2];
209
210 bits = BN_num_bits(value);
211 bin_size = (bits + 7) / 8;
212 buf = malloc(bin_size);
213 if (buf == NULL) {
214 *buf = 0;
215 goto error;
216 }
217
218 buf[0] = '\0';
219 /* Get the value of in binary */
220 oi = BN_bn2bin(value, buf);
221 if (oi != bin_size) {
222 goto error;
223 }
224
225 /* Store the number of bits in the buffer in two bytes, msb first. */
226 set_ushort16_MSBfirst(msg, bits);
227 buffer_append(buffer, msg, 2);
228
229 /* Store the binary data. */
230 buffer_append(buffer, (char *)buf, oi);
231
232 error:
233 free(buf);
234 }
235
236 // for SSH2
237 void buffer_put_bignum2(buffer_t *msg, BIGNUM *value)
238 {
239 unsigned int bytes;
240 unsigned char *buf;
241 int oi;
242 unsigned int hasnohigh = 0;
243
244 bytes = BN_num_bytes(value) + 1; /* extra padding byte */
245 buf = malloc(bytes);
246 if (buf == NULL) {
247 *buf = 0;
248 goto error;
249 }
250
251 buf[0] = '\0';
252 /* Get the value of in binary */
253 oi = BN_bn2bin(value, buf+1);
254 hasnohigh = (buf[1] & 0x80) ? 0 : 1;
255 buffer_put_string(msg, buf+hasnohigh, bytes-hasnohigh);
256 //memset(buf, 0, bytes);
257
258 error:
259 free(buf);
260 }
261
262 void buffer_get_bignum2(char **data, BIGNUM *value)
263 {
264 char *buf = *data;
265 int len;
266
267 len = get_uint32_MSBfirst(buf);
268 buf += 4;
269 BN_bin2bn(buf, len, value);
270 buf += len;
271
272 *data = buf;
273 }
274
275 void buffer_dump(FILE *fp, buffer_t *buf)
276 {
277 int i;
278 char *ch = buffer_ptr(buf);
279
280 for (i = 0 ; i < buffer_len(buf) ; i++) {
281 fprintf(fp, "%02x", ch[i] & 0xff);
282 if (i % 16 == 15)
283 fprintf(fp, "\n");
284 else if (i % 2 == 1)
285 fprintf(fp, " ");
286 }
287 fprintf(fp, "\n");
288 }
289
290 // バッファのオフセットを進める。
291 void buffer_consume(buffer_t *buf, int shift_byte)
292 {
293 int n;
294
295 n = buf->offset + shift_byte;
296 if (n < buf->maxlen) {
297 buf->offset += shift_byte;
298 } else {
299 // TODO: fatal error
300 }
301 }
302
303 // パケットの圧縮
304 int buffer_compress(z_stream *zstream, char *payload, int len, buffer_t *compbuf)
305 {
306 unsigned char buf[4096];
307 int status;
308
309 // input buffer
310 zstream->next_in = payload;
311 zstream->avail_in = len;
312
313 do {
314 // output buffer
315 zstream->next_out = buf;
316 zstream->avail_out = sizeof(buf);
317
318 // バッファを圧縮する。圧縮すると、逆にサイズが大きくなることも考慮すること。
319 status = deflate(zstream, Z_PARTIAL_FLUSH);
320 if (status == Z_OK) {
321 buffer_append(compbuf, buf, sizeof(buf) - zstream->avail_out);
322 } else {
323 return -1; // error
324 }
325 } while (zstream->avail_out == 0);
326
327 return 0; // success
328 }
329
330 // パケットの展開
331 int buffer_decompress(z_stream *zstream, char *payload, int len, buffer_t *compbuf)
332 {
333 unsigned char buf[4096];
334 int status;
335
336 // input buffer
337 zstream->next_in = payload;
338 zstream->avail_in = len;
339
340 do {
341 // output buffer
342 zstream->next_out = buf;
343 zstream->avail_out = sizeof(buf);
344
345 // バッファを展開する。
346 status = inflate(zstream, Z_PARTIAL_FLUSH);
347 if (status == Z_OK) {
348 buffer_append(compbuf, buf, sizeof(buf) - zstream->avail_out);
349
350 } else if (status == Z_OK) {
351 break;
352
353 } else {
354 return -1; // error
355 }
356 } while (zstream->avail_out == 0);
357
358 return 0; // success
359 }

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