source: trunk/third/openssh/bufaux.c @ 22570

Revision 22570, 9.3 KB checked in by ghudson, 18 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r22569, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 *                    All rights reserved
5 * Auxiliary functions for storing and retrieving various data types to/from
6 * Buffers.
7 *
8 * As far as I am concerned, the code I have written for this software
9 * can be used freely for any purpose.  Any derived versions of this
10 * software must be clearly marked as such, and if the derived work is
11 * incompatible with the protocol description in the RFC file, it must be
12 * called by a name other than "ssh" or "Secure Shell".
13 *
14 *
15 * SSH2 packet format added by Markus Friedl
16 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 */
38
39#include "includes.h"
40RCSID("$OpenBSD: bufaux.c,v 1.36 2005/06/17 02:44:32 djm Exp $");
41
42#include <openssl/bn.h>
43#include "bufaux.h"
44#include "xmalloc.h"
45#include "getput.h"
46#include "log.h"
47
48/*
49 * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
50 * by (bits+7)/8 bytes of binary data, msb first.
51 */
52int
53buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
54{
55        int bits = BN_num_bits(value);
56        int bin_size = (bits + 7) / 8;
57        u_char *buf = xmalloc(bin_size);
58        int oi;
59        char msg[2];
60
61        /* Get the value of in binary */
62        oi = BN_bn2bin(value, buf);
63        if (oi != bin_size) {
64                error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
65                    oi, bin_size);
66                return (-1);
67        }
68
69        /* Store the number of bits in the buffer in two bytes, msb first. */
70        PUT_16BIT(msg, bits);
71        buffer_append(buffer, msg, 2);
72        /* Store the binary data. */
73        buffer_append(buffer, (char *)buf, oi);
74
75        memset(buf, 0, bin_size);
76        xfree(buf);
77
78        return (0);
79}
80
81void
82buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
83{
84        if (buffer_put_bignum_ret(buffer, value) == -1)
85                fatal("buffer_put_bignum: buffer error");
86}
87
88/*
89 * Retrieves an BIGNUM from the buffer.
90 */
91int
92buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
93{
94        u_int bits, bytes;
95        u_char buf[2], *bin;
96
97        /* Get the number for bits. */
98        if (buffer_get_ret(buffer, (char *) buf, 2) == -1) {
99                error("buffer_get_bignum_ret: invalid length");
100                return (-1);
101        }
102        bits = GET_16BIT(buf);
103        /* Compute the number of binary bytes that follow. */
104        bytes = (bits + 7) / 8;
105        if (bytes > 8 * 1024) {
106                error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
107                return (-1);
108        }
109        if (buffer_len(buffer) < bytes) {
110                error("buffer_get_bignum_ret: input buffer too small");
111                return (-1);
112        }
113        bin = buffer_ptr(buffer);
114        BN_bin2bn(bin, bytes, value);
115        if (buffer_consume_ret(buffer, bytes) == -1) {
116                error("buffer_get_bignum_ret: buffer_consume failed");
117                return (-1);
118        }
119        return (0);
120}
121
122void
123buffer_get_bignum(Buffer *buffer, BIGNUM *value)
124{
125        if (buffer_get_bignum_ret(buffer, value) == -1)
126                fatal("buffer_get_bignum: buffer error");
127}
128
129/*
130 * Stores an BIGNUM in the buffer in SSH2 format.
131 */
132int
133buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
134{
135        u_int bytes;
136        u_char *buf;
137        int oi;
138        u_int hasnohigh = 0;
139
140        if (BN_is_zero(value)) {
141                buffer_put_int(buffer, 0);
142                return 0;
143        }
144        if (value->neg) {
145                error("buffer_put_bignum2_ret: negative numbers not supported");
146                return (-1);
147        }
148        bytes = BN_num_bytes(value) + 1; /* extra padding byte */
149        if (bytes < 2) {
150                error("buffer_put_bignum2_ret: BN too small");
151                return (-1);
152        }
153        buf = xmalloc(bytes);
154        buf[0] = 0x00;
155        /* Get the value of in binary */
156        oi = BN_bn2bin(value, buf+1);
157        if (oi < 0 || (u_int)oi != bytes - 1) {
158                error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
159                    "oi %d != bin_size %d", oi, bytes);
160                xfree(buf);
161                return (-1);
162        }
163        hasnohigh = (buf[1] & 0x80) ? 0 : 1;
164        buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
165        memset(buf, 0, bytes);
166        xfree(buf);
167        return (0);
168}
169
170void
171buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
172{
173        if (buffer_put_bignum2_ret(buffer, value) == -1)
174                fatal("buffer_put_bignum2: buffer error");
175}
176
177int
178buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
179{
180        u_int len;
181        u_char *bin;
182
183        if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) {
184                error("buffer_get_bignum2_ret: invalid bignum");
185                return (-1);
186        }
187
188        if (len > 0 && (bin[0] & 0x80)) {
189                error("buffer_get_bignum2_ret: negative numbers not supported");
190                return (-1);
191        }
192        if (len > 8 * 1024) {
193                error("buffer_get_bignum2_ret: cannot handle BN of size %d", len);
194                return (-1);
195        }
196        BN_bin2bn(bin, len, value);
197        xfree(bin);
198        return (0);
199}
200
201void
202buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
203{
204        if (buffer_get_bignum2_ret(buffer, value) == -1)
205                fatal("buffer_get_bignum2: buffer error");
206}
207
208/*
209 * Returns integers from the buffer (msb first).
210 */
211
212int
213buffer_get_short_ret(u_short *ret, Buffer *buffer)
214{
215        u_char buf[2];
216
217        if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
218                return (-1);
219        *ret = GET_16BIT(buf);
220        return (0);
221}
222
223u_short
224buffer_get_short(Buffer *buffer)
225{
226        u_short ret;
227
228        if (buffer_get_short_ret(&ret, buffer) == -1)
229                fatal("buffer_get_short: buffer error");
230
231        return (ret);
232}
233
234int
235buffer_get_int_ret(u_int *ret, Buffer *buffer)
236{
237        u_char buf[4];
238
239        if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
240                return (-1);
241        *ret = GET_32BIT(buf);
242        return (0);
243}
244
245u_int
246buffer_get_int(Buffer *buffer)
247{
248        u_int ret;
249
250        if (buffer_get_int_ret(&ret, buffer) == -1)
251                fatal("buffer_get_int: buffer error");
252
253        return (ret);
254}
255
256int
257buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
258{
259        u_char buf[8];
260
261        if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
262                return (-1);
263        *ret = GET_64BIT(buf);
264        return (0);
265}
266
267u_int64_t
268buffer_get_int64(Buffer *buffer)
269{
270        u_int64_t ret;
271
272        if (buffer_get_int64_ret(&ret, buffer) == -1)
273                fatal("buffer_get_int: buffer error");
274
275        return (ret);
276}
277
278/*
279 * Stores integers in the buffer, msb first.
280 */
281void
282buffer_put_short(Buffer *buffer, u_short value)
283{
284        char buf[2];
285
286        PUT_16BIT(buf, value);
287        buffer_append(buffer, buf, 2);
288}
289
290void
291buffer_put_int(Buffer *buffer, u_int value)
292{
293        char buf[4];
294
295        PUT_32BIT(buf, value);
296        buffer_append(buffer, buf, 4);
297}
298
299void
300buffer_put_int64(Buffer *buffer, u_int64_t value)
301{
302        char buf[8];
303
304        PUT_64BIT(buf, value);
305        buffer_append(buffer, buf, 8);
306}
307
308/*
309 * Returns an arbitrary binary string from the buffer.  The string cannot
310 * be longer than 256k.  The returned value points to memory allocated
311 * with xmalloc; it is the responsibility of the calling function to free
312 * the data.  If length_ptr is non-NULL, the length of the returned data
313 * will be stored there.  A null character will be automatically appended
314 * to the returned string, and is not counted in length.
315 */
316void *
317buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
318{
319        u_char *value;
320        u_int len;
321
322        /* Get the length. */
323        len = buffer_get_int(buffer);
324        if (len > 256 * 1024) {
325                error("buffer_get_string_ret: bad string length %u", len);
326                return (NULL);
327        }
328        /* Allocate space for the string.  Add one byte for a null character. */
329        value = xmalloc(len + 1);
330        /* Get the string. */
331        if (buffer_get_ret(buffer, value, len) == -1) {
332                error("buffer_get_string_ret: buffer_get failed");
333                xfree(value);
334                return (NULL);
335        }
336        /* Append a null character to make processing easier. */
337        value[len] = 0;
338        /* Optionally return the length of the string. */
339        if (length_ptr)
340                *length_ptr = len;
341        return (value);
342}
343
344void *
345buffer_get_string(Buffer *buffer, u_int *length_ptr)
346{
347        void *ret;
348
349        if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
350                fatal("buffer_get_string: buffer error");
351        return (ret);
352}
353
354/*
355 * Stores and arbitrary binary string in the buffer.
356 */
357void
358buffer_put_string(Buffer *buffer, const void *buf, u_int len)
359{
360        buffer_put_int(buffer, len);
361        buffer_append(buffer, buf, len);
362}
363void
364buffer_put_cstring(Buffer *buffer, const char *s)
365{
366        if (s == NULL)
367                fatal("buffer_put_cstring: s == NULL");
368        buffer_put_string(buffer, s, strlen(s));
369}
370
371/*
372 * Returns a character from the buffer (0 - 255).
373 */
374int
375buffer_get_char_ret(char *ret, Buffer *buffer)
376{
377        if (buffer_get_ret(buffer, ret, 1) == -1) {
378                error("buffer_get_char_ret: buffer_get_ret failed");
379                return (-1);
380        }
381        return (0);
382}
383
384int
385buffer_get_char(Buffer *buffer)
386{
387        char ch;
388
389        if (buffer_get_char_ret(&ch, buffer) == -1)
390                fatal("buffer_get_char: buffer error");
391        return (u_char) ch;
392}
393
394/*
395 * Stores a character in the buffer.
396 */
397void
398buffer_put_char(Buffer *buffer, int value)
399{
400        char ch = value;
401
402        buffer_append(buffer, &ch, 1);
403}
Note: See TracBrowser for help on using the repository browser.