1/* $OpenBSD: bufaux.c,v 1.50 2010/08/31 09:58:37 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#ifdef __APPLE_CRYPTO__ 45#include "ossl-bn.h" 46#else 47#include <openssl/bn.h> 48#endif 49 50#include <string.h> 51#include <stdarg.h> 52 53#include "xmalloc.h" 54#include "buffer.h" 55#include "log.h" 56#include "misc.h" 57 58/* 59 * Returns integers from the buffer (msb first). 60 */ 61 62int 63buffer_get_short_ret(u_short *ret, Buffer *buffer) 64{ 65 u_char buf[2]; 66 67 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) 68 return (-1); 69 *ret = get_u16(buf); 70 return (0); 71} 72 73u_short 74buffer_get_short(Buffer *buffer) 75{ 76 u_short ret; 77 78 if (buffer_get_short_ret(&ret, buffer) == -1) 79 fatal("buffer_get_short: buffer error"); 80 81 return (ret); 82} 83 84int 85buffer_get_int_ret(u_int *ret, Buffer *buffer) 86{ 87 u_char buf[4]; 88 89 if (buffer_get_ret(buffer, (char *) buf, 4) == -1) 90 return (-1); 91 if (ret != NULL) 92 *ret = get_u32(buf); 93 return (0); 94} 95 96u_int 97buffer_get_int(Buffer *buffer) 98{ 99 u_int ret; 100 101 if (buffer_get_int_ret(&ret, buffer) == -1) 102 fatal("buffer_get_int: buffer error"); 103 104 return (ret); 105} 106 107int 108buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) 109{ 110 u_char buf[8]; 111 112 if (buffer_get_ret(buffer, (char *) buf, 8) == -1) 113 return (-1); 114 if (ret != NULL) 115 *ret = get_u64(buf); 116 return (0); 117} 118 119u_int64_t 120buffer_get_int64(Buffer *buffer) 121{ 122 u_int64_t ret; 123 124 if (buffer_get_int64_ret(&ret, buffer) == -1) 125 fatal("buffer_get_int: buffer error"); 126 127 return (ret); 128} 129 130/* 131 * Stores integers in the buffer, msb first. 132 */ 133void 134buffer_put_short(Buffer *buffer, u_short value) 135{ 136 char buf[2]; 137 138 put_u16(buf, value); 139 buffer_append(buffer, buf, 2); 140} 141 142void 143buffer_put_int(Buffer *buffer, u_int value) 144{ 145 char buf[4]; 146 147 put_u32(buf, value); 148 buffer_append(buffer, buf, 4); 149} 150 151void 152buffer_put_int64(Buffer *buffer, u_int64_t value) 153{ 154 char buf[8]; 155 156 put_u64(buf, value); 157 buffer_append(buffer, buf, 8); 158} 159 160/* 161 * Returns an arbitrary binary string from the buffer. The string cannot 162 * be longer than 256k. The returned value points to memory allocated 163 * with xmalloc; it is the responsibility of the calling function to free 164 * the data. If length_ptr is non-NULL, the length of the returned data 165 * will be stored there. A null character will be automatically appended 166 * to the returned string, and is not counted in length. 167 */ 168void * 169buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) 170{ 171 u_char *value; 172 u_int len; 173 174 /* Get the length. */ 175 if (buffer_get_int_ret(&len, buffer) != 0) { 176 error("buffer_get_string_ret: cannot extract length"); 177 return (NULL); 178 } 179 if (len > 256 * 1024) { 180 error("buffer_get_string_ret: bad string length %u", len); 181 return (NULL); 182 } 183 /* Allocate space for the string. Add one byte for a null character. */ 184 value = xmalloc(len + 1); 185 /* Get the string. */ 186 if (buffer_get_ret(buffer, value, len) == -1) { 187 error("buffer_get_string_ret: buffer_get failed"); 188 xfree(value); 189 return (NULL); 190 } 191 /* Append a null character to make processing easier. */ 192 value[len] = '\0'; 193 /* Optionally return the length of the string. */ 194 if (length_ptr) 195 *length_ptr = len; 196 return (value); 197} 198 199void * 200buffer_get_string(Buffer *buffer, u_int *length_ptr) 201{ 202 void *ret; 203 204 if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) 205 fatal("buffer_get_string: buffer error"); 206 return (ret); 207} 208 209char * 210buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) 211{ 212 u_int length; 213 char *cp, *ret = buffer_get_string_ret(buffer, &length); 214 215 if (ret == NULL) 216 return NULL; 217 if ((cp = memchr(ret, '\0', length)) != NULL) { 218 /* XXX allow \0 at end-of-string for a while, remove later */ 219 if (cp == ret + length - 1) 220 error("buffer_get_cstring_ret: string contains \\0"); 221 else { 222 bzero(ret, length); 223 xfree(ret); 224 return NULL; 225 } 226 } 227 if (length_ptr != NULL) 228 *length_ptr = length; 229 return ret; 230} 231 232char * 233buffer_get_cstring(Buffer *buffer, u_int *length_ptr) 234{ 235 char *ret; 236 237 if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) 238 fatal("buffer_get_cstring: buffer error"); 239 return ret; 240} 241 242void * 243buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) 244{ 245 void *ptr; 246 u_int len; 247 248 if (buffer_get_int_ret(&len, buffer) != 0) 249 return NULL; 250 if (len > 256 * 1024) { 251 error("buffer_get_string_ptr: bad string length %u", len); 252 return NULL; 253 } 254 ptr = buffer_ptr(buffer); 255 buffer_consume(buffer, len); 256 if (length_ptr) 257 *length_ptr = len; 258 return (ptr); 259} 260 261void * 262buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr) 263{ 264 void *ret; 265 266 if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) 267 fatal("buffer_get_string_ptr: buffer error"); 268 return (ret); 269} 270 271/* 272 * Stores and arbitrary binary string in the buffer. 273 */ 274void 275buffer_put_string(Buffer *buffer, const void *buf, u_int len) 276{ 277 buffer_put_int(buffer, len); 278 buffer_append(buffer, buf, len); 279} 280void 281buffer_put_cstring(Buffer *buffer, const char *s) 282{ 283 if (s == NULL) 284 fatal("buffer_put_cstring: s == NULL"); 285 buffer_put_string(buffer, s, strlen(s)); 286} 287 288/* 289 * Returns a character from the buffer (0 - 255). 290 */ 291int 292buffer_get_char_ret(char *ret, Buffer *buffer) 293{ 294 if (buffer_get_ret(buffer, ret, 1) == -1) { 295 error("buffer_get_char_ret: buffer_get_ret failed"); 296 return (-1); 297 } 298 return (0); 299} 300 301int 302buffer_get_char(Buffer *buffer) 303{ 304 char ch; 305 306 if (buffer_get_char_ret(&ch, buffer) == -1) 307 fatal("buffer_get_char: buffer error"); 308 return (u_char) ch; 309} 310 311/* 312 * Stores a character in the buffer. 313 */ 314void 315buffer_put_char(Buffer *buffer, int value) 316{ 317 char ch = value; 318 319 buffer_append(buffer, &ch, 1); 320} 321