10Sstevel@tonic-gate /* 2*9600SNobutomo.Nakano@Sun.COM * Copyright 2009 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 #include <langinfo.h> 470Sstevel@tonic-gate #include <openssl/bn.h> 480Sstevel@tonic-gate #include "bufaux.h" 490Sstevel@tonic-gate #include "xmalloc.h" 500Sstevel@tonic-gate #include "getput.h" 510Sstevel@tonic-gate #include "log.h" 520Sstevel@tonic-gate #include "g11n.h" 530Sstevel@tonic-gate 540Sstevel@tonic-gate /* 550Sstevel@tonic-gate * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed 560Sstevel@tonic-gate * by (bits+7)/8 bytes of binary data, msb first. 570Sstevel@tonic-gate */ 582757Sjp161948 int 592757Sjp161948 buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value) 600Sstevel@tonic-gate { 610Sstevel@tonic-gate int bits = BN_num_bits(value); 620Sstevel@tonic-gate int bin_size = (bits + 7) / 8; 630Sstevel@tonic-gate u_char *buf = xmalloc(bin_size); 640Sstevel@tonic-gate int oi; 650Sstevel@tonic-gate char msg[2]; 660Sstevel@tonic-gate 670Sstevel@tonic-gate /* Get the value of in binary */ 680Sstevel@tonic-gate oi = BN_bn2bin(value, buf); 692757Sjp161948 if (oi != bin_size) { 702757Sjp161948 error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d", 710Sstevel@tonic-gate oi, bin_size); 722757Sjp161948 xfree(buf); 732757Sjp161948 return (-1); 742757Sjp161948 } 750Sstevel@tonic-gate 760Sstevel@tonic-gate /* Store the number of bits in the buffer in two bytes, msb first. */ 770Sstevel@tonic-gate PUT_16BIT(msg, bits); 780Sstevel@tonic-gate buffer_append(buffer, msg, 2); 790Sstevel@tonic-gate /* Store the binary data. */ 800Sstevel@tonic-gate buffer_append(buffer, (char *)buf, oi); 810Sstevel@tonic-gate 820Sstevel@tonic-gate memset(buf, 0, bin_size); 830Sstevel@tonic-gate xfree(buf); 842757Sjp161948 852757Sjp161948 return (0); 862757Sjp161948 } 872757Sjp161948 882757Sjp161948 void 892757Sjp161948 buffer_put_bignum(Buffer *buffer, const BIGNUM *value) 902757Sjp161948 { 912757Sjp161948 if (buffer_put_bignum_ret(buffer, value) == -1) 922757Sjp161948 fatal("buffer_put_bignum: buffer error"); 930Sstevel@tonic-gate } 940Sstevel@tonic-gate 950Sstevel@tonic-gate /* 960Sstevel@tonic-gate * Retrieves an BIGNUM from the buffer. 970Sstevel@tonic-gate */ 982757Sjp161948 int 992757Sjp161948 buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value) 1000Sstevel@tonic-gate { 1012757Sjp161948 u_int bits, bytes; 1020Sstevel@tonic-gate u_char buf[2], *bin; 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate /* Get the number for bits. */ 1052757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) { 1062757Sjp161948 error("buffer_get_bignum_ret: invalid length"); 1072757Sjp161948 return (-1); 1082757Sjp161948 } 1090Sstevel@tonic-gate bits = GET_16BIT(buf); 1100Sstevel@tonic-gate /* Compute the number of binary bytes that follow. */ 1110Sstevel@tonic-gate bytes = (bits + 7) / 8; 1122757Sjp161948 if (bytes > 8 * 1024) { 1132757Sjp161948 error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes); 1142757Sjp161948 return (-1); 1152757Sjp161948 } 1162757Sjp161948 if (buffer_len(buffer) < bytes) { 1172757Sjp161948 error("buffer_get_bignum_ret: input buffer too small"); 1182757Sjp161948 return (-1); 1192757Sjp161948 } 1200Sstevel@tonic-gate bin = buffer_ptr(buffer); 1210Sstevel@tonic-gate BN_bin2bn(bin, bytes, value); 1222757Sjp161948 if (buffer_consume_ret(buffer, bytes) == -1) { 1232757Sjp161948 error("buffer_get_bignum_ret: buffer_consume failed"); 1242757Sjp161948 return (-1); 1252757Sjp161948 } 1262757Sjp161948 return (0); 1272757Sjp161948 } 1282757Sjp161948 1292757Sjp161948 void 1302757Sjp161948 buffer_get_bignum(Buffer *buffer, BIGNUM *value) 1312757Sjp161948 { 1322757Sjp161948 if (buffer_get_bignum_ret(buffer, value) == -1) 1332757Sjp161948 fatal("buffer_get_bignum: buffer error"); 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate /* 1370Sstevel@tonic-gate * Stores an BIGNUM in the buffer in SSH2 format. 1380Sstevel@tonic-gate */ 1392757Sjp161948 int 1402757Sjp161948 buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value) 1410Sstevel@tonic-gate { 1422757Sjp161948 u_int bytes; 1432757Sjp161948 u_char *buf; 1440Sstevel@tonic-gate int oi; 1452757Sjp161948 u_int hasnohigh = 0; 1460Sstevel@tonic-gate 1472757Sjp161948 if (BN_is_zero(value)) { 1482757Sjp161948 buffer_put_int(buffer, 0); 1492757Sjp161948 return 0; 1502757Sjp161948 } 1512757Sjp161948 if (value->neg) { 1522757Sjp161948 error("buffer_put_bignum2_ret: negative numbers not supported"); 1532757Sjp161948 return (-1); 1542757Sjp161948 } 1552757Sjp161948 bytes = BN_num_bytes(value) + 1; /* extra padding byte */ 1562757Sjp161948 if (bytes < 2) { 1572757Sjp161948 error("buffer_put_bignum2_ret: BN too small"); 1582757Sjp161948 return (-1); 1592757Sjp161948 } 1602757Sjp161948 buf = xmalloc(bytes); 1612757Sjp161948 buf[0] = 0x00; 1620Sstevel@tonic-gate /* Get the value of in binary */ 1630Sstevel@tonic-gate oi = BN_bn2bin(value, buf+1); 1642757Sjp161948 if (oi < 0 || (u_int)oi != bytes - 1) { 1652757Sjp161948 error("buffer_put_bignum2_ret: BN_bn2bin() failed: " 1662757Sjp161948 "oi %d != bin_size %d", oi, bytes); 1672757Sjp161948 xfree(buf); 1682757Sjp161948 return (-1); 1692757Sjp161948 } 1700Sstevel@tonic-gate hasnohigh = (buf[1] & 0x80) ? 0 : 1; 1710Sstevel@tonic-gate buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh); 1720Sstevel@tonic-gate memset(buf, 0, bytes); 1730Sstevel@tonic-gate xfree(buf); 1742757Sjp161948 return (0); 1752757Sjp161948 } 1762757Sjp161948 1772757Sjp161948 void 1782757Sjp161948 buffer_put_bignum2(Buffer *buffer, const BIGNUM *value) 1792757Sjp161948 { 1802757Sjp161948 if (buffer_put_bignum2_ret(buffer, value) == -1) 1812757Sjp161948 fatal("buffer_put_bignum2: buffer error"); 1820Sstevel@tonic-gate } 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate /* XXX does not handle negative BNs */ 1852757Sjp161948 int 1862757Sjp161948 buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value) 1872757Sjp161948 { 1882757Sjp161948 u_int len; 1892757Sjp161948 u_char *bin; 1902757Sjp161948 1912757Sjp161948 if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) { 1922757Sjp161948 error("buffer_get_bignum2_ret: invalid bignum"); 1932757Sjp161948 return (-1); 1942757Sjp161948 } 1952757Sjp161948 1962757Sjp161948 if (len > 0 && (bin[0] & 0x80)) { 1972757Sjp161948 error("buffer_get_bignum2_ret: negative numbers not supported"); 1982757Sjp161948 xfree(bin); 1992757Sjp161948 return (-1); 2002757Sjp161948 } 2012757Sjp161948 if (len > 8 * 1024) { 2022757Sjp161948 error("buffer_get_bignum2_ret: cannot handle BN of size %d", len); 2032757Sjp161948 xfree(bin); 2042757Sjp161948 return (-1); 2052757Sjp161948 } 2062757Sjp161948 BN_bin2bn(bin, len, value); 2072757Sjp161948 xfree(bin); 2082757Sjp161948 return (0); 2092757Sjp161948 } 2102757Sjp161948 2110Sstevel@tonic-gate void 2120Sstevel@tonic-gate buffer_get_bignum2(Buffer *buffer, BIGNUM *value) 2130Sstevel@tonic-gate { 2142757Sjp161948 if (buffer_get_bignum2_ret(buffer, value) == -1) 2152757Sjp161948 fatal("buffer_get_bignum2: buffer error"); 2162757Sjp161948 } 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /* 2190Sstevel@tonic-gate * Returns integers from the buffer (msb first). 2200Sstevel@tonic-gate */ 2210Sstevel@tonic-gate 2222757Sjp161948 int 2232757Sjp161948 buffer_get_short_ret(u_short *ret, Buffer *buffer) 2242757Sjp161948 { 2252757Sjp161948 u_char buf[2]; 2262757Sjp161948 2272757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) 2282757Sjp161948 return (-1); 2292757Sjp161948 *ret = GET_16BIT(buf); 2302757Sjp161948 return (0); 2312757Sjp161948 } 2322757Sjp161948 2330Sstevel@tonic-gate u_short 2340Sstevel@tonic-gate buffer_get_short(Buffer *buffer) 2350Sstevel@tonic-gate { 2362757Sjp161948 u_short ret; 2372757Sjp161948 2382757Sjp161948 if (buffer_get_short_ret(&ret, buffer) == -1) 2392757Sjp161948 fatal("buffer_get_short: buffer error"); 2402757Sjp161948 2412757Sjp161948 return (ret); 2422757Sjp161948 } 2430Sstevel@tonic-gate 2442757Sjp161948 int 2452757Sjp161948 buffer_get_int_ret(u_int *ret, Buffer *buffer) 2462757Sjp161948 { 2472757Sjp161948 u_char buf[4]; 2482757Sjp161948 2492757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 4) == -1) 2502757Sjp161948 return (-1); 2512757Sjp161948 *ret = GET_32BIT(buf); 2522757Sjp161948 return (0); 2530Sstevel@tonic-gate } 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate u_int 2560Sstevel@tonic-gate buffer_get_int(Buffer *buffer) 2570Sstevel@tonic-gate { 2582757Sjp161948 u_int ret; 2590Sstevel@tonic-gate 2602757Sjp161948 if (buffer_get_int_ret(&ret, buffer) == -1) 2612757Sjp161948 fatal("buffer_get_int: buffer error"); 2622757Sjp161948 2632757Sjp161948 return (ret); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate #ifdef HAVE_U_INT64_T 2672757Sjp161948 int 2682757Sjp161948 buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) 2692757Sjp161948 { 2702757Sjp161948 u_char buf[8]; 2712757Sjp161948 2722757Sjp161948 if (buffer_get_ret(buffer, (char *) buf, 8) == -1) 2732757Sjp161948 return (-1); 2742757Sjp161948 *ret = GET_64BIT(buf); 2752757Sjp161948 return (0); 2762757Sjp161948 } 2772757Sjp161948 2780Sstevel@tonic-gate u_int64_t 2790Sstevel@tonic-gate buffer_get_int64(Buffer *buffer) 2800Sstevel@tonic-gate { 2812757Sjp161948 u_int64_t ret; 2820Sstevel@tonic-gate 2832757Sjp161948 if (buffer_get_int64_ret(&ret, buffer) == -1) 2842757Sjp161948 fatal("buffer_get_int: buffer error"); 2852757Sjp161948 2862757Sjp161948 return (ret); 2870Sstevel@tonic-gate } 2880Sstevel@tonic-gate #endif 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate /* 2910Sstevel@tonic-gate * Stores integers in the buffer, msb first. 2920Sstevel@tonic-gate */ 2930Sstevel@tonic-gate void 2940Sstevel@tonic-gate buffer_put_short(Buffer *buffer, u_short value) 2950Sstevel@tonic-gate { 2960Sstevel@tonic-gate char buf[2]; 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate PUT_16BIT(buf, value); 2990Sstevel@tonic-gate buffer_append(buffer, buf, 2); 3000Sstevel@tonic-gate } 3010Sstevel@tonic-gate 3020Sstevel@tonic-gate void 3030Sstevel@tonic-gate buffer_put_int(Buffer *buffer, u_int value) 3040Sstevel@tonic-gate { 3050Sstevel@tonic-gate char buf[4]; 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate PUT_32BIT(buf, value); 3080Sstevel@tonic-gate buffer_append(buffer, buf, 4); 3090Sstevel@tonic-gate } 3100Sstevel@tonic-gate 3110Sstevel@tonic-gate #ifdef HAVE_U_INT64_T 3120Sstevel@tonic-gate void 3130Sstevel@tonic-gate buffer_put_int64(Buffer *buffer, u_int64_t value) 3140Sstevel@tonic-gate { 3150Sstevel@tonic-gate char buf[8]; 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate PUT_64BIT(buf, value); 3180Sstevel@tonic-gate buffer_append(buffer, buf, 8); 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate #endif 3210Sstevel@tonic-gate 3220Sstevel@tonic-gate /* 3230Sstevel@tonic-gate * Returns an arbitrary binary string from the buffer. The string cannot 3240Sstevel@tonic-gate * be longer than 256k. The returned value points to memory allocated 3250Sstevel@tonic-gate * with xmalloc; it is the responsibility of the calling function to free 3260Sstevel@tonic-gate * the data. If length_ptr is non-NULL, the length of the returned data 3270Sstevel@tonic-gate * will be stored there. A null character will be automatically appended 3280Sstevel@tonic-gate * to the returned string, and is not counted in length. 3290Sstevel@tonic-gate */ 3300Sstevel@tonic-gate void * 3312757Sjp161948 buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) 3320Sstevel@tonic-gate { 3330Sstevel@tonic-gate u_char *value; 3340Sstevel@tonic-gate u_int len; 3350Sstevel@tonic-gate 3360Sstevel@tonic-gate /* Get the length. */ 3370Sstevel@tonic-gate len = buffer_get_int(buffer); 3382757Sjp161948 if (len > 256 * 1024) { 3392757Sjp161948 error("buffer_get_string_ret: bad string length %u", len); 3402757Sjp161948 return (NULL); 3412757Sjp161948 } 3420Sstevel@tonic-gate /* Allocate space for the string. Add one byte for a null character. */ 3430Sstevel@tonic-gate value = xmalloc(len + 1); 3440Sstevel@tonic-gate /* Get the string. */ 3452757Sjp161948 if (buffer_get_ret(buffer, value, len) == -1) { 3462757Sjp161948 error("buffer_get_string_ret: buffer_get failed"); 3472757Sjp161948 xfree(value); 3482757Sjp161948 return (NULL); 3492757Sjp161948 } 3500Sstevel@tonic-gate /* Append a null character to make processing easier. */ 3510Sstevel@tonic-gate value[len] = 0; 3520Sstevel@tonic-gate /* Optionally return the length of the string. */ 3530Sstevel@tonic-gate if (length_ptr) 3540Sstevel@tonic-gate *length_ptr = len; 3552757Sjp161948 return (value); 3560Sstevel@tonic-gate } 3572757Sjp161948 3582757Sjp161948 void * 3592757Sjp161948 buffer_get_string(Buffer *buffer, u_int *length_ptr) 3602757Sjp161948 { 3612757Sjp161948 void *ret; 3622757Sjp161948 3632757Sjp161948 if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) 3642757Sjp161948 fatal("buffer_get_string: buffer error"); 3652757Sjp161948 return (ret); 3662757Sjp161948 } 3672757Sjp161948 3680Sstevel@tonic-gate char * 369*9600SNobutomo.Nakano@Sun.COM buffer_get_utf8_string(Buffer *buffer, uint_t *length_ptr) 3700Sstevel@tonic-gate { 371*9600SNobutomo.Nakano@Sun.COM char *value, *converted, *estr; 372*9600SNobutomo.Nakano@Sun.COM uint_t len; 3730Sstevel@tonic-gate 374*9600SNobutomo.Nakano@Sun.COM if ((value = buffer_get_string(buffer, &len)) == NULL) 375*9600SNobutomo.Nakano@Sun.COM return (value); 3760Sstevel@tonic-gate 377*9600SNobutomo.Nakano@Sun.COM converted = g11n_convert_from_utf8(value, &len, &estr); 378*9600SNobutomo.Nakano@Sun.COM if (converted == NULL) { 379*9600SNobutomo.Nakano@Sun.COM if (estr != NULL) 380*9600SNobutomo.Nakano@Sun.COM error("invalid UTF-8 sequence: %s", estr); 381*9600SNobutomo.Nakano@Sun.COM converted = value; 382*9600SNobutomo.Nakano@Sun.COM } else { 383*9600SNobutomo.Nakano@Sun.COM xfree(value); 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 386*9600SNobutomo.Nakano@Sun.COM if (length_ptr != NULL) 387*9600SNobutomo.Nakano@Sun.COM *length_ptr = len; 3880Sstevel@tonic-gate 389*9600SNobutomo.Nakano@Sun.COM return (converted); 3900Sstevel@tonic-gate } 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate /* 3930Sstevel@tonic-gate * Stores and arbitrary binary string in the buffer. 3940Sstevel@tonic-gate */ 3950Sstevel@tonic-gate void 3960Sstevel@tonic-gate buffer_put_string(Buffer *buffer, const void *buf, u_int len) 3970Sstevel@tonic-gate { 3980Sstevel@tonic-gate buffer_put_int(buffer, len); 3990Sstevel@tonic-gate buffer_append(buffer, buf, len); 4000Sstevel@tonic-gate } 4010Sstevel@tonic-gate void 4020Sstevel@tonic-gate buffer_put_cstring(Buffer *buffer, const char *s) 4030Sstevel@tonic-gate { 4040Sstevel@tonic-gate if (s == NULL) 4050Sstevel@tonic-gate fatal("buffer_put_cstring: s == NULL"); 4060Sstevel@tonic-gate buffer_put_string(buffer, s, strlen(s)); 4070Sstevel@tonic-gate } 4080Sstevel@tonic-gate 4090Sstevel@tonic-gate /* 4100Sstevel@tonic-gate * UTF-8 versions of the above. 4110Sstevel@tonic-gate */ 4120Sstevel@tonic-gate void 413*9600SNobutomo.Nakano@Sun.COM buffer_put_utf8_string(Buffer *buffer, const char *s, uint_t len) 4140Sstevel@tonic-gate { 415*9600SNobutomo.Nakano@Sun.COM char *converted, *estr; 416*9600SNobutomo.Nakano@Sun.COM uint_t nlen = len; 4170Sstevel@tonic-gate 418*9600SNobutomo.Nakano@Sun.COM converted = g11n_convert_to_utf8(s, &nlen, 0, &estr); 419*9600SNobutomo.Nakano@Sun.COM if (converted == NULL) { 420*9600SNobutomo.Nakano@Sun.COM if (estr != NULL) 421*9600SNobutomo.Nakano@Sun.COM error("Can't convert to UTF-8: %s", estr); 422*9600SNobutomo.Nakano@Sun.COM converted = (char *)s; 423*9600SNobutomo.Nakano@Sun.COM } 4240Sstevel@tonic-gate 425*9600SNobutomo.Nakano@Sun.COM buffer_put_string(buffer, converted, nlen); 4260Sstevel@tonic-gate 427*9600SNobutomo.Nakano@Sun.COM if (converted != s) 428*9600SNobutomo.Nakano@Sun.COM xfree(converted); 4290Sstevel@tonic-gate } 4300Sstevel@tonic-gate 431*9600SNobutomo.Nakano@Sun.COM void 432*9600SNobutomo.Nakano@Sun.COM buffer_put_utf8_cstring(Buffer *buffer, const char *s) 433*9600SNobutomo.Nakano@Sun.COM { 434*9600SNobutomo.Nakano@Sun.COM buffer_put_utf8_string(buffer, s, strlen(s)); 435*9600SNobutomo.Nakano@Sun.COM } 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate /* 4380Sstevel@tonic-gate * Returns a character from the buffer (0 - 255). 4390Sstevel@tonic-gate */ 4400Sstevel@tonic-gate int 4412757Sjp161948 buffer_get_char_ret(char *ret, Buffer *buffer) 4422757Sjp161948 { 4432757Sjp161948 if (buffer_get_ret(buffer, ret, 1) == -1) { 4442757Sjp161948 error("buffer_get_char_ret: buffer_get_ret failed"); 4452757Sjp161948 return (-1); 4462757Sjp161948 } 4472757Sjp161948 return (0); 4482757Sjp161948 } 4492757Sjp161948 4502757Sjp161948 int 4510Sstevel@tonic-gate buffer_get_char(Buffer *buffer) 4520Sstevel@tonic-gate { 4530Sstevel@tonic-gate char ch; 4540Sstevel@tonic-gate 4552757Sjp161948 if (buffer_get_char_ret(&ch, buffer) == -1) 4562757Sjp161948 fatal("buffer_get_char: buffer error"); 4570Sstevel@tonic-gate return (u_char) ch; 4580Sstevel@tonic-gate } 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate /* 4610Sstevel@tonic-gate * Stores a character in the buffer. 4620Sstevel@tonic-gate */ 4630Sstevel@tonic-gate void 4640Sstevel@tonic-gate buffer_put_char(Buffer *buffer, int value) 4650Sstevel@tonic-gate { 4660Sstevel@tonic-gate char ch = value; 4670Sstevel@tonic-gate 4680Sstevel@tonic-gate buffer_append(buffer, &ch, 1); 4690Sstevel@tonic-gate } 470