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 3227 - (show annotations) (download) (as text)
Tue Mar 24 15:10:33 2009 UTC (15 years, 2 months ago) by maya
File MIME type: text/x-csrc
File size: 6897 byte(s)
CVS から SVN へ移行: 改行コードを LF から CR+LF へ変換
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 void buffer_put_raw(buffer_t *msg, char *ptr, int size)
109 {
110 int ret = -1;
111
112 ret = buffer_append(msg, ptr, size);
113 }
114
115 // getting string buffer.
116 // NOTE: You should free the return pointer if it's unused.
117 // (2005.6.26 yutaka)
118 char *buffer_get_string(char **data_ptr, int *buflen_ptr)
119 {
120 char *data = *data_ptr;
121 char *ptr;
122 int buflen;
123
124 buflen = get_uint32_MSBfirst(data);
125 data += 4;
126 if (buflen <= 0)
127 return NULL;
128
129 ptr = malloc(buflen + 1);
130 if (ptr == NULL) {
131 if (buflen_ptr != NULL)
132 *buflen_ptr = 0;
133 return NULL;
134 }
135 memcpy(ptr, data, buflen);
136 ptr[buflen] = '\0'; // null-terminate
137 data += buflen;
138
139 *data_ptr = data;
140 if (buflen_ptr != NULL)
141 *buflen_ptr = buflen;
142
143 return(ptr);
144 }
145
146 void buffer_put_string(buffer_t *msg, char *ptr, int size)
147 {
148 char buf[4];
149 int val;
150 int ret = -1;
151
152 // 「サイズ+文字列」で書き込む。サイズは4byteのbig-endian。
153 val = htonl(size);
154 memcpy(buf, &val, sizeof(val));
155 ret = buffer_append(msg, buf, sizeof(buf));
156 if (ptr != NULL) {
157 ret = buffer_append(msg, ptr, size);
158 }
159 }
160
161 void buffer_put_char(buffer_t *msg, int value)
162 {
163 char ch = value;
164
165 buffer_append(msg, &ch, 1);
166 }
167
168 void buffer_put_padding(buffer_t *msg, int size)
169 {
170 char ch = ' ';
171 int i;
172
173 for (i = 0 ; i < size ; i++) {
174 buffer_append(msg, &ch, 1);
175 }
176 }
177
178 void buffer_put_int(buffer_t *msg, int value)
179 {
180 char buf[4];
181
182 set_uint32_MSBfirst(buf, value);
183 buffer_append(msg, buf, sizeof(buf));
184 }
185
186 int buffer_len(buffer_t *msg)
187 {
188 return (msg->len);
189 }
190
191 char *buffer_ptr(buffer_t *msg)
192 {
193 return (msg->buf);
194 }
195
196 char *buffer_tail_ptr(buffer_t *msg)
197 {
198 return (char *)(msg->buf + msg->offset);
199 }
200
201 int buffer_overflow_verify(buffer_t *msg, int len)
202 {
203 if (msg->offset + len > msg->maxlen) {
204 return -1; // error
205 }
206 return 0; // no problem
207 }
208
209 // for SSH1
210 void buffer_put_bignum(buffer_t *buffer, BIGNUM *value)
211 {
212 unsigned int bits, bin_size;
213 unsigned char *buf;
214 int oi;
215 char msg[2];
216
217 bits = BN_num_bits(value);
218 bin_size = (bits + 7) / 8;
219 buf = malloc(bin_size);
220 if (buf == NULL) {
221 *buf = 0;
222 goto error;
223 }
224
225 buf[0] = '\0';
226 /* Get the value of in binary */
227 oi = BN_bn2bin(value, buf);
228 if (oi != bin_size) {
229 goto error;
230 }
231
232 /* Store the number of bits in the buffer in two bytes, msb first. */
233 set_ushort16_MSBfirst(msg, bits);
234 buffer_append(buffer, msg, 2);
235
236 /* Store the binary data. */
237 buffer_append(buffer, (char *)buf, oi);
238
239 error:
240 free(buf);
241 }
242
243 // for SSH2
244 void buffer_put_bignum2(buffer_t *msg, BIGNUM *value)
245 {
246 unsigned int bytes;
247 unsigned char *buf;
248 int oi;
249 unsigned int hasnohigh = 0;
250
251 bytes = BN_num_bytes(value) + 1; /* extra padding byte */
252 buf = malloc(bytes);
253 if (buf == NULL) {
254 *buf = 0;
255 goto error;
256 }
257
258 buf[0] = '\0';
259 /* Get the value of in binary */
260 oi = BN_bn2bin(value, buf+1);
261 hasnohigh = (buf[1] & 0x80) ? 0 : 1;
262 buffer_put_string(msg, buf+hasnohigh, bytes-hasnohigh);
263 //memset(buf, 0, bytes);
264
265 error:
266 free(buf);
267 }
268
269 void buffer_get_bignum2(char **data, BIGNUM *value)
270 {
271 char *buf = *data;
272 int len;
273
274 len = get_uint32_MSBfirst(buf);
275 buf += 4;
276 BN_bin2bn(buf, len, value);
277 buf += len;
278
279 *data = buf;
280 }
281
282 void buffer_dump(FILE *fp, buffer_t *buf)
283 {
284 int i;
285 char *ch = buffer_ptr(buf);
286
287 for (i = 0 ; i < buffer_len(buf) ; i++) {
288 fprintf(fp, "%02x", ch[i] & 0xff);
289 if (i % 16 == 15)
290 fprintf(fp, "\n");
291 else if (i % 2 == 1)
292 fprintf(fp, " ");
293 }
294 fprintf(fp, "\n");
295 }
296
297 // バッファのオフセットを進める。
298 void buffer_consume(buffer_t *buf, int shift_byte)
299 {
300 int n;
301
302 n = buf->offset + shift_byte;
303 if (n < buf->maxlen) {
304 buf->offset += shift_byte;
305 } else {
306 // TODO: fatal error
307 }
308 }
309
310 // パケットの圧縮
311 int buffer_compress(z_stream *zstream, char *payload, int len, buffer_t *compbuf)
312 {
313 unsigned char buf[4096];
314 int status;
315
316 // input buffer
317 zstream->next_in = payload;
318 zstream->avail_in = len;
319
320 do {
321 // output buffer
322 zstream->next_out = buf;
323 zstream->avail_out = sizeof(buf);
324
325 // バッファを圧縮する。圧縮すると、逆にサイズが大きくなることも考慮すること。
326 status = deflate(zstream, Z_PARTIAL_FLUSH);
327 if (status == Z_OK) {
328 buffer_append(compbuf, buf, sizeof(buf) - zstream->avail_out);
329 } else {
330 return -1; // error
331 }
332 } while (zstream->avail_out == 0);
333
334 return 0; // success
335 }
336
337 // パケットの展開
338 int buffer_decompress(z_stream *zstream, char *payload, int len, buffer_t *compbuf)
339 {
340 unsigned char buf[4096];
341 int status;
342
343 // input buffer
344 zstream->next_in = payload;
345 zstream->avail_in = len;
346
347 do {
348 // output buffer
349 zstream->next_out = buf;
350 zstream->avail_out = sizeof(buf);
351
352 // バッファを展開する。
353 status = inflate(zstream, Z_PARTIAL_FLUSH);
354 if (status == Z_OK) {
355 buffer_append(compbuf, buf, sizeof(buf) - zstream->avail_out);
356
357 } else if (status == Z_OK) {
358 break;
359
360 } else {
361 return -1; // error
362 }
363 } while (zstream->avail_out == 0);
364
365 return 0; // success
366 }

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