bufaux.c revision 264692
1/* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */ 2/* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * Auxiliary functions for storing and retrieving various data types to/from 7 * Buffers. 8 * 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". 14 * 15 * 16 * SSH2 packet format added by Markus Friedl 17 * Copyright (c) 2000 Markus Friedl. All rights reserved. 18 * 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. 38 */ 39 40#include "includes.h" 41 42#include <sys/types.h> 43 44#include <openssl/bn.h> 45 46#include <string.h> 47#include <stdarg.h> 48#include <stdlib.h> 49 50#include "xmalloc.h" 51#include "buffer.h" 52#include "log.h" 53#include "misc.h" 54 55/* 56 * Returns integers from the buffer (msb first). 57 */ 58 59int 60buffer_get_short_ret(u_short *ret, Buffer *buffer) 61{ 62 u_char buf[2]; 63 64 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) 65 return (-1); 66 *ret = get_u16(buf); 67 return (0); 68} 69 70u_short 71buffer_get_short(Buffer *buffer) 72{ 73 u_short ret; 74 75 if (buffer_get_short_ret(&ret, buffer) == -1) 76 fatal("buffer_get_short: buffer error"); 77 78 return (ret); 79} 80 81int 82buffer_get_int_ret(u_int *ret, Buffer *buffer) 83{ 84 u_char buf[4]; 85 86 if (buffer_get_ret(buffer, (char *) buf, 4) == -1) 87 return (-1); 88 if (ret != NULL) 89 *ret = get_u32(buf); 90 return (0); 91} 92 93u_int 94buffer_get_int(Buffer *buffer) 95{ 96 u_int ret; 97 98 if (buffer_get_int_ret(&ret, buffer) == -1) 99 fatal("buffer_get_int: buffer error"); 100 101 return (ret); 102} 103 104int 105buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) 106{ 107 u_char buf[8]; 108 109 if (buffer_get_ret(buffer, (char *) buf, 8) == -1) 110 return (-1); 111 if (ret != NULL) 112 *ret = get_u64(buf); 113 return (0); 114} 115 116u_int64_t 117buffer_get_int64(Buffer *buffer) 118{ 119 u_int64_t ret; 120 121 if (buffer_get_int64_ret(&ret, buffer) == -1) 122 fatal("buffer_get_int: buffer error"); 123 124 return (ret); 125} 126 127/* 128 * Stores integers in the buffer, msb first. 129 */ 130void 131buffer_put_short(Buffer *buffer, u_short value) 132{ 133 char buf[2]; 134 135 put_u16(buf, value); 136 buffer_append(buffer, buf, 2); 137} 138 139void 140buffer_put_int(Buffer *buffer, u_int value) 141{ 142 char buf[4]; 143 144 put_u32(buf, value); 145 buffer_append(buffer, buf, 4); 146} 147 148void 149buffer_put_int64(Buffer *buffer, u_int64_t value) 150{ 151 char buf[8]; 152 153 put_u64(buf, value); 154 buffer_append(buffer, buf, 8); 155} 156 157/* 158 * Returns an arbitrary binary string from the buffer. The string cannot 159 * be longer than 256k. The returned value points to memory allocated 160 * with xmalloc; it is the responsibility of the calling function to free 161 * the data. If length_ptr is non-NULL, the length of the returned data 162 * will be stored there. A null character will be automatically appended 163 * to the returned string, and is not counted in length. 164 */ 165void * 166buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) 167{ 168 u_char *value; 169 u_int len; 170 171 /* Get the length. */ 172 if (buffer_get_int_ret(&len, buffer) != 0) { 173 error("buffer_get_string_ret: cannot extract length"); 174 return (NULL); 175 } 176 if (len > 256 * 1024) { 177 error("buffer_get_string_ret: bad string length %u", len); 178 return (NULL); 179 } 180 /* Allocate space for the string. Add one byte for a null character. */ 181 value = xmalloc(len + 1); 182 /* Get the string. */ 183 if (buffer_get_ret(buffer, value, len) == -1) { 184 error("buffer_get_string_ret: buffer_get failed"); 185 free(value); 186 return (NULL); 187 } 188 /* Append a null character to make processing easier. */ 189 value[len] = '\0'; 190 /* Optionally return the length of the string. */ 191 if (length_ptr) 192 *length_ptr = len; 193 return (value); 194} 195 196void * 197buffer_get_string(Buffer *buffer, u_int *length_ptr) 198{ 199 void *ret; 200 201 if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) 202 fatal("buffer_get_string: buffer error"); 203 return (ret); 204} 205 206char * 207buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) 208{ 209 u_int length; 210 char *cp, *ret = buffer_get_string_ret(buffer, &length); 211 212 if (ret == NULL) 213 return NULL; 214 if ((cp = memchr(ret, '\0', length)) != NULL) { 215 /* XXX allow \0 at end-of-string for a while, remove later */ 216 if (cp == ret + length - 1) 217 error("buffer_get_cstring_ret: string contains \\0"); 218 else { 219 explicit_bzero(ret, length); 220 free(ret); 221 return NULL; 222 } 223 } 224 if (length_ptr != NULL) 225 *length_ptr = length; 226 return ret; 227} 228 229char * 230buffer_get_cstring(Buffer *buffer, u_int *length_ptr) 231{ 232 char *ret; 233 234 if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) 235 fatal("buffer_get_cstring: buffer error"); 236 return ret; 237} 238 239void * 240buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) 241{ 242 void *ptr; 243 u_int len; 244 245 if (buffer_get_int_ret(&len, buffer) != 0) 246 return NULL; 247 if (len > 256 * 1024) { 248 error("buffer_get_string_ptr: bad string length %u", len); 249 return NULL; 250 } 251 ptr = buffer_ptr(buffer); 252 buffer_consume(buffer, len); 253 if (length_ptr) 254 *length_ptr = len; 255 return (ptr); 256} 257 258void * 259buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr) 260{ 261 void *ret; 262 263 if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) 264 fatal("buffer_get_string_ptr: buffer error"); 265 return (ret); 266} 267 268/* 269 * Stores and arbitrary binary string in the buffer. 270 */ 271void 272buffer_put_string(Buffer *buffer, const void *buf, u_int len) 273{ 274 buffer_put_int(buffer, len); 275 buffer_append(buffer, buf, len); 276} 277void 278buffer_put_cstring(Buffer *buffer, const char *s) 279{ 280 if (s == NULL) 281 fatal("buffer_put_cstring: s == NULL"); 282 buffer_put_string(buffer, s, strlen(s)); 283} 284 285/* 286 * Returns a character from the buffer (0 - 255). 287 */ 288int 289buffer_get_char_ret(u_char *ret, Buffer *buffer) 290{ 291 if (buffer_get_ret(buffer, ret, 1) == -1) { 292 error("buffer_get_char_ret: buffer_get_ret failed"); 293 return (-1); 294 } 295 return (0); 296} 297 298int 299buffer_get_char(Buffer *buffer) 300{ 301 u_char ch; 302 303 if (buffer_get_char_ret(&ch, buffer) == -1) 304 fatal("buffer_get_char: buffer error"); 305 return ch; 306} 307 308/* 309 * Stores a character in the buffer. 310 */ 311void 312buffer_put_char(Buffer *buffer, int value) 313{ 314 char ch = value; 315 316 buffer_append(buffer, &ch, 1); 317} 318 319/* Pseudo bignum functions */ 320 321void * 322buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr) 323{ 324 u_int len; 325 u_char *bin, *p, *ret; 326 327 if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) { 328 error("%s: invalid bignum", __func__); 329 return NULL; 330 } 331 332 if (len > 0 && (bin[0] & 0x80)) { 333 error("%s: negative numbers not supported", __func__); 334 free(bin); 335 return NULL; 336 } 337 if (len > 8 * 1024) { 338 error("%s: cannot handle BN of size %d", __func__, len); 339 free(bin); 340 return NULL; 341 } 342 /* Skip zero prefix on numbers with the MSB set */ 343 if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) { 344 p++; 345 len--; 346 } 347 ret = xmalloc(len); 348 memcpy(ret, p, len); 349 explicit_bzero(p, len); 350 free(bin); 351 return ret; 352} 353 354void * 355buffer_get_bignum2_as_string(Buffer *buffer, u_int *l) 356{ 357 void *ret = buffer_get_bignum2_as_string_ret(buffer, l); 358 359 if (ret == NULL) 360 fatal("%s: buffer error", __func__); 361 return ret; 362} 363 364/* 365 * Stores a string using the bignum encoding rules (\0 pad if MSB set). 366 */ 367void 368buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) 369{ 370 u_char *buf, *p; 371 int pad = 0; 372 373 if (l > 8 * 1024) 374 fatal("%s: length %u too long", __func__, l); 375 /* Skip leading zero bytes */ 376 for (; l > 0 && *s == 0; l--, s++) 377 ; 378 p = buf = xmalloc(l + 1); 379 /* 380 * If most significant bit is set then prepend a zero byte to 381 * avoid interpretation as a negative number. 382 */ 383 if (l > 0 && (s[0] & 0x80) != 0) { 384 *p++ = '\0'; 385 pad = 1; 386 } 387 memcpy(p, s, l); 388 buffer_put_string(buffer, buf, l + pad); 389 explicit_bzero(buf, l + pad); 390 free(buf); 391} 392 393 394