Branch data Line data Source code
1 : : /* $OpenBSD: bufaux.c,v 1.56 2014/02/02 03:44:31 djm Exp $ */
2 : : /*
3 : : * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 : : * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 : : * All rights reserved
6 : : * Auxiliary functions for storing and retrieving various data types to/from
7 : : * Buffers.
8 : : *
9 : : * As far as I am concerned, the code I have written for this software
10 : : * can be used freely for any purpose. Any derived versions of this
11 : : * software must be clearly marked as such, and if the derived work is
12 : : * incompatible with the protocol description in the RFC file, it must be
13 : : * called by a name other than "ssh" or "Secure Shell".
14 : : *
15 : : *
16 : : * SSH2 packet format added by Markus Friedl
17 : : * Copyright (c) 2000 Markus Friedl. All rights reserved.
18 : : *
19 : : * Redistribution and use in source and binary forms, with or without
20 : : * modification, are permitted provided that the following conditions
21 : : * are met:
22 : : * 1. Redistributions of source code must retain the above copyright
23 : : * notice, this list of conditions and the following disclaimer.
24 : : * 2. Redistributions in binary form must reproduce the above copyright
25 : : * notice, this list of conditions and the following disclaimer in the
26 : : * documentation and/or other materials provided with the distribution.
27 : : *
28 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
32 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 : : */
39 : :
40 : : #include "includes.h"
41 : :
42 : : #include <sys/types.h>
43 : :
44 : : #include <openssl/bn.h>
45 : :
46 : : #include <string.h>
47 : : #include <stdarg.h>
48 : : #include <stdlib.h>
49 : :
50 : : #include "xmalloc.h"
51 : : #include "buffer.h"
52 : : #include "log.h"
53 : : #include "misc.h"
54 : :
55 : : /*
56 : : * Returns integers from the buffer (msb first).
57 : : */
58 : :
59 : : int
60 : 0 : buffer_get_short_ret(u_short *ret, Buffer *buffer)
61 : : {
62 : : u_char buf[2];
63 : :
64 [ # # ]: 0 : if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
65 : : return (-1);
66 : 0 : *ret = get_u16(buf);
67 : 0 : return (0);
68 : : }
69 : :
70 : : u_short
71 : 0 : buffer_get_short(Buffer *buffer)
72 : : {
73 : : u_short ret;
74 : :
75 [ # # ]: 0 : if (buffer_get_short_ret(&ret, buffer) == -1)
76 : 0 : fatal("buffer_get_short: buffer error");
77 : :
78 : 0 : return (ret);
79 : : }
80 : :
81 : : int
82 : 4737791 : buffer_get_int_ret(u_int *ret, Buffer *buffer)
83 : : {
84 : : u_char buf[4];
85 : :
86 [ + - ]: 4737791 : if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
87 : : return (-1);
88 [ + - ]: 4737791 : if (ret != NULL)
89 : 4737791 : *ret = get_u32(buf);
90 : : return (0);
91 : : }
92 : :
93 : : u_int
94 : 3731945 : buffer_get_int(Buffer *buffer)
95 : : {
96 : : u_int ret;
97 : :
98 [ - + ]: 3731945 : if (buffer_get_int_ret(&ret, buffer) == -1)
99 : 0 : fatal("buffer_get_int: buffer error");
100 : :
101 : 3731945 : return (ret);
102 : : }
103 : :
104 : : int
105 : 10571 : buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
106 : : {
107 : : u_char buf[8];
108 : :
109 [ + - ]: 10571 : if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
110 : : return (-1);
111 [ + - ]: 10571 : if (ret != NULL)
112 : 10571 : *ret = get_u64(buf);
113 : : return (0);
114 : : }
115 : :
116 : : u_int64_t
117 : 5503 : buffer_get_int64(Buffer *buffer)
118 : : {
119 : : u_int64_t ret;
120 : :
121 [ - + ]: 5503 : if (buffer_get_int64_ret(&ret, buffer) == -1)
122 : 0 : fatal("buffer_get_int: buffer error");
123 : :
124 : 5503 : return (ret);
125 : : }
126 : :
127 : : /*
128 : : * Stores integers in the buffer, msb first.
129 : : */
130 : : void
131 : 0 : buffer_put_short(Buffer *buffer, u_short value)
132 : : {
133 : : char buf[2];
134 : :
135 : 0 : put_u16(buf, value);
136 : 0 : buffer_append(buffer, buf, 2);
137 : 0 : }
138 : :
139 : : void
140 : 4623867 : buffer_put_int(Buffer *buffer, u_int value)
141 : : {
142 : : char buf[4];
143 : :
144 : 4623867 : put_u32(buf, value);
145 : 4623867 : buffer_append(buffer, buf, 4);
146 : 4623867 : }
147 : :
148 : : void
149 : 1420585 : buffer_put_int64(Buffer *buffer, u_int64_t value)
150 : : {
151 : : char buf[8];
152 : :
153 : 1420585 : put_u64(buf, value);
154 : 1420585 : buffer_append(buffer, buf, 8);
155 : 1420585 : }
156 : :
157 : : /*
158 : : * Returns an arbitrary binary string from the buffer. The string cannot
159 : : * be longer than 256k. The returned value points to memory allocated
160 : : * with xmalloc; it is the responsibility of the calling function to free
161 : : * the data. If length_ptr is non-NULL, the length of the returned data
162 : : * will be stored there. A null character will be automatically appended
163 : : * to the returned string, and is not counted in length.
164 : : */
165 : : void *
166 : 984591 : buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
167 : : {
168 : : u_char *value;
169 : : u_int len;
170 : :
171 : : /* Get the length. */
172 [ - + ]: 984591 : if (buffer_get_int_ret(&len, buffer) != 0) {
173 : 0 : error("buffer_get_string_ret: cannot extract length");
174 : 0 : return (NULL);
175 : : }
176 [ - + ]: 984591 : if (len > 256 * 1024) {
177 : 0 : error("buffer_get_string_ret: bad string length %u", len);
178 : 0 : return (NULL);
179 : : }
180 : : /* Allocate space for the string. Add one byte for a null character. */
181 : 984591 : value = xmalloc(len + 1);
182 : : /* Get the string. */
183 [ + + ]: 984591 : if (buffer_get_ret(buffer, value, len) == -1) {
184 : 2 : error("buffer_get_string_ret: buffer_get failed");
185 : 2 : free(value);
186 : 2 : return (NULL);
187 : : }
188 : : /* Append a null character to make processing easier. */
189 : 984589 : value[len] = '\0';
190 : : /* Optionally return the length of the string. */
191 [ + + ]: 984589 : if (length_ptr)
192 : 875600 : *length_ptr = len;
193 : 984589 : return (value);
194 : : }
195 : :
196 : : void *
197 : 850043 : buffer_get_string(Buffer *buffer, u_int *length_ptr)
198 : : {
199 : : void *ret;
200 : :
201 [ - + ]: 850043 : if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
202 : 0 : fatal("buffer_get_string: buffer error");
203 : 850043 : return (ret);
204 : : }
205 : :
206 : : char *
207 : 91727 : buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
208 : : {
209 : : u_int length;
210 : 91727 : char *cp, *ret = buffer_get_string_ret(buffer, &length);
211 : :
212 [ + - ]: 91727 : if (ret == NULL)
213 : : return NULL;
214 [ - + ]: 91727 : if ((cp = memchr(ret, '\0', length)) != NULL) {
215 : : /* XXX allow \0 at end-of-string for a while, remove later */
216 [ # # ]: 0 : if (cp == ret + length - 1)
217 : 0 : error("buffer_get_cstring_ret: string contains \\0");
218 : : else {
219 : 0 : explicit_bzero(ret, length);
220 : 0 : free(ret);
221 : 0 : return NULL;
222 : : }
223 : : }
224 [ + + ]: 91727 : if (length_ptr != NULL)
225 : 5300 : *length_ptr = length;
226 : 91727 : return ret;
227 : : }
228 : :
229 : : char *
230 : 49568 : buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
231 : : {
232 : : char *ret;
233 : :
234 [ - + ]: 49568 : if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
235 : 0 : fatal("buffer_get_cstring: buffer error");
236 : 49568 : return ret;
237 : : }
238 : :
239 : : void *
240 : 19333 : buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
241 : : {
242 : : void *ptr;
243 : : u_int len;
244 : :
245 [ + - ]: 19333 : if (buffer_get_int_ret(&len, buffer) != 0)
246 : : return NULL;
247 [ - + ]: 19333 : if (len > 256 * 1024) {
248 : 0 : error("buffer_get_string_ptr: bad string length %u", len);
249 : 0 : return NULL;
250 : : }
251 : 19333 : ptr = buffer_ptr(buffer);
252 : 19333 : buffer_consume(buffer, len);
253 [ + + ]: 19333 : if (length_ptr)
254 : 4020 : *length_ptr = len;
255 : 19333 : return (ptr);
256 : : }
257 : :
258 : : void *
259 : 4253 : buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
260 : : {
261 : : void *ret;
262 : :
263 [ - + ]: 4253 : if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
264 : 0 : fatal("buffer_get_string_ptr: buffer error");
265 : 4253 : return (ret);
266 : : }
267 : :
268 : : /*
269 : : * Stores and arbitrary binary string in the buffer.
270 : : */
271 : : void
272 : 2196194 : buffer_put_string(Buffer *buffer, const void *buf, u_int len)
273 : : {
274 : 2331269 : buffer_put_int(buffer, len);
275 : 2331269 : buffer_append(buffer, buf, len);
276 : 2196194 : }
277 : : void
278 : 133466 : buffer_put_cstring(Buffer *buffer, const char *s)
279 : : {
280 [ - + ]: 133466 : if (s == NULL)
281 : 0 : fatal("buffer_put_cstring: s == NULL");
282 : 133466 : buffer_put_string(buffer, s, strlen(s));
283 : 133466 : }
284 : :
285 : : /*
286 : : * Returns a character from the buffer (0 - 255).
287 : : */
288 : : int
289 : 1531452 : buffer_get_char_ret(u_char *ret, Buffer *buffer)
290 : : {
291 [ - + ]: 1531452 : if (buffer_get_ret(buffer, ret, 1) == -1) {
292 : 0 : error("buffer_get_char_ret: buffer_get_ret failed");
293 : 0 : return (-1);
294 : : }
295 : : return (0);
296 : : }
297 : :
298 : : int
299 : 1530384 : buffer_get_char(Buffer *buffer)
300 : : {
301 : : u_char ch;
302 : :
303 [ - + ]: 1530384 : if (buffer_get_char_ret(&ch, buffer) == -1)
304 : 0 : fatal("buffer_get_char: buffer error");
305 : 1530384 : return ch;
306 : : }
307 : :
308 : : /*
309 : : * Stores a character in the buffer.
310 : : */
311 : : void
312 : 1461130 : buffer_put_char(Buffer *buffer, int value)
313 : : {
314 : 1461130 : char ch = value;
315 : :
316 : 1461130 : buffer_append(buffer, &ch, 1);
317 : 1461130 : }
318 : :
319 : : /* Pseudo bignum functions */
320 : :
321 : : void *
322 : 0 : buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr)
323 : : {
324 : : u_int len;
325 : : u_char *bin, *p, *ret;
326 : :
327 [ # # ]: 0 : if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) {
328 : 0 : error("%s: invalid bignum", __func__);
329 : 0 : return NULL;
330 : : }
331 : :
332 [ # # ][ # # ]: 0 : if (len > 0 && (bin[0] & 0x80)) {
333 : 0 : error("%s: negative numbers not supported", __func__);
334 : 0 : free(bin);
335 : 0 : return NULL;
336 : : }
337 [ # # ]: 0 : if (len > 8 * 1024) {
338 : 0 : error("%s: cannot handle BN of size %d", __func__, len);
339 : 0 : free(bin);
340 : 0 : return NULL;
341 : : }
342 : : /* Skip zero prefix on numbers with the MSB set */
343 [ # # ][ # # ]: 0 : if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) {
[ # # ]
344 : 0 : p++;
345 : 0 : len--;
346 : : }
347 : 0 : ret = xmalloc(len);
348 : 0 : memcpy(ret, p, len);
349 : 0 : explicit_bzero(p, len);
350 : 0 : free(bin);
351 : 0 : return ret;
352 : : }
353 : :
354 : : void *
355 : 0 : buffer_get_bignum2_as_string(Buffer *buffer, u_int *l)
356 : : {
357 : 0 : void *ret = buffer_get_bignum2_as_string_ret(buffer, l);
358 : :
359 [ # # ]: 0 : if (ret == NULL)
360 : 0 : fatal("%s: buffer error", __func__);
361 : 0 : return ret;
362 : : }
363 : :
364 : : /*
365 : : * Stores a string using the bignum encoding rules (\0 pad if MSB set).
366 : : */
367 : : void
368 : 1609 : buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
369 : : {
370 : : u_char *buf, *p;
371 : 1609 : int pad = 0;
372 : :
373 [ - + ]: 1609 : if (l > 8 * 1024)
374 : 0 : fatal("%s: length %u too long", __func__, l);
375 : 1609 : p = buf = xmalloc(l + 1);
376 : : /*
377 : : * If most significant bit is set then prepend a zero byte to
378 : : * avoid interpretation as a negative number.
379 : : */
380 [ + - ][ + + ]: 1609 : if (l > 0 && (s[0] & 0x80) != 0) {
381 : 805 : *p++ = '\0';
382 : 805 : pad = 1;
383 : : }
384 : 1609 : memcpy(p, s, l);
385 : 1609 : buffer_put_string(buffer, buf, l + pad);
386 : 1609 : explicit_bzero(buf, l + pad);
387 : 1609 : free(buf);
388 : 1609 : }
389 : :
390 : :
|