[BACK]Return to bufaux.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/bufaux.c, Revision 1.56

1.56    ! djm         1: /* $OpenBSD: bufaux.c,v 1.55 2014/01/31 16:39:19 tedu Exp $ */
1.1       deraadt     2: /*
1.6       deraadt     3:  * Author: Tatu Ylonen <ylo@cs.hut.fi>
                      4:  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
                      5:  *                    All rights reserved
1.13      deraadt     6:  * Auxiliary functions for storing and retrieving various data types to/from
                      7:  * Buffers.
1.11      markus      8:  *
1.13      deraadt     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".
1.11      markus     14:  *
1.6       deraadt    15:  *
1.9       markus     16:  * SSH2 packet format added by Markus Friedl
1.13      deraadt    17:  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
1.9       markus     18:  *
1.13      deraadt    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.
1.6       deraadt    38:  */
1.1       deraadt    39:
1.44      deraadt    40: #include <sys/types.h>
1.1       deraadt    41:
1.10      markus     42: #include <openssl/bn.h>
1.43      stevesk    43:
                     44: #include <string.h>
1.44      deraadt    45: #include <stdarg.h>
1.53      dtucker    46: #include <stdlib.h>
1.43      stevesk    47:
1.1       deraadt    48: #include "xmalloc.h"
1.44      deraadt    49: #include "buffer.h"
1.17      markus     50: #include "log.h"
1.41      djm        51: #include "misc.h"
1.32      markus     52:
1.9       markus     53: /*
1.25      markus     54:  * Returns integers from the buffer (msb first).
1.6       deraadt    55:  */
1.25      markus     56:
1.33      djm        57: int
                     58: buffer_get_short_ret(u_short *ret, Buffer *buffer)
                     59: {
                     60:        u_char buf[2];
                     61:
                     62:        if (buffer_get_ret(buffer, (char *) buf, 2) == -1)
                     63:                return (-1);
1.41      djm        64:        *ret = get_u16(buf);
1.33      djm        65:        return (0);
                     66: }
                     67:
1.25      markus     68: u_short
                     69: buffer_get_short(Buffer *buffer)
                     70: {
1.33      djm        71:        u_short ret;
                     72:
                     73:        if (buffer_get_short_ret(&ret, buffer) == -1)
                     74:                fatal("buffer_get_short: buffer error");
                     75:
                     76:        return (ret);
                     77: }
                     78:
                     79: int
                     80: buffer_get_int_ret(u_int *ret, Buffer *buffer)
                     81: {
                     82:        u_char buf[4];
1.26      deraadt    83:
1.33      djm        84:        if (buffer_get_ret(buffer, (char *) buf, 4) == -1)
                     85:                return (-1);
1.49      djm        86:        if (ret != NULL)
                     87:                *ret = get_u32(buf);
1.33      djm        88:        return (0);
1.25      markus     89: }
                     90:
1.14      markus     91: u_int
1.5       markus     92: buffer_get_int(Buffer *buffer)
1.1       deraadt    93: {
1.33      djm        94:        u_int ret;
                     95:
                     96:        if (buffer_get_int_ret(&ret, buffer) == -1)
                     97:                fatal("buffer_get_int: buffer error");
                     98:
                     99:        return (ret);
                    100: }
                    101:
                    102: int
                    103: buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer)
                    104: {
                    105:        u_char buf[8];
1.26      deraadt   106:
1.33      djm       107:        if (buffer_get_ret(buffer, (char *) buf, 8) == -1)
                    108:                return (-1);
1.49      djm       109:        if (ret != NULL)
                    110:                *ret = get_u64(buf);
1.33      djm       111:        return (0);
1.1       deraadt   112: }
                    113:
1.15      markus    114: u_int64_t
                    115: buffer_get_int64(Buffer *buffer)
                    116: {
1.33      djm       117:        u_int64_t ret;
                    118:
                    119:        if (buffer_get_int64_ret(&ret, buffer) == -1)
                    120:                fatal("buffer_get_int: buffer error");
1.26      deraadt   121:
1.33      djm       122:        return (ret);
1.15      markus    123: }
                    124:
1.6       deraadt   125: /*
1.25      markus    126:  * Stores integers in the buffer, msb first.
1.6       deraadt   127:  */
1.25      markus    128: void
                    129: buffer_put_short(Buffer *buffer, u_short value)
                    130: {
                    131:        char buf[2];
1.26      deraadt   132:
1.41      djm       133:        put_u16(buf, value);
1.25      markus    134:        buffer_append(buffer, buf, 2);
                    135: }
                    136:
1.11      markus    137: void
1.14      markus    138: buffer_put_int(Buffer *buffer, u_int value)
1.1       deraadt   139: {
1.5       markus    140:        char buf[4];
1.26      deraadt   141:
1.41      djm       142:        put_u32(buf, value);
1.5       markus    143:        buffer_append(buffer, buf, 4);
1.15      markus    144: }
                    145:
                    146: void
                    147: buffer_put_int64(Buffer *buffer, u_int64_t value)
                    148: {
                    149:        char buf[8];
1.26      deraadt   150:
1.41      djm       151:        put_u64(buf, value);
1.15      markus    152:        buffer_append(buffer, buf, 8);
1.1       deraadt   153: }
                    154:
1.6       deraadt   155: /*
                    156:  * Returns an arbitrary binary string from the buffer.  The string cannot
                    157:  * be longer than 256k.  The returned value points to memory allocated
                    158:  * with xmalloc; it is the responsibility of the calling function to free
                    159:  * the data.  If length_ptr is non-NULL, the length of the returned data
                    160:  * will be stored there.  A null character will be automatically appended
                    161:  * to the returned string, and is not counted in length.
                    162:  */
1.20      stevesk   163: void *
1.33      djm       164: buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
1.1       deraadt   165: {
1.26      deraadt   166:        u_char *value;
1.14      markus    167:        u_int len;
1.26      deraadt   168:
1.5       markus    169:        /* Get the length. */
1.48      djm       170:        if (buffer_get_int_ret(&len, buffer) != 0) {
                    171:                error("buffer_get_string_ret: cannot extract length");
                    172:                return (NULL);
                    173:        }
1.33      djm       174:        if (len > 256 * 1024) {
                    175:                error("buffer_get_string_ret: bad string length %u", len);
                    176:                return (NULL);
                    177:        }
1.5       markus    178:        /* Allocate space for the string.  Add one byte for a null character. */
                    179:        value = xmalloc(len + 1);
                    180:        /* Get the string. */
1.33      djm       181:        if (buffer_get_ret(buffer, value, len) == -1) {
                    182:                error("buffer_get_string_ret: buffer_get failed");
1.51      djm       183:                free(value);
1.33      djm       184:                return (NULL);
                    185:        }
1.5       markus    186:        /* Append a null character to make processing easier. */
1.46      dtucker   187:        value[len] = '\0';
1.5       markus    188:        /* Optionally return the length of the string. */
                    189:        if (length_ptr)
                    190:                *length_ptr = len;
1.33      djm       191:        return (value);
                    192: }
                    193:
                    194: void *
                    195: buffer_get_string(Buffer *buffer, u_int *length_ptr)
                    196: {
                    197:        void *ret;
                    198:
                    199:        if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
                    200:                fatal("buffer_get_string: buffer error");
                    201:        return (ret);
1.50      djm       202: }
                    203:
                    204: char *
                    205: buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
                    206: {
                    207:        u_int length;
                    208:        char *cp, *ret = buffer_get_string_ret(buffer, &length);
                    209:
                    210:        if (ret == NULL)
                    211:                return NULL;
                    212:        if ((cp = memchr(ret, '\0', length)) != NULL) {
                    213:                /* XXX allow \0 at end-of-string for a while, remove later */
                    214:                if (cp == ret + length - 1)
                    215:                        error("buffer_get_cstring_ret: string contains \\0");
                    216:                else {
1.55      tedu      217:                        explicit_bzero(ret, length);
1.51      djm       218:                        free(ret);
1.50      djm       219:                        return NULL;
                    220:                }
                    221:        }
                    222:        if (length_ptr != NULL)
                    223:                *length_ptr = length;
                    224:        return ret;
                    225: }
                    226:
                    227: char *
                    228: buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
                    229: {
                    230:        char *ret;
                    231:
                    232:        if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
                    233:                fatal("buffer_get_cstring: buffer error");
                    234:        return ret;
1.45      markus    235: }
                    236:
                    237: void *
1.47      djm       238: buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
1.45      markus    239: {
                    240:        void *ptr;
                    241:        u_int len;
                    242:
1.47      djm       243:        if (buffer_get_int_ret(&len, buffer) != 0)
                    244:                return NULL;
                    245:        if (len > 256 * 1024) {
                    246:                error("buffer_get_string_ptr: bad string length %u", len);
                    247:                return NULL;
                    248:        }
1.45      markus    249:        ptr = buffer_ptr(buffer);
                    250:        buffer_consume(buffer, len);
                    251:        if (length_ptr)
                    252:                *length_ptr = len;
                    253:        return (ptr);
1.47      djm       254: }
                    255:
                    256: void *
                    257: buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
                    258: {
                    259:        void *ret;
                    260:
                    261:        if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
                    262:                fatal("buffer_get_string_ptr: buffer error");
                    263:        return (ret);
1.1       deraadt   264: }
                    265:
1.6       deraadt   266: /*
                    267:  * Stores and arbitrary binary string in the buffer.
                    268:  */
1.11      markus    269: void
1.14      markus    270: buffer_put_string(Buffer *buffer, const void *buf, u_int len)
1.1       deraadt   271: {
1.5       markus    272:        buffer_put_int(buffer, len);
                    273:        buffer_append(buffer, buf, len);
1.9       markus    274: }
1.11      markus    275: void
1.9       markus    276: buffer_put_cstring(Buffer *buffer, const char *s)
                    277: {
1.23      provos    278:        if (s == NULL)
                    279:                fatal("buffer_put_cstring: s == NULL");
1.9       markus    280:        buffer_put_string(buffer, s, strlen(s));
1.1       deraadt   281: }
                    282:
1.6       deraadt   283: /*
                    284:  * Returns a character from the buffer (0 - 255).
                    285:  */
1.11      markus    286: int
1.52      djm       287: buffer_get_char_ret(u_char *ret, Buffer *buffer)
1.33      djm       288: {
                    289:        if (buffer_get_ret(buffer, ret, 1) == -1) {
                    290:                error("buffer_get_char_ret: buffer_get_ret failed");
                    291:                return (-1);
                    292:        }
                    293:        return (0);
                    294: }
                    295:
                    296: int
1.5       markus    297: buffer_get_char(Buffer *buffer)
1.1       deraadt   298: {
1.52      djm       299:        u_char ch;
1.26      deraadt   300:
1.33      djm       301:        if (buffer_get_char_ret(&ch, buffer) == -1)
                    302:                fatal("buffer_get_char: buffer error");
1.52      djm       303:        return ch;
1.1       deraadt   304: }
                    305:
1.6       deraadt   306: /*
                    307:  * Stores a character in the buffer.
                    308:  */
1.11      markus    309: void
1.5       markus    310: buffer_put_char(Buffer *buffer, int value)
1.1       deraadt   311: {
1.5       markus    312:        char ch = value;
1.26      deraadt   313:
1.5       markus    314:        buffer_append(buffer, &ch, 1);
1.1       deraadt   315: }
1.54      djm       316:
                    317: /* Pseudo bignum functions */
                    318:
                    319: void *
                    320: buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr)
                    321: {
                    322:        u_int len;
                    323:        u_char *bin, *p, *ret;
                    324:
                    325:        if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) {
                    326:                error("%s: invalid bignum", __func__);
                    327:                return NULL;
                    328:        }
                    329:
                    330:        if (len > 0 && (bin[0] & 0x80)) {
                    331:                error("%s: negative numbers not supported", __func__);
                    332:                free(bin);
                    333:                return NULL;
                    334:        }
                    335:        if (len > 8 * 1024) {
                    336:                error("%s: cannot handle BN of size %d", __func__, len);
                    337:                free(bin);
                    338:                return NULL;
                    339:        }
                    340:        /* Skip zero prefix on numbers with the MSB set */
                    341:        if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) {
                    342:                p++;
                    343:                len--;
                    344:        }
                    345:        ret = xmalloc(len);
                    346:        memcpy(ret, p, len);
1.56    ! djm       347:        explicit_bzero(p, len);
1.54      djm       348:        free(bin);
                    349:        return ret;
                    350: }
                    351:
                    352: void *
                    353: buffer_get_bignum2_as_string(Buffer *buffer, u_int *l)
                    354: {
                    355:        void *ret = buffer_get_bignum2_as_string_ret(buffer, l);
                    356:
                    357:        if (ret == NULL)
                    358:                fatal("%s: buffer error", __func__);
                    359:        return ret;
                    360: }
                    361:
                    362: /*
                    363:  * Stores a string using the bignum encoding rules (\0 pad if MSB set).
                    364:  */
                    365: void
                    366: buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
                    367: {
                    368:        u_char *buf, *p;
                    369:        int pad = 0;
                    370:
                    371:        if (l > 8 * 1024)
                    372:                fatal("%s: length %u too long", __func__, l);
                    373:        p = buf = xmalloc(l + 1);
                    374:        /*
                    375:         * If most significant bit is set then prepend a zero byte to
                    376:         * avoid interpretation as a negative number.
                    377:         */
                    378:        if (l > 0 && (s[0] & 0x80) != 0) {
                    379:                *p++ = '\0';
                    380:                pad = 1;
                    381:        }
                    382:        memcpy(p, s, l);
                    383:        buffer_put_string(buffer, buf, l + pad);
1.56    ! djm       384:        explicit_bzero(buf, l + pad);
1.54      djm       385:        free(buf);
                    386: }
                    387:
                    388: