1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate /* 6*0Sstevel@tonic-gate * Author: Tatu Ylonen <ylo@cs.hut.fi> 7*0Sstevel@tonic-gate * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 8*0Sstevel@tonic-gate * All rights reserved 9*0Sstevel@tonic-gate * Auxiliary functions for storing and retrieving various data types to/from 10*0Sstevel@tonic-gate * Buffers. 11*0Sstevel@tonic-gate * 12*0Sstevel@tonic-gate * As far as I am concerned, the code I have written for this software 13*0Sstevel@tonic-gate * can be used freely for any purpose. Any derived versions of this 14*0Sstevel@tonic-gate * software must be clearly marked as such, and if the derived work is 15*0Sstevel@tonic-gate * incompatible with the protocol description in the RFC file, it must be 16*0Sstevel@tonic-gate * called by a name other than "ssh" or "Secure Shell". 17*0Sstevel@tonic-gate * 18*0Sstevel@tonic-gate * 19*0Sstevel@tonic-gate * SSH2 packet format added by Markus Friedl 20*0Sstevel@tonic-gate * Copyright (c) 2000 Markus Friedl. All rights reserved. 21*0Sstevel@tonic-gate * 22*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 23*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 24*0Sstevel@tonic-gate * are met: 25*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 26*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 27*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 28*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 29*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 30*0Sstevel@tonic-gate * 31*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 32*0Sstevel@tonic-gate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 33*0Sstevel@tonic-gate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 34*0Sstevel@tonic-gate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 35*0Sstevel@tonic-gate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 36*0Sstevel@tonic-gate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 37*0Sstevel@tonic-gate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 38*0Sstevel@tonic-gate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 39*0Sstevel@tonic-gate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 40*0Sstevel@tonic-gate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 41*0Sstevel@tonic-gate */ 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate #include "includes.h" 44*0Sstevel@tonic-gate RCSID("$OpenBSD: bufaux.c,v 1.27 2002/06/26 08:53:12 markus Exp $"); 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #include <langinfo.h> 49*0Sstevel@tonic-gate #include <openssl/bn.h> 50*0Sstevel@tonic-gate #include "bufaux.h" 51*0Sstevel@tonic-gate #include "xmalloc.h" 52*0Sstevel@tonic-gate #include "getput.h" 53*0Sstevel@tonic-gate #include "log.h" 54*0Sstevel@tonic-gate #include "g11n.h" 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate /* 57*0Sstevel@tonic-gate * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed 58*0Sstevel@tonic-gate * by (bits+7)/8 bytes of binary data, msb first. 59*0Sstevel@tonic-gate */ 60*0Sstevel@tonic-gate void 61*0Sstevel@tonic-gate buffer_put_bignum(Buffer *buffer, BIGNUM *value) 62*0Sstevel@tonic-gate { 63*0Sstevel@tonic-gate int bits = BN_num_bits(value); 64*0Sstevel@tonic-gate int bin_size = (bits + 7) / 8; 65*0Sstevel@tonic-gate u_char *buf = xmalloc(bin_size); 66*0Sstevel@tonic-gate int oi; 67*0Sstevel@tonic-gate char msg[2]; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate /* Get the value of in binary */ 70*0Sstevel@tonic-gate oi = BN_bn2bin(value, buf); 71*0Sstevel@tonic-gate if (oi != bin_size) 72*0Sstevel@tonic-gate fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d", 73*0Sstevel@tonic-gate oi, bin_size); 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate /* Store the number of bits in the buffer in two bytes, msb first. */ 76*0Sstevel@tonic-gate PUT_16BIT(msg, bits); 77*0Sstevel@tonic-gate buffer_append(buffer, msg, 2); 78*0Sstevel@tonic-gate /* Store the binary data. */ 79*0Sstevel@tonic-gate buffer_append(buffer, (char *)buf, oi); 80*0Sstevel@tonic-gate 81*0Sstevel@tonic-gate memset(buf, 0, bin_size); 82*0Sstevel@tonic-gate xfree(buf); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* 86*0Sstevel@tonic-gate * Retrieves an BIGNUM from the buffer. 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate void 89*0Sstevel@tonic-gate buffer_get_bignum(Buffer *buffer, BIGNUM *value) 90*0Sstevel@tonic-gate { 91*0Sstevel@tonic-gate int bits, bytes; 92*0Sstevel@tonic-gate u_char buf[2], *bin; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate /* Get the number for bits. */ 95*0Sstevel@tonic-gate buffer_get(buffer, (char *) buf, 2); 96*0Sstevel@tonic-gate bits = GET_16BIT(buf); 97*0Sstevel@tonic-gate /* Compute the number of binary bytes that follow. */ 98*0Sstevel@tonic-gate bytes = (bits + 7) / 8; 99*0Sstevel@tonic-gate if (bytes > 8 * 1024) 100*0Sstevel@tonic-gate fatal("buffer_get_bignum: cannot handle BN of size %d", bytes); 101*0Sstevel@tonic-gate if (buffer_len(buffer) < bytes) 102*0Sstevel@tonic-gate fatal("buffer_get_bignum: input buffer too small"); 103*0Sstevel@tonic-gate bin = buffer_ptr(buffer); 104*0Sstevel@tonic-gate BN_bin2bn(bin, bytes, value); 105*0Sstevel@tonic-gate buffer_consume(buffer, bytes); 106*0Sstevel@tonic-gate } 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate /* 109*0Sstevel@tonic-gate * Stores an BIGNUM in the buffer in SSH2 format. 110*0Sstevel@tonic-gate */ 111*0Sstevel@tonic-gate void 112*0Sstevel@tonic-gate buffer_put_bignum2(Buffer *buffer, BIGNUM *value) 113*0Sstevel@tonic-gate { 114*0Sstevel@tonic-gate int bytes = BN_num_bytes(value) + 1; 115*0Sstevel@tonic-gate u_char *buf = xmalloc(bytes); 116*0Sstevel@tonic-gate int oi; 117*0Sstevel@tonic-gate int hasnohigh = 0; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate buf[0] = '\0'; 120*0Sstevel@tonic-gate /* Get the value of in binary */ 121*0Sstevel@tonic-gate oi = BN_bn2bin(value, buf+1); 122*0Sstevel@tonic-gate if (oi != bytes-1) 123*0Sstevel@tonic-gate fatal("buffer_put_bignum: BN_bn2bin() failed: oi %d != bin_size %d", 124*0Sstevel@tonic-gate oi, bytes); 125*0Sstevel@tonic-gate hasnohigh = (buf[1] & 0x80) ? 0 : 1; 126*0Sstevel@tonic-gate if (value->neg) { 127*0Sstevel@tonic-gate /**XXX should be two's-complement */ 128*0Sstevel@tonic-gate int i, carry; 129*0Sstevel@tonic-gate u_char *uc = buf; 130*0Sstevel@tonic-gate log("negativ!"); 131*0Sstevel@tonic-gate for (i = bytes-1, carry = 1; i>=0; i--) { 132*0Sstevel@tonic-gate uc[i] ^= 0xff; 133*0Sstevel@tonic-gate if (carry) 134*0Sstevel@tonic-gate carry = !++uc[i]; 135*0Sstevel@tonic-gate } 136*0Sstevel@tonic-gate } 137*0Sstevel@tonic-gate buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); 138*0Sstevel@tonic-gate memset(buf, 0, bytes); 139*0Sstevel@tonic-gate xfree(buf); 140*0Sstevel@tonic-gate } 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate /* XXX does not handle negative BNs */ 143*0Sstevel@tonic-gate void 144*0Sstevel@tonic-gate buffer_get_bignum2(Buffer *buffer, BIGNUM *value) 145*0Sstevel@tonic-gate { 146*0Sstevel@tonic-gate u_int len; 147*0Sstevel@tonic-gate u_char *bin = buffer_get_string(buffer, &len); 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate if (len > 8 * 1024) 150*0Sstevel@tonic-gate fatal("buffer_get_bignum2: cannot handle BN of size %d", len); 151*0Sstevel@tonic-gate BN_bin2bn(bin, len, value); 152*0Sstevel@tonic-gate xfree(bin); 153*0Sstevel@tonic-gate } 154*0Sstevel@tonic-gate /* 155*0Sstevel@tonic-gate * Returns integers from the buffer (msb first). 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gate u_short 159*0Sstevel@tonic-gate buffer_get_short(Buffer *buffer) 160*0Sstevel@tonic-gate { 161*0Sstevel@tonic-gate u_char buf[2]; 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate buffer_get(buffer, (char *) buf, 2); 164*0Sstevel@tonic-gate return GET_16BIT(buf); 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate u_int 168*0Sstevel@tonic-gate buffer_get_int(Buffer *buffer) 169*0Sstevel@tonic-gate { 170*0Sstevel@tonic-gate u_char buf[4]; 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate buffer_get(buffer, (char *) buf, 4); 173*0Sstevel@tonic-gate return GET_32BIT(buf); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate 176*0Sstevel@tonic-gate #ifdef HAVE_U_INT64_T 177*0Sstevel@tonic-gate u_int64_t 178*0Sstevel@tonic-gate buffer_get_int64(Buffer *buffer) 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate u_char buf[8]; 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate buffer_get(buffer, (char *) buf, 8); 183*0Sstevel@tonic-gate return GET_64BIT(buf); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate #endif 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate /* 188*0Sstevel@tonic-gate * Stores integers in the buffer, msb first. 189*0Sstevel@tonic-gate */ 190*0Sstevel@tonic-gate void 191*0Sstevel@tonic-gate buffer_put_short(Buffer *buffer, u_short value) 192*0Sstevel@tonic-gate { 193*0Sstevel@tonic-gate char buf[2]; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate PUT_16BIT(buf, value); 196*0Sstevel@tonic-gate buffer_append(buffer, buf, 2); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate void 200*0Sstevel@tonic-gate buffer_put_int(Buffer *buffer, u_int value) 201*0Sstevel@tonic-gate { 202*0Sstevel@tonic-gate char buf[4]; 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate PUT_32BIT(buf, value); 205*0Sstevel@tonic-gate buffer_append(buffer, buf, 4); 206*0Sstevel@tonic-gate } 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate #ifdef HAVE_U_INT64_T 209*0Sstevel@tonic-gate void 210*0Sstevel@tonic-gate buffer_put_int64(Buffer *buffer, u_int64_t value) 211*0Sstevel@tonic-gate { 212*0Sstevel@tonic-gate char buf[8]; 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate PUT_64BIT(buf, value); 215*0Sstevel@tonic-gate buffer_append(buffer, buf, 8); 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate #endif 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate /* 220*0Sstevel@tonic-gate * Returns an arbitrary binary string from the buffer. The string cannot 221*0Sstevel@tonic-gate * be longer than 256k. The returned value points to memory allocated 222*0Sstevel@tonic-gate * with xmalloc; it is the responsibility of the calling function to free 223*0Sstevel@tonic-gate * the data. If length_ptr is non-NULL, the length of the returned data 224*0Sstevel@tonic-gate * will be stored there. A null character will be automatically appended 225*0Sstevel@tonic-gate * to the returned string, and is not counted in length. 226*0Sstevel@tonic-gate */ 227*0Sstevel@tonic-gate void * 228*0Sstevel@tonic-gate buffer_get_string(Buffer *buffer, u_int *length_ptr) 229*0Sstevel@tonic-gate { 230*0Sstevel@tonic-gate u_char *value; 231*0Sstevel@tonic-gate u_int len; 232*0Sstevel@tonic-gate 233*0Sstevel@tonic-gate /* Get the length. */ 234*0Sstevel@tonic-gate len = buffer_get_int(buffer); 235*0Sstevel@tonic-gate if (len > 256 * 1024) 236*0Sstevel@tonic-gate fatal("buffer_get_string: bad string length %d", len); 237*0Sstevel@tonic-gate /* Allocate space for the string. Add one byte for a null character. */ 238*0Sstevel@tonic-gate value = xmalloc(len + 1); 239*0Sstevel@tonic-gate /* Get the string. */ 240*0Sstevel@tonic-gate buffer_get(buffer, value, len); 241*0Sstevel@tonic-gate /* Append a null character to make processing easier. */ 242*0Sstevel@tonic-gate value[len] = 0; 243*0Sstevel@tonic-gate /* Optionally return the length of the string. */ 244*0Sstevel@tonic-gate if (length_ptr) 245*0Sstevel@tonic-gate *length_ptr = len; 246*0Sstevel@tonic-gate return value; 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate char * 249*0Sstevel@tonic-gate buffer_get_ascii_cstring(Buffer *buffer) 250*0Sstevel@tonic-gate { 251*0Sstevel@tonic-gate char *value; 252*0Sstevel@tonic-gate u_char *p; 253*0Sstevel@tonic-gate u_int len; 254*0Sstevel@tonic-gate value = buffer_get_string(buffer, &len); 255*0Sstevel@tonic-gate 256*0Sstevel@tonic-gate /* Look for NULL or high-bit set bytes */ 257*0Sstevel@tonic-gate for (p = (u_char *) value ; 258*0Sstevel@tonic-gate p && *p && (!(*p & 0x80)) && (p - (u_char *) value) < len ; 259*0Sstevel@tonic-gate p++) ; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* If there were any, bomb */ 262*0Sstevel@tonic-gate if ((p - (u_char *) value) != len) { 263*0Sstevel@tonic-gate xfree(value); 264*0Sstevel@tonic-gate errno = EILSEQ; 265*0Sstevel@tonic-gate return NULL; 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate return value; 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate u_char * 270*0Sstevel@tonic-gate buffer_get_utf8_cstring(Buffer *buffer) 271*0Sstevel@tonic-gate { 272*0Sstevel@tonic-gate u_char *value, *converted, *estr; 273*0Sstevel@tonic-gate u_int len; 274*0Sstevel@tonic-gate int err; 275*0Sstevel@tonic-gate 276*0Sstevel@tonic-gate if ((value = buffer_get_string(buffer, &len)) == NULL) { 277*0Sstevel@tonic-gate return value; 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate converted = g11n_convert_from_utf8(value, &err, &estr); 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate if (converted != value) xfree(value); 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate if (err) 285*0Sstevel@tonic-gate fatal("invalid UTF-8 sequence; %s", estr); 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate return converted; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate /* 291*0Sstevel@tonic-gate * Stores and arbitrary binary string in the buffer. 292*0Sstevel@tonic-gate */ 293*0Sstevel@tonic-gate void 294*0Sstevel@tonic-gate buffer_put_string(Buffer *buffer, const void *buf, u_int len) 295*0Sstevel@tonic-gate { 296*0Sstevel@tonic-gate buffer_put_int(buffer, len); 297*0Sstevel@tonic-gate buffer_append(buffer, buf, len); 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate void 300*0Sstevel@tonic-gate buffer_put_cstring(Buffer *buffer, const char *s) 301*0Sstevel@tonic-gate { 302*0Sstevel@tonic-gate if (s == NULL) 303*0Sstevel@tonic-gate fatal("buffer_put_cstring: s == NULL"); 304*0Sstevel@tonic-gate buffer_put_string(buffer, s, strlen(s)); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* 308*0Sstevel@tonic-gate * ASCII versions of the above 309*0Sstevel@tonic-gate */ 310*0Sstevel@tonic-gate #if 0 311*0Sstevel@tonic-gate void 312*0Sstevel@tonic-gate buffer_put_ascii_string(Buffer *buffer, const void *buf, u_int len) 313*0Sstevel@tonic-gate { 314*0Sstevel@tonic-gate u_char *p; 315*0Sstevel@tonic-gate for (p = (u_char *) buf ; 316*0Sstevel@tonic-gate p && ((p - (u_char *) buf) < len) && *p && (!(*p & 0x80)) ; 317*0Sstevel@tonic-gate p++) ; 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate if ((p - (u_char *) buf) != len) 320*0Sstevel@tonic-gate verbose("buffer_put_ascii_string: storing a non-ASCII string"); 321*0Sstevel@tonic-gate buffer_put_int(buffer, len); 322*0Sstevel@tonic-gate buffer_append(buffer, buf, len); 323*0Sstevel@tonic-gate } 324*0Sstevel@tonic-gate #endif 325*0Sstevel@tonic-gate void 326*0Sstevel@tonic-gate buffer_put_ascii_cstring(Buffer *buffer, const char *s) 327*0Sstevel@tonic-gate { 328*0Sstevel@tonic-gate u_char *estr; 329*0Sstevel@tonic-gate if (s == NULL) 330*0Sstevel@tonic-gate fatal("buffer_put_cstring: s == NULL"); 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate if (!g11n_validate_ascii(s, strlen(s), &estr)) 333*0Sstevel@tonic-gate verbose("buffer_put_ascii_cstring: non-ASCII string; %s", estr); 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate buffer_put_cstring(buffer, s); 336*0Sstevel@tonic-gate } 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* 339*0Sstevel@tonic-gate * UTF-8 versions of the above. 340*0Sstevel@tonic-gate */ 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate #if 0 343*0Sstevel@tonic-gate void 344*0Sstevel@tonic-gate buffer_put_utf8_string(Buffer *buffer, const void *buf, u_int len) 345*0Sstevel@tonic-gate { 346*0Sstevel@tonic-gate char *converted *estr; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate converted = g11n_convert_to_utf8(buf, &err, &estr); 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate if (!converted && err) 351*0Sstevel@tonic-gate fatal("buffer_put_utf8_string: input not a valid UTF-8 encoding; %s", estr); 352*0Sstevel@tonic-gate 353*0Sstevel@tonic-gate if (err) 354*0Sstevel@tonic-gate verbose("buffer_put_utf8_string: input not a valid UTF-8 encoding; %s", estr); 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate buffer_put_string(buffer, converted, strlen(converted)); 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate if (converted != bug) xfree(converted); 359*0Sstevel@tonic-gate 360*0Sstevel@tonic-gate return; 361*0Sstevel@tonic-gate } 362*0Sstevel@tonic-gate #endif 363*0Sstevel@tonic-gate void 364*0Sstevel@tonic-gate buffer_put_utf8_cstring(Buffer *buffer, const u_char *s) 365*0Sstevel@tonic-gate { 366*0Sstevel@tonic-gate u_char *converted, *estr; 367*0Sstevel@tonic-gate int err; 368*0Sstevel@tonic-gate 369*0Sstevel@tonic-gate if (s == NULL) 370*0Sstevel@tonic-gate fatal("buffer_put_cstring: s == NULL"); 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate converted = g11n_convert_to_utf8(s, &err, &estr); 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate if (!converted && err) 375*0Sstevel@tonic-gate fatal("buffer_put_utf8_string: input not a valid UTF-8 encoding; %s", estr); 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate if (err) 378*0Sstevel@tonic-gate verbose("buffer_put_utf8_string: input not a valid UTF-8 encoding; %s", estr); 379*0Sstevel@tonic-gate 380*0Sstevel@tonic-gate buffer_put_cstring(buffer, (const char *) converted); 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate if (converted != s) xfree(converted); 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate return; 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate /* 389*0Sstevel@tonic-gate * Returns a character from the buffer (0 - 255). 390*0Sstevel@tonic-gate */ 391*0Sstevel@tonic-gate int 392*0Sstevel@tonic-gate buffer_get_char(Buffer *buffer) 393*0Sstevel@tonic-gate { 394*0Sstevel@tonic-gate char ch; 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate buffer_get(buffer, &ch, 1); 397*0Sstevel@tonic-gate return (u_char) ch; 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate /* 401*0Sstevel@tonic-gate * Stores a character in the buffer. 402*0Sstevel@tonic-gate */ 403*0Sstevel@tonic-gate void 404*0Sstevel@tonic-gate buffer_put_char(Buffer *buffer, int value) 405*0Sstevel@tonic-gate { 406*0Sstevel@tonic-gate char ch = value; 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate buffer_append(buffer, &ch, 1); 409*0Sstevel@tonic-gate } 410