10Sstevel@tonic-gate /* 2*2757Sjp161948 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 30Sstevel@tonic-gate * Use is subject to license terms. 40Sstevel@tonic-gate */ 50Sstevel@tonic-gate /* 60Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi> 70Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 80Sstevel@tonic-gate * All rights reserved 90Sstevel@tonic-gate * Auxiliary functions for storing and retrieving various data types to/from 100Sstevel@tonic-gate * Buffers. 110Sstevel@tonic-gate * 120Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 130Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 140Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 150Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 160Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * SSH2 packet format added by Markus Friedl 200Sstevel@tonic-gate * Copyright (c) 2000 Markus Friedl. All rights reserved. 210Sstevel@tonic-gate * 220Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 230Sstevel@tonic-gate * modification, are permitted provided that the following conditions 240Sstevel@tonic-gate * are met: 250Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 260Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 270Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 280Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 290Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 300Sstevel@tonic-gate * 310Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 320Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 330Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 340Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 350Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 360Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 370Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 380Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 390Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 400Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 410Sstevel@tonic-gate */ 420Sstevel@tonic-gate 430Sstevel@tonic-gate #include "includes.h" 440Sstevel@tonic-gate RCSID("$OpenBSD: bufaux.c,v 1.27 2002/06/26 08:53:12 markus Exp $"); 450Sstevel@tonic-gate 460Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 470Sstevel@tonic-gate 480Sstevel@tonic-gate #include <langinfo.h> 490Sstevel@tonic-gate #include <openssl/bn.h> 500Sstevel@tonic-gate #include "bufaux.h" 510Sstevel@tonic-gate #include "xmalloc.h" 520Sstevel@tonic-gate #include "getput.h" 530Sstevel@tonic-gate #include "log.h" 540Sstevel@tonic-gate #include "g11n.h" 550Sstevel@tonic-gate 560Sstevel@tonic-gate /* 570Sstevel@tonic-gate * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed 580Sstevel@tonic-gate * by (bits+7)/8 bytes of binary data, msb first. 590Sstevel@tonic-gate */ 60*2757Sjp161948 int 61*2757Sjp161948 buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value) 620Sstevel@tonic-gate { 630Sstevel@tonic-gate int bits = BN_num_bits(value); 640Sstevel@tonic-gate int bin_size = (bits + 7) / 8; 650Sstevel@tonic-gate u_char *buf = xmalloc(bin_size); 660Sstevel@tonic-gate int oi; 670Sstevel@tonic-gate char msg[2]; 680Sstevel@tonic-gate 690Sstevel@tonic-gate /* Get the value of in binary */ 700Sstevel@tonic-gate oi = BN_bn2bin(value, buf); 71*2757Sjp161948 if (oi != bin_size) { 72*2757Sjp161948 error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d", 730Sstevel@tonic-gate oi, bin_size); 74*2757Sjp161948 xfree(buf); 75*2757Sjp161948 return (-1); 76*2757Sjp161948 } 770Sstevel@tonic-gate 780Sstevel@tonic-gate /* Store the number of bits in the buffer in two bytes, msb first. */ 790Sstevel@tonic-gate PUT_16BIT(msg, bits); 800Sstevel@tonic-gate buffer_append(buffer, msg, 2); 810Sstevel@tonic-gate /* Store the binary data. */ 820Sstevel@tonic-gate buffer_append(buffer, (char *)buf, oi); 830Sstevel@tonic-gate 840Sstevel@tonic-gate memset(buf, 0, bin_size); 850Sstevel@tonic-gate xfree(buf); 86*2757Sjp161948 87*2757Sjp161948 return (0); 88*2757Sjp161948 } 89*2757Sjp161948 90*2757Sjp161948 void 91*2757Sjp161948 buffer_put_bignum(Buffer *buffer, const BIGNUM *value) 92*2757Sjp161948 { 93*2757Sjp161948 if (buffer_put_bignum_ret(buffer, value) == -1) 94*2757Sjp161948 fatal("buffer_put_bignum: buffer error"); 950Sstevel@tonic-gate } 960Sstevel@tonic-gate 970Sstevel@tonic-gate /* 980Sstevel@tonic-gate * Retrieves an BIGNUM from the buffer. 990Sstevel@tonic-gate */ 100*2757Sjp161948 int 101*2757Sjp161948 buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value) 1020Sstevel@tonic-gate { 103*2757Sjp161948 u_int bits, bytes; 1040Sstevel@tonic-gate u_char buf[2], *bin; 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate /* Get the number for bits. */ 107*2757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) { 108*2757Sjp161948 error("buffer_get_bignum_ret: invalid length"); 109*2757Sjp161948 return (-1); 110*2757Sjp161948 } 1110Sstevel@tonic-gate bits = GET_16BIT(buf); 1120Sstevel@tonic-gate /* Compute the number of binary bytes that follow. */ 1130Sstevel@tonic-gate bytes = (bits + 7) / 8; 114*2757Sjp161948 if (bytes > 8 * 1024) { 115*2757Sjp161948 error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes); 116*2757Sjp161948 return (-1); 117*2757Sjp161948 } 118*2757Sjp161948 if (buffer_len(buffer) < bytes) { 119*2757Sjp161948 error("buffer_get_bignum_ret: input buffer too small"); 120*2757Sjp161948 return (-1); 121*2757Sjp161948 } 1220Sstevel@tonic-gate bin = buffer_ptr(buffer); 1230Sstevel@tonic-gate BN_bin2bn(bin, bytes, value); 124*2757Sjp161948 if (buffer_consume_ret(buffer, bytes) == -1) { 125*2757Sjp161948 error("buffer_get_bignum_ret: buffer_consume failed"); 126*2757Sjp161948 return (-1); 127*2757Sjp161948 } 128*2757Sjp161948 return (0); 129*2757Sjp161948 } 130*2757Sjp161948 131*2757Sjp161948 void 132*2757Sjp161948 buffer_get_bignum(Buffer *buffer, BIGNUM *value) 133*2757Sjp161948 { 134*2757Sjp161948 if (buffer_get_bignum_ret(buffer, value) == -1) 135*2757Sjp161948 fatal("buffer_get_bignum: buffer error"); 1360Sstevel@tonic-gate } 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate /* 1390Sstevel@tonic-gate * Stores an BIGNUM in the buffer in SSH2 format. 1400Sstevel@tonic-gate */ 141*2757Sjp161948 int 142*2757Sjp161948 buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value) 1430Sstevel@tonic-gate { 144*2757Sjp161948 u_int bytes; 145*2757Sjp161948 u_char *buf; 1460Sstevel@tonic-gate int oi; 147*2757Sjp161948 u_int hasnohigh = 0; 1480Sstevel@tonic-gate 149*2757Sjp161948 if (BN_is_zero(value)) { 150*2757Sjp161948 buffer_put_int(buffer, 0); 151*2757Sjp161948 return 0; 152*2757Sjp161948 } 153*2757Sjp161948 if (value->neg) { 154*2757Sjp161948 error("buffer_put_bignum2_ret: negative numbers not supported"); 155*2757Sjp161948 return (-1); 156*2757Sjp161948 } 157*2757Sjp161948 bytes = BN_num_bytes(value) + 1; /* extra padding byte */ 158*2757Sjp161948 if (bytes < 2) { 159*2757Sjp161948 error("buffer_put_bignum2_ret: BN too small"); 160*2757Sjp161948 return (-1); 161*2757Sjp161948 } 162*2757Sjp161948 buf = xmalloc(bytes); 163*2757Sjp161948 buf[0] = 0x00; 1640Sstevel@tonic-gate /* Get the value of in binary */ 1650Sstevel@tonic-gate oi = BN_bn2bin(value, buf+1); 166*2757Sjp161948 if (oi < 0 || (u_int)oi != bytes - 1) { 167*2757Sjp161948 error("buffer_put_bignum2_ret: BN_bn2bin() failed: " 168*2757Sjp161948 "oi %d != bin_size %d", oi, bytes); 169*2757Sjp161948 xfree(buf); 170*2757Sjp161948 return (-1); 171*2757Sjp161948 } 1720Sstevel@tonic-gate hasnohigh = (buf[1] & 0x80) ? 0 : 1; 1730Sstevel@tonic-gate buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); 1740Sstevel@tonic-gate memset(buf, 0, bytes); 1750Sstevel@tonic-gate xfree(buf); 176*2757Sjp161948 return (0); 177*2757Sjp161948 } 178*2757Sjp161948 179*2757Sjp161948 void 180*2757Sjp161948 buffer_put_bignum2(Buffer *buffer, const BIGNUM *value) 181*2757Sjp161948 { 182*2757Sjp161948 if (buffer_put_bignum2_ret(buffer, value) == -1) 183*2757Sjp161948 fatal("buffer_put_bignum2: buffer error"); 1840Sstevel@tonic-gate } 1850Sstevel@tonic-gate 1860Sstevel@tonic-gate /* XXX does not handle negative BNs */ 187*2757Sjp161948 int 188*2757Sjp161948 buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value) 189*2757Sjp161948 { 190*2757Sjp161948 u_int len; 191*2757Sjp161948 u_char *bin; 192*2757Sjp161948 193*2757Sjp161948 if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) { 194*2757Sjp161948 error("buffer_get_bignum2_ret: invalid bignum"); 195*2757Sjp161948 return (-1); 196*2757Sjp161948 } 197*2757Sjp161948 198*2757Sjp161948 if (len > 0 && (bin[0] & 0x80)) { 199*2757Sjp161948 error("buffer_get_bignum2_ret: negative numbers not supported"); 200*2757Sjp161948 xfree(bin); 201*2757Sjp161948 return (-1); 202*2757Sjp161948 } 203*2757Sjp161948 if (len > 8 * 1024) { 204*2757Sjp161948 error("buffer_get_bignum2_ret: cannot handle BN of size %d", len); 205*2757Sjp161948 xfree(bin); 206*2757Sjp161948 return (-1); 207*2757Sjp161948 } 208*2757Sjp161948 BN_bin2bn(bin, len, value); 209*2757Sjp161948 xfree(bin); 210*2757Sjp161948 return (0); 211*2757Sjp161948 } 212*2757Sjp161948 2130Sstevel@tonic-gate void 2140Sstevel@tonic-gate buffer_get_bignum2(Buffer *buffer, BIGNUM *value) 2150Sstevel@tonic-gate { 216*2757Sjp161948 if (buffer_get_bignum2_ret(buffer, value) == -1) 217*2757Sjp161948 fatal("buffer_get_bignum2: buffer error"); 218*2757Sjp161948 } 2190Sstevel@tonic-gate 2200Sstevel@tonic-gate /* 2210Sstevel@tonic-gate * Returns integers from the buffer (msb first). 2220Sstevel@tonic-gate */ 2230Sstevel@tonic-gate 224*2757Sjp161948 int 225*2757Sjp161948 buffer_get_short_ret(u_short *ret, Buffer *buffer) 226*2757Sjp161948 { 227*2757Sjp161948 u_char buf[2]; 228*2757Sjp161948 229*2757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) 230*2757Sjp161948 return (-1); 231*2757Sjp161948 *ret = GET_16BIT(buf); 232*2757Sjp161948 return (0); 233*2757Sjp161948 } 234*2757Sjp161948 2350Sstevel@tonic-gate u_short 2360Sstevel@tonic-gate buffer_get_short(Buffer *buffer) 2370Sstevel@tonic-gate { 238*2757Sjp161948 u_short ret; 239*2757Sjp161948 240*2757Sjp161948 if (buffer_get_short_ret(&ret, buffer) == -1) 241*2757Sjp161948 fatal("buffer_get_short: buffer error"); 242*2757Sjp161948 243*2757Sjp161948 return (ret); 244*2757Sjp161948 } 2450Sstevel@tonic-gate 246*2757Sjp161948 int 247*2757Sjp161948 buffer_get_int_ret(u_int *ret, Buffer *buffer) 248*2757Sjp161948 { 249*2757Sjp161948 u_char buf[4]; 250*2757Sjp161948 251*2757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 4) == -1) 252*2757Sjp161948 return (-1); 253*2757Sjp161948 *ret = GET_32BIT(buf); 254*2757Sjp161948 return (0); 2550Sstevel@tonic-gate } 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate u_int 2580Sstevel@tonic-gate buffer_get_int(Buffer *buffer) 2590Sstevel@tonic-gate { 260*2757Sjp161948 u_int ret; 2610Sstevel@tonic-gate 262*2757Sjp161948 if (buffer_get_int_ret(&ret, buffer) == -1) 263*2757Sjp161948 fatal("buffer_get_int: buffer error"); 264*2757Sjp161948 265*2757Sjp161948 return (ret); 2660Sstevel@tonic-gate } 2670Sstevel@tonic-gate 2680Sstevel@tonic-gate #ifdef HAVE_U_INT64_T 269*2757Sjp161948 int 270*2757Sjp161948 buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) 271*2757Sjp161948 { 272*2757Sjp161948 u_char buf[8]; 273*2757Sjp161948 274*2757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 8) == -1) 275*2757Sjp161948 return (-1); 276*2757Sjp161948 *ret = GET_64BIT(buf); 277*2757Sjp161948 return (0); 278*2757Sjp161948 } 279*2757Sjp161948 2800Sstevel@tonic-gate u_int64_t 2810Sstevel@tonic-gate buffer_get_int64(Buffer *buffer) 2820Sstevel@tonic-gate { 283*2757Sjp161948 u_int64_t ret; 2840Sstevel@tonic-gate 285*2757Sjp161948 if (buffer_get_int64_ret(&ret, buffer) == -1) 286*2757Sjp161948 fatal("buffer_get_int: buffer error"); 287*2757Sjp161948 288*2757Sjp161948 return (ret); 2890Sstevel@tonic-gate } 2900Sstevel@tonic-gate #endif 2910Sstevel@tonic-gate 2920Sstevel@tonic-gate /* 2930Sstevel@tonic-gate * Stores integers in the buffer, msb first. 2940Sstevel@tonic-gate */ 2950Sstevel@tonic-gate void 2960Sstevel@tonic-gate buffer_put_short(Buffer *buffer, u_short value) 2970Sstevel@tonic-gate { 2980Sstevel@tonic-gate char buf[2]; 2990Sstevel@tonic-gate 3000Sstevel@tonic-gate PUT_16BIT(buf, value); 3010Sstevel@tonic-gate buffer_append(buffer, buf, 2); 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate 3040Sstevel@tonic-gate void 3050Sstevel@tonic-gate buffer_put_int(Buffer *buffer, u_int value) 3060Sstevel@tonic-gate { 3070Sstevel@tonic-gate char buf[4]; 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate PUT_32BIT(buf, value); 3100Sstevel@tonic-gate buffer_append(buffer, buf, 4); 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate #ifdef HAVE_U_INT64_T 3140Sstevel@tonic-gate void 3150Sstevel@tonic-gate buffer_put_int64(Buffer *buffer, u_int64_t value) 3160Sstevel@tonic-gate { 3170Sstevel@tonic-gate char buf[8]; 3180Sstevel@tonic-gate 3190Sstevel@tonic-gate PUT_64BIT(buf, value); 3200Sstevel@tonic-gate buffer_append(buffer, buf, 8); 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate #endif 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate /* 3250Sstevel@tonic-gate * Returns an arbitrary binary string from the buffer. The string cannot 3260Sstevel@tonic-gate * be longer than 256k. The returned value points to memory allocated 3270Sstevel@tonic-gate * with xmalloc; it is the responsibility of the calling function to free 3280Sstevel@tonic-gate * the data. If length_ptr is non-NULL, the length of the returned data 3290Sstevel@tonic-gate * will be stored there. A null character will be automatically appended 3300Sstevel@tonic-gate * to the returned string, and is not counted in length. 3310Sstevel@tonic-gate */ 3320Sstevel@tonic-gate void * 333*2757Sjp161948 buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) 3340Sstevel@tonic-gate { 3350Sstevel@tonic-gate u_char *value; 3360Sstevel@tonic-gate u_int len; 3370Sstevel@tonic-gate 3380Sstevel@tonic-gate /* Get the length. */ 3390Sstevel@tonic-gate len = buffer_get_int(buffer); 340*2757Sjp161948 if (len > 256 * 1024) { 341*2757Sjp161948 error("buffer_get_string_ret: bad string length %u", len); 342*2757Sjp161948 return (NULL); 343*2757Sjp161948 } 3440Sstevel@tonic-gate /* Allocate space for the string. Add one byte for a null character. */ 3450Sstevel@tonic-gate value = xmalloc(len + 1); 3460Sstevel@tonic-gate /* Get the string. */ 347*2757Sjp161948 if (buffer_get_ret(buffer, value, len) == -1) { 348*2757Sjp161948 error("buffer_get_string_ret: buffer_get failed"); 349*2757Sjp161948 xfree(value); 350*2757Sjp161948 return (NULL); 351*2757Sjp161948 } 3520Sstevel@tonic-gate /* Append a null character to make processing easier. */ 3530Sstevel@tonic-gate value[len] = 0; 3540Sstevel@tonic-gate /* Optionally return the length of the string. */ 3550Sstevel@tonic-gate if (length_ptr) 3560Sstevel@tonic-gate *length_ptr = len; 357*2757Sjp161948 return (value); 3580Sstevel@tonic-gate } 359*2757Sjp161948 360*2757Sjp161948 void * 361*2757Sjp161948 buffer_get_string(Buffer *buffer, u_int *length_ptr) 362*2757Sjp161948 { 363*2757Sjp161948 void *ret; 364*2757Sjp161948 365*2757Sjp161948 if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) 366*2757Sjp161948 fatal("buffer_get_string: buffer error"); 367*2757Sjp161948 return (ret); 368*2757Sjp161948 } 369*2757Sjp161948 3700Sstevel@tonic-gate char * 3710Sstevel@tonic-gate buffer_get_ascii_cstring(Buffer *buffer) 3720Sstevel@tonic-gate { 3730Sstevel@tonic-gate char *value; 3740Sstevel@tonic-gate u_char *p; 3750Sstevel@tonic-gate u_int len; 3760Sstevel@tonic-gate value = buffer_get_string(buffer, &len); 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate /* Look for NULL or high-bit set bytes */ 3790Sstevel@tonic-gate for (p = (u_char *) value ; 3800Sstevel@tonic-gate p && *p && (!(*p & 0x80)) && (p - (u_char *) value) < len ; 3810Sstevel@tonic-gate p++) ; 3820Sstevel@tonic-gate 3830Sstevel@tonic-gate /* If there were any, bomb */ 3840Sstevel@tonic-gate if ((p - (u_char *) value) != len) { 3850Sstevel@tonic-gate xfree(value); 3860Sstevel@tonic-gate errno = EILSEQ; 3870Sstevel@tonic-gate return NULL; 3880Sstevel@tonic-gate } 3890Sstevel@tonic-gate return value; 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate u_char * 3920Sstevel@tonic-gate buffer_get_utf8_cstring(Buffer *buffer) 3930Sstevel@tonic-gate { 3940Sstevel@tonic-gate u_char *value, *converted, *estr; 3950Sstevel@tonic-gate u_int len; 3960Sstevel@tonic-gate int err; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate if ((value = buffer_get_string(buffer, &len)) == NULL) { 3990Sstevel@tonic-gate return value; 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate converted = g11n_convert_from_utf8(value, &err, &estr); 4030Sstevel@tonic-gate 4040Sstevel@tonic-gate if (converted != value) xfree(value); 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate if (err) 4070Sstevel@tonic-gate fatal("invalid UTF-8 sequence; %s", estr); 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate return converted; 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate /* 4130Sstevel@tonic-gate * Stores and arbitrary binary string in the buffer. 4140Sstevel@tonic-gate */ 4150Sstevel@tonic-gate void 4160Sstevel@tonic-gate buffer_put_string(Buffer *buffer, const void *buf, u_int len) 4170Sstevel@tonic-gate { 4180Sstevel@tonic-gate buffer_put_int(buffer, len); 4190Sstevel@tonic-gate buffer_append(buffer, buf, len); 4200Sstevel@tonic-gate } 4210Sstevel@tonic-gate void 4220Sstevel@tonic-gate buffer_put_cstring(Buffer *buffer, const char *s) 4230Sstevel@tonic-gate { 4240Sstevel@tonic-gate if (s == NULL) 4250Sstevel@tonic-gate fatal("buffer_put_cstring: s == NULL"); 4260Sstevel@tonic-gate buffer_put_string(buffer, s, strlen(s)); 4270Sstevel@tonic-gate } 4280Sstevel@tonic-gate 4290Sstevel@tonic-gate /* 4300Sstevel@tonic-gate * ASCII versions of the above 4310Sstevel@tonic-gate */ 4320Sstevel@tonic-gate #if 0 4330Sstevel@tonic-gate void 4340Sstevel@tonic-gate buffer_put_ascii_string(Buffer *buffer, const void *buf, u_int len) 4350Sstevel@tonic-gate { 4360Sstevel@tonic-gate u_char *p; 4370Sstevel@tonic-gate for (p = (u_char *) buf ; 4380Sstevel@tonic-gate p && ((p - (u_char *) buf) < len) && *p && (!(*p & 0x80)) ; 4390Sstevel@tonic-gate p++) ; 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate if ((p - (u_char *) buf) != len) 4420Sstevel@tonic-gate verbose("buffer_put_ascii_string: storing a non-ASCII string"); 4430Sstevel@tonic-gate buffer_put_int(buffer, len); 4440Sstevel@tonic-gate buffer_append(buffer, buf, len); 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate #endif 4470Sstevel@tonic-gate void 4480Sstevel@tonic-gate buffer_put_ascii_cstring(Buffer *buffer, const char *s) 4490Sstevel@tonic-gate { 4500Sstevel@tonic-gate u_char *estr; 4510Sstevel@tonic-gate if (s == NULL) 4520Sstevel@tonic-gate fatal("buffer_put_cstring: s == NULL"); 4530Sstevel@tonic-gate 4540Sstevel@tonic-gate if (!g11n_validate_ascii(s, strlen(s), &estr)) 4550Sstevel@tonic-gate verbose("buffer_put_ascii_cstring: non-ASCII string; %s", estr); 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate buffer_put_cstring(buffer, s); 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate /* 4610Sstevel@tonic-gate * UTF-8 versions of the above. 4620Sstevel@tonic-gate */ 4630Sstevel@tonic-gate 4640Sstevel@tonic-gate #if 0 4650Sstevel@tonic-gate void 4660Sstevel@tonic-gate buffer_put_utf8_string(Buffer *buffer, const void *buf, u_int len) 4670Sstevel@tonic-gate { 4680Sstevel@tonic-gate char *converted *estr; 4690Sstevel@tonic-gate 4700Sstevel@tonic-gate converted = g11n_convert_to_utf8(buf, &err, &estr); 4710Sstevel@tonic-gate 4720Sstevel@tonic-gate if (!converted && err) 4730Sstevel@tonic-gate fatal("buffer_put_utf8_string: input not a valid UTF-8 encoding; %s", estr); 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate if (err) 4760Sstevel@tonic-gate verbose("buffer_put_utf8_string: input not a valid UTF-8 encoding; %s", estr); 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate buffer_put_string(buffer, converted, strlen(converted)); 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate if (converted != bug) xfree(converted); 4810Sstevel@tonic-gate 4820Sstevel@tonic-gate return; 4830Sstevel@tonic-gate } 4840Sstevel@tonic-gate #endif 4850Sstevel@tonic-gate void 4860Sstevel@tonic-gate buffer_put_utf8_cstring(Buffer *buffer, const u_char *s) 4870Sstevel@tonic-gate { 4880Sstevel@tonic-gate u_char *converted, *estr; 4890Sstevel@tonic-gate int err; 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate if (s == NULL) 4920Sstevel@tonic-gate fatal("buffer_put_cstring: s == NULL"); 4930Sstevel@tonic-gate 4940Sstevel@tonic-gate converted = g11n_convert_to_utf8(s, &err, &estr); 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate if (!converted && err) 4970Sstevel@tonic-gate fatal("buffer_put_utf8_string: input not a valid UTF-8 encoding; %s", estr); 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate if (err) 5000Sstevel@tonic-gate verbose("buffer_put_utf8_string: input not a valid UTF-8 encoding; %s", estr); 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate buffer_put_cstring(buffer, (const char *) converted); 5030Sstevel@tonic-gate 5040Sstevel@tonic-gate if (converted != s) xfree(converted); 5050Sstevel@tonic-gate 5060Sstevel@tonic-gate return; 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate /* 5110Sstevel@tonic-gate * Returns a character from the buffer (0 - 255). 5120Sstevel@tonic-gate */ 5130Sstevel@tonic-gate int 514*2757Sjp161948 buffer_get_char_ret(char *ret, Buffer *buffer) 515*2757Sjp161948 { 516*2757Sjp161948 if (buffer_get_ret(buffer, ret, 1) == -1) { 517*2757Sjp161948 error("buffer_get_char_ret: buffer_get_ret failed"); 518*2757Sjp161948 return (-1); 519*2757Sjp161948 } 520*2757Sjp161948 return (0); 521*2757Sjp161948 } 522*2757Sjp161948 523*2757Sjp161948 int 5240Sstevel@tonic-gate buffer_get_char(Buffer *buffer) 5250Sstevel@tonic-gate { 5260Sstevel@tonic-gate char ch; 5270Sstevel@tonic-gate 528*2757Sjp161948 if (buffer_get_char_ret(&ch, buffer) == -1) 529*2757Sjp161948 fatal("buffer_get_char: buffer error"); 5300Sstevel@tonic-gate return (u_char) ch; 5310Sstevel@tonic-gate } 5320Sstevel@tonic-gate 5330Sstevel@tonic-gate /* 5340Sstevel@tonic-gate * Stores a character in the buffer. 5350Sstevel@tonic-gate */ 5360Sstevel@tonic-gate void 5370Sstevel@tonic-gate buffer_put_char(Buffer *buffer, int value) 5380Sstevel@tonic-gate { 5390Sstevel@tonic-gate char ch = value; 5400Sstevel@tonic-gate 5410Sstevel@tonic-gate buffer_append(buffer, &ch, 1); 5420Sstevel@tonic-gate } 543