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