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