1255767Sdes/* $OpenBSD: bufaux.c,v 1.52 2013/07/12 00:19:58 djm Exp $ */ 257429Smarkm/* 357429Smarkm * Author: Tatu Ylonen <ylo@cs.hut.fi> 457429Smarkm * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 557429Smarkm * All rights reserved 657429Smarkm * Auxiliary functions for storing and retrieving various data types to/from 757429Smarkm * Buffers. 857429Smarkm * 965674Skris * As far as I am concerned, the code I have written for this software 1065674Skris * can be used freely for any purpose. Any derived versions of this 1165674Skris * software must be clearly marked as such, and if the derived work is 1265674Skris * incompatible with the protocol description in the RFC file, it must be 1365674Skris * called by a name other than "ssh" or "Secure Shell". 1465674Skris * 1565674Skris * 1660576Skris * SSH2 packet format added by Markus Friedl 1765674Skris * Copyright (c) 2000 Markus Friedl. All rights reserved. 1860576Skris * 1965674Skris * Redistribution and use in source and binary forms, with or without 2065674Skris * modification, are permitted provided that the following conditions 2165674Skris * are met: 2265674Skris * 1. Redistributions of source code must retain the above copyright 2365674Skris * notice, this list of conditions and the following disclaimer. 2465674Skris * 2. Redistributions in binary form must reproduce the above copyright 2565674Skris * notice, this list of conditions and the following disclaimer in the 2665674Skris * documentation and/or other materials provided with the distribution. 2765674Skris * 2865674Skris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2965674Skris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 3065674Skris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 3165674Skris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 3265674Skris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 3365674Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3465674Skris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3565674Skris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3665674Skris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3765674Skris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3857429Smarkm */ 3957429Smarkm 4057429Smarkm#include "includes.h" 4157429Smarkm 42162856Sdes#include <sys/types.h> 43162856Sdes 4457464Sgreen#include <openssl/bn.h> 45162856Sdes 46162856Sdes#include <string.h> 47162856Sdes#include <stdarg.h> 48162856Sdes 4957429Smarkm#include "xmalloc.h" 50162856Sdes#include "buffer.h" 5176262Sgreen#include "log.h" 52162856Sdes#include "misc.h" 5357429Smarkm 5457429Smarkm/* 5598684Sdes * Returns integers from the buffer (msb first). 5657429Smarkm */ 5798684Sdes 58147005Sdesint 59147005Sdesbuffer_get_short_ret(u_short *ret, Buffer *buffer) 60147005Sdes{ 61147005Sdes u_char buf[2]; 62147005Sdes 63147005Sdes if (buffer_get_ret(buffer, (char *) buf, 2) == -1) 64147005Sdes return (-1); 65162856Sdes *ret = get_u16(buf); 66147005Sdes return (0); 67147005Sdes} 68147005Sdes 6998684Sdesu_short 7098684Sdesbuffer_get_short(Buffer *buffer) 7198684Sdes{ 72147005Sdes u_short ret; 7399063Sdes 74147005Sdes if (buffer_get_short_ret(&ret, buffer) == -1) 75147005Sdes fatal("buffer_get_short: buffer error"); 76147005Sdes 77147005Sdes return (ret); 7898684Sdes} 7998684Sdes 80147005Sdesint 81147005Sdesbuffer_get_int_ret(u_int *ret, Buffer *buffer) 82147005Sdes{ 83147005Sdes u_char buf[4]; 84147005Sdes 85147005Sdes if (buffer_get_ret(buffer, (char *) buf, 4) == -1) 86147005Sdes return (-1); 87215116Sdes if (ret != NULL) 88215116Sdes *ret = get_u32(buf); 89147005Sdes return (0); 90147005Sdes} 91147005Sdes 9276262Sgreenu_int 9357429Smarkmbuffer_get_int(Buffer *buffer) 9457429Smarkm{ 95147005Sdes u_int ret; 9699063Sdes 97147005Sdes if (buffer_get_int_ret(&ret, buffer) == -1) 98147005Sdes fatal("buffer_get_int: buffer error"); 99147005Sdes 100147005Sdes return (ret); 10157429Smarkm} 10257429Smarkm 103147005Sdesint 104147005Sdesbuffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) 105147005Sdes{ 106147005Sdes u_char buf[8]; 107147005Sdes 108147005Sdes if (buffer_get_ret(buffer, (char *) buf, 8) == -1) 109147005Sdes return (-1); 110215116Sdes if (ret != NULL) 111215116Sdes *ret = get_u64(buf); 112147005Sdes return (0); 113147005Sdes} 114147005Sdes 11576262Sgreenu_int64_t 11676262Sgreenbuffer_get_int64(Buffer *buffer) 11776262Sgreen{ 118147005Sdes u_int64_t ret; 11999063Sdes 120147005Sdes if (buffer_get_int64_ret(&ret, buffer) == -1) 121147005Sdes fatal("buffer_get_int: buffer error"); 122147005Sdes 123147005Sdes return (ret); 12476262Sgreen} 12576262Sgreen 12657429Smarkm/* 12798684Sdes * Stores integers in the buffer, msb first. 12857429Smarkm */ 12960576Skrisvoid 13098684Sdesbuffer_put_short(Buffer *buffer, u_short value) 13198684Sdes{ 13298684Sdes char buf[2]; 13399063Sdes 134162856Sdes put_u16(buf, value); 13598684Sdes buffer_append(buffer, buf, 2); 13698684Sdes} 13798684Sdes 13898684Sdesvoid 13976262Sgreenbuffer_put_int(Buffer *buffer, u_int value) 14057429Smarkm{ 14157429Smarkm char buf[4]; 14299063Sdes 143162856Sdes put_u32(buf, value); 14457429Smarkm buffer_append(buffer, buf, 4); 14557429Smarkm} 14657429Smarkm 14776262Sgreenvoid 14876262Sgreenbuffer_put_int64(Buffer *buffer, u_int64_t value) 14976262Sgreen{ 15076262Sgreen char buf[8]; 15199063Sdes 152162856Sdes put_u64(buf, value); 15376262Sgreen buffer_append(buffer, buf, 8); 15476262Sgreen} 15576262Sgreen 15657429Smarkm/* 15757429Smarkm * Returns an arbitrary binary string from the buffer. The string cannot 15857429Smarkm * be longer than 256k. The returned value points to memory allocated 15957429Smarkm * with xmalloc; it is the responsibility of the calling function to free 16057429Smarkm * the data. If length_ptr is non-NULL, the length of the returned data 16157429Smarkm * will be stored there. A null character will be automatically appended 16257429Smarkm * to the returned string, and is not counted in length. 16357429Smarkm */ 16492559Sdesvoid * 165147005Sdesbuffer_get_string_ret(Buffer *buffer, u_int *length_ptr) 16657429Smarkm{ 16799063Sdes u_char *value; 16876262Sgreen u_int len; 16999063Sdes 17057429Smarkm /* Get the length. */ 171204917Sdes if (buffer_get_int_ret(&len, buffer) != 0) { 172204917Sdes error("buffer_get_string_ret: cannot extract length"); 173204917Sdes return (NULL); 174204917Sdes } 175147005Sdes if (len > 256 * 1024) { 176147005Sdes error("buffer_get_string_ret: bad string length %u", len); 177147005Sdes return (NULL); 178147005Sdes } 17957429Smarkm /* Allocate space for the string. Add one byte for a null character. */ 18057429Smarkm value = xmalloc(len + 1); 18157429Smarkm /* Get the string. */ 182147005Sdes if (buffer_get_ret(buffer, value, len) == -1) { 183147005Sdes error("buffer_get_string_ret: buffer_get failed"); 184255767Sdes free(value); 185147005Sdes return (NULL); 186147005Sdes } 18757429Smarkm /* Append a null character to make processing easier. */ 188181111Sdes value[len] = '\0'; 18957429Smarkm /* Optionally return the length of the string. */ 19057429Smarkm if (length_ptr) 19157429Smarkm *length_ptr = len; 192147005Sdes return (value); 19357429Smarkm} 19457429Smarkm 195147005Sdesvoid * 196147005Sdesbuffer_get_string(Buffer *buffer, u_int *length_ptr) 197147005Sdes{ 198147005Sdes void *ret; 199147005Sdes 200147005Sdes if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) 201147005Sdes fatal("buffer_get_string: buffer error"); 202147005Sdes return (ret); 203147005Sdes} 204147005Sdes 205221420Sdeschar * 206221420Sdesbuffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) 207221420Sdes{ 208221420Sdes u_int length; 209221420Sdes char *cp, *ret = buffer_get_string_ret(buffer, &length); 210221420Sdes 211221420Sdes if (ret == NULL) 212221420Sdes return NULL; 213221420Sdes if ((cp = memchr(ret, '\0', length)) != NULL) { 214221420Sdes /* XXX allow \0 at end-of-string for a while, remove later */ 215221420Sdes if (cp == ret + length - 1) 216221420Sdes error("buffer_get_cstring_ret: string contains \\0"); 217221420Sdes else { 218221420Sdes bzero(ret, length); 219255767Sdes free(ret); 220221420Sdes return NULL; 221221420Sdes } 222221420Sdes } 223221420Sdes if (length_ptr != NULL) 224221420Sdes *length_ptr = length; 225221420Sdes return ret; 226221420Sdes} 227221420Sdes 228221420Sdeschar * 229221420Sdesbuffer_get_cstring(Buffer *buffer, u_int *length_ptr) 230221420Sdes{ 231221420Sdes char *ret; 232221420Sdes 233221420Sdes if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) 234221420Sdes fatal("buffer_get_cstring: buffer error"); 235221420Sdes return ret; 236221420Sdes} 237221420Sdes 238181111Sdesvoid * 239204917Sdesbuffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) 240181111Sdes{ 241181111Sdes void *ptr; 242181111Sdes u_int len; 243181111Sdes 244204917Sdes if (buffer_get_int_ret(&len, buffer) != 0) 245204917Sdes return NULL; 246204917Sdes if (len > 256 * 1024) { 247204917Sdes error("buffer_get_string_ptr: bad string length %u", len); 248204917Sdes return NULL; 249204917Sdes } 250181111Sdes ptr = buffer_ptr(buffer); 251181111Sdes buffer_consume(buffer, len); 252181111Sdes if (length_ptr) 253181111Sdes *length_ptr = len; 254181111Sdes return (ptr); 255181111Sdes} 256181111Sdes 257204917Sdesvoid * 258204917Sdesbuffer_get_string_ptr(Buffer *buffer, u_int *length_ptr) 259204917Sdes{ 260204917Sdes void *ret; 261204917Sdes 262204917Sdes if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) 263204917Sdes fatal("buffer_get_string_ptr: buffer error"); 264204917Sdes return (ret); 265204917Sdes} 266204917Sdes 26757429Smarkm/* 26857429Smarkm * Stores and arbitrary binary string in the buffer. 26957429Smarkm */ 27060576Skrisvoid 27176262Sgreenbuffer_put_string(Buffer *buffer, const void *buf, u_int len) 27257429Smarkm{ 27357429Smarkm buffer_put_int(buffer, len); 27457429Smarkm buffer_append(buffer, buf, len); 27557429Smarkm} 27660576Skrisvoid 27760576Skrisbuffer_put_cstring(Buffer *buffer, const char *s) 27860576Skris{ 27998684Sdes if (s == NULL) 28098684Sdes fatal("buffer_put_cstring: s == NULL"); 28160576Skris buffer_put_string(buffer, s, strlen(s)); 28260576Skris} 28357429Smarkm 28457429Smarkm/* 28557429Smarkm * Returns a character from the buffer (0 - 255). 28657429Smarkm */ 28760576Skrisint 288255767Sdesbuffer_get_char_ret(u_char *ret, Buffer *buffer) 289147005Sdes{ 290147005Sdes if (buffer_get_ret(buffer, ret, 1) == -1) { 291147005Sdes error("buffer_get_char_ret: buffer_get_ret failed"); 292147005Sdes return (-1); 293147005Sdes } 294147005Sdes return (0); 295147005Sdes} 296147005Sdes 297147005Sdesint 29857429Smarkmbuffer_get_char(Buffer *buffer) 29957429Smarkm{ 300255767Sdes u_char ch; 30199063Sdes 302147005Sdes if (buffer_get_char_ret(&ch, buffer) == -1) 303147005Sdes fatal("buffer_get_char: buffer error"); 304255767Sdes return ch; 30557429Smarkm} 30657429Smarkm 30757429Smarkm/* 30857429Smarkm * Stores a character in the buffer. 30957429Smarkm */ 31060576Skrisvoid 31157429Smarkmbuffer_put_char(Buffer *buffer, int value) 31257429Smarkm{ 31357429Smarkm char ch = value; 31499063Sdes 31557429Smarkm buffer_append(buffer, &ch, 1); 31657429Smarkm} 317