Annotation of src/usr.bin/ssh/bufaux.c, Revision 1.56
1.56 ! djm 1: /* $OpenBSD: bufaux.c,v 1.55 2014/01/31 16:39:19 tedu Exp $ */
1.1 deraadt 2: /*
1.6 deraadt 3: * Author: Tatu Ylonen <ylo@cs.hut.fi>
4: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5: * All rights reserved
1.13 deraadt 6: * Auxiliary functions for storing and retrieving various data types to/from
7: * Buffers.
1.11 markus 8: *
1.13 deraadt 9: * As far as I am concerned, the code I have written for this software
10: * can be used freely for any purpose. Any derived versions of this
11: * software must be clearly marked as such, and if the derived work is
12: * incompatible with the protocol description in the RFC file, it must be
13: * called by a name other than "ssh" or "Secure Shell".
1.11 markus 14: *
1.6 deraadt 15: *
1.9 markus 16: * SSH2 packet format added by Markus Friedl
1.13 deraadt 17: * Copyright (c) 2000 Markus Friedl. All rights reserved.
1.9 markus 18: *
1.13 deraadt 19: * Redistribution and use in source and binary forms, with or without
20: * modification, are permitted provided that the following conditions
21: * are met:
22: * 1. Redistributions of source code must retain the above copyright
23: * notice, this list of conditions and the following disclaimer.
24: * 2. Redistributions in binary form must reproduce the above copyright
25: * notice, this list of conditions and the following disclaimer in the
26: * documentation and/or other materials provided with the distribution.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
32: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.6 deraadt 38: */
1.1 deraadt 39:
1.44 deraadt 40: #include <sys/types.h>
1.1 deraadt 41:
1.10 markus 42: #include <openssl/bn.h>
1.43 stevesk 43:
44: #include <string.h>
1.44 deraadt 45: #include <stdarg.h>
1.53 dtucker 46: #include <stdlib.h>
1.43 stevesk 47:
1.1 deraadt 48: #include "xmalloc.h"
1.44 deraadt 49: #include "buffer.h"
1.17 markus 50: #include "log.h"
1.41 djm 51: #include "misc.h"
1.32 markus 52:
1.9 markus 53: /*
1.25 markus 54: * Returns integers from the buffer (msb first).
1.6 deraadt 55: */
1.25 markus 56:
1.33 djm 57: int
58: buffer_get_short_ret(u_short *ret, Buffer *buffer)
59: {
60: u_char buf[2];
61:
62: if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
63: return (-1);
1.41 djm 64: *ret = get_u16(buf);
1.33 djm 65: return (0);
66: }
67:
1.25 markus 68: u_short
69: buffer_get_short(Buffer *buffer)
70: {
1.33 djm 71: u_short ret;
72:
73: if (buffer_get_short_ret(&ret, buffer) == -1)
74: fatal("buffer_get_short: buffer error");
75:
76: return (ret);
77: }
78:
79: int
80: buffer_get_int_ret(u_int *ret, Buffer *buffer)
81: {
82: u_char buf[4];
1.26 deraadt 83:
1.33 djm 84: if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
85: return (-1);
1.49 djm 86: if (ret != NULL)
87: *ret = get_u32(buf);
1.33 djm 88: return (0);
1.25 markus 89: }
90:
1.14 markus 91: u_int
1.5 markus 92: buffer_get_int(Buffer *buffer)
1.1 deraadt 93: {
1.33 djm 94: u_int ret;
95:
96: if (buffer_get_int_ret(&ret, buffer) == -1)
97: fatal("buffer_get_int: buffer error");
98:
99: return (ret);
100: }
101:
102: int
103: buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
104: {
105: u_char buf[8];
1.26 deraadt 106:
1.33 djm 107: if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
108: return (-1);
1.49 djm 109: if (ret != NULL)
110: *ret = get_u64(buf);
1.33 djm 111: return (0);
1.1 deraadt 112: }
113:
1.15 markus 114: u_int64_t
115: buffer_get_int64(Buffer *buffer)
116: {
1.33 djm 117: u_int64_t ret;
118:
119: if (buffer_get_int64_ret(&ret, buffer) == -1)
120: fatal("buffer_get_int: buffer error");
1.26 deraadt 121:
1.33 djm 122: return (ret);
1.15 markus 123: }
124:
1.6 deraadt 125: /*
1.25 markus 126: * Stores integers in the buffer, msb first.
1.6 deraadt 127: */
1.25 markus 128: void
129: buffer_put_short(Buffer *buffer, u_short value)
130: {
131: char buf[2];
1.26 deraadt 132:
1.41 djm 133: put_u16(buf, value);
1.25 markus 134: buffer_append(buffer, buf, 2);
135: }
136:
1.11 markus 137: void
1.14 markus 138: buffer_put_int(Buffer *buffer, u_int value)
1.1 deraadt 139: {
1.5 markus 140: char buf[4];
1.26 deraadt 141:
1.41 djm 142: put_u32(buf, value);
1.5 markus 143: buffer_append(buffer, buf, 4);
1.15 markus 144: }
145:
146: void
147: buffer_put_int64(Buffer *buffer, u_int64_t value)
148: {
149: char buf[8];
1.26 deraadt 150:
1.41 djm 151: put_u64(buf, value);
1.15 markus 152: buffer_append(buffer, buf, 8);
1.1 deraadt 153: }
154:
1.6 deraadt 155: /*
156: * Returns an arbitrary binary string from the buffer. The string cannot
157: * be longer than 256k. The returned value points to memory allocated
158: * with xmalloc; it is the responsibility of the calling function to free
159: * the data. If length_ptr is non-NULL, the length of the returned data
160: * will be stored there. A null character will be automatically appended
161: * to the returned string, and is not counted in length.
162: */
1.20 stevesk 163: void *
1.33 djm 164: buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
1.1 deraadt 165: {
1.26 deraadt 166: u_char *value;
1.14 markus 167: u_int len;
1.26 deraadt 168:
1.5 markus 169: /* Get the length. */
1.48 djm 170: if (buffer_get_int_ret(&len, buffer) != 0) {
171: error("buffer_get_string_ret: cannot extract length");
172: return (NULL);
173: }
1.33 djm 174: if (len > 256 * 1024) {
175: error("buffer_get_string_ret: bad string length %u", len);
176: return (NULL);
177: }
1.5 markus 178: /* Allocate space for the string. Add one byte for a null character. */
179: value = xmalloc(len + 1);
180: /* Get the string. */
1.33 djm 181: if (buffer_get_ret(buffer, value, len) == -1) {
182: error("buffer_get_string_ret: buffer_get failed");
1.51 djm 183: free(value);
1.33 djm 184: return (NULL);
185: }
1.5 markus 186: /* Append a null character to make processing easier. */
1.46 dtucker 187: value[len] = '\0';
1.5 markus 188: /* Optionally return the length of the string. */
189: if (length_ptr)
190: *length_ptr = len;
1.33 djm 191: return (value);
192: }
193:
194: void *
195: buffer_get_string(Buffer *buffer, u_int *length_ptr)
196: {
197: void *ret;
198:
199: if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
200: fatal("buffer_get_string: buffer error");
201: return (ret);
1.50 djm 202: }
203:
204: char *
205: buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
206: {
207: u_int length;
208: char *cp, *ret = buffer_get_string_ret(buffer, &length);
209:
210: if (ret == NULL)
211: return NULL;
212: if ((cp = memchr(ret, '\0', length)) != NULL) {
213: /* XXX allow \0 at end-of-string for a while, remove later */
214: if (cp == ret + length - 1)
215: error("buffer_get_cstring_ret: string contains \\0");
216: else {
1.55 tedu 217: explicit_bzero(ret, length);
1.51 djm 218: free(ret);
1.50 djm 219: return NULL;
220: }
221: }
222: if (length_ptr != NULL)
223: *length_ptr = length;
224: return ret;
225: }
226:
227: char *
228: buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
229: {
230: char *ret;
231:
232: if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
233: fatal("buffer_get_cstring: buffer error");
234: return ret;
1.45 markus 235: }
236:
237: void *
1.47 djm 238: buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
1.45 markus 239: {
240: void *ptr;
241: u_int len;
242:
1.47 djm 243: if (buffer_get_int_ret(&len, buffer) != 0)
244: return NULL;
245: if (len > 256 * 1024) {
246: error("buffer_get_string_ptr: bad string length %u", len);
247: return NULL;
248: }
1.45 markus 249: ptr = buffer_ptr(buffer);
250: buffer_consume(buffer, len);
251: if (length_ptr)
252: *length_ptr = len;
253: return (ptr);
1.47 djm 254: }
255:
256: void *
257: buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
258: {
259: void *ret;
260:
261: if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
262: fatal("buffer_get_string_ptr: buffer error");
263: return (ret);
1.1 deraadt 264: }
265:
1.6 deraadt 266: /*
267: * Stores and arbitrary binary string in the buffer.
268: */
1.11 markus 269: void
1.14 markus 270: buffer_put_string(Buffer *buffer, const void *buf, u_int len)
1.1 deraadt 271: {
1.5 markus 272: buffer_put_int(buffer, len);
273: buffer_append(buffer, buf, len);
1.9 markus 274: }
1.11 markus 275: void
1.9 markus 276: buffer_put_cstring(Buffer *buffer, const char *s)
277: {
1.23 provos 278: if (s == NULL)
279: fatal("buffer_put_cstring: s == NULL");
1.9 markus 280: buffer_put_string(buffer, s, strlen(s));
1.1 deraadt 281: }
282:
1.6 deraadt 283: /*
284: * Returns a character from the buffer (0 - 255).
285: */
1.11 markus 286: int
1.52 djm 287: buffer_get_char_ret(u_char *ret, Buffer *buffer)
1.33 djm 288: {
289: if (buffer_get_ret(buffer, ret, 1) == -1) {
290: error("buffer_get_char_ret: buffer_get_ret failed");
291: return (-1);
292: }
293: return (0);
294: }
295:
296: int
1.5 markus 297: buffer_get_char(Buffer *buffer)
1.1 deraadt 298: {
1.52 djm 299: u_char ch;
1.26 deraadt 300:
1.33 djm 301: if (buffer_get_char_ret(&ch, buffer) == -1)
302: fatal("buffer_get_char: buffer error");
1.52 djm 303: return ch;
1.1 deraadt 304: }
305:
1.6 deraadt 306: /*
307: * Stores a character in the buffer.
308: */
1.11 markus 309: void
1.5 markus 310: buffer_put_char(Buffer *buffer, int value)
1.1 deraadt 311: {
1.5 markus 312: char ch = value;
1.26 deraadt 313:
1.5 markus 314: buffer_append(buffer, &ch, 1);
1.1 deraadt 315: }
1.54 djm 316:
317: /* Pseudo bignum functions */
318:
319: void *
320: buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr)
321: {
322: u_int len;
323: u_char *bin, *p, *ret;
324:
325: if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) {
326: error("%s: invalid bignum", __func__);
327: return NULL;
328: }
329:
330: if (len > 0 && (bin[0] & 0x80)) {
331: error("%s: negative numbers not supported", __func__);
332: free(bin);
333: return NULL;
334: }
335: if (len > 8 * 1024) {
336: error("%s: cannot handle BN of size %d", __func__, len);
337: free(bin);
338: return NULL;
339: }
340: /* Skip zero prefix on numbers with the MSB set */
341: if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) {
342: p++;
343: len--;
344: }
345: ret = xmalloc(len);
346: memcpy(ret, p, len);
1.56 ! djm 347: explicit_bzero(p, len);
1.54 djm 348: free(bin);
349: return ret;
350: }
351:
352: void *
353: buffer_get_bignum2_as_string(Buffer *buffer, u_int *l)
354: {
355: void *ret = buffer_get_bignum2_as_string_ret(buffer, l);
356:
357: if (ret == NULL)
358: fatal("%s: buffer error", __func__);
359: return ret;
360: }
361:
362: /*
363: * Stores a string using the bignum encoding rules (\0 pad if MSB set).
364: */
365: void
366: buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
367: {
368: u_char *buf, *p;
369: int pad = 0;
370:
371: if (l > 8 * 1024)
372: fatal("%s: length %u too long", __func__, l);
373: p = buf = xmalloc(l + 1);
374: /*
375: * If most significant bit is set then prepend a zero byte to
376: * avoid interpretation as a negative number.
377: */
378: if (l > 0 && (s[0] & 0x80) != 0) {
379: *p++ = '\0';
380: pad = 1;
381: }
382: memcpy(p, s, l);
383: buffer_put_string(buffer, buf, l + pad);
1.56 ! djm 384: explicit_bzero(buf, l + pad);
1.54 djm 385: free(buf);
386: }
387:
388: