[BACK]Return to sshbuf-getput-basic.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/sshbuf-getput-basic.c, Revision 1.1

1.1     ! djm         1: /*     $OpenBSD$       */
        !             2: /*
        !             3:  * Copyright (c) 2011 Damien Miller
        !             4:  *
        !             5:  * Permission to use, copy, modify, and distribute this software for any
        !             6:  * purpose with or without fee is hereby granted, provided that the above
        !             7:  * copyright notice and this permission notice appear in all copies.
        !             8:  *
        !             9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            16:  */
        !            17:
        !            18: #include <sys/types.h>
        !            19: #include <stdlib.h>
        !            20: #include <stdio.h>
        !            21: #include <string.h>
        !            22:
        !            23: #include "ssherr.h"
        !            24: #define SSHBUF_INTERNAL
        !            25: #include "sshbuf.h"
        !            26:
        !            27: int
        !            28: sshbuf_get(struct sshbuf *buf, void *v, size_t len)
        !            29: {
        !            30:        const u_char *p = sshbuf_ptr(buf);
        !            31:        int r;
        !            32:
        !            33:        if ((r = sshbuf_consume(buf, len)) < 0)
        !            34:                return r;
        !            35:        if (v != NULL)
        !            36:                memcpy(v, p, len);
        !            37:        return 0;
        !            38: }
        !            39:
        !            40: int
        !            41: sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp)
        !            42: {
        !            43:        const u_char *p = sshbuf_ptr(buf);
        !            44:        int r;
        !            45:
        !            46:        if ((r = sshbuf_consume(buf, 8)) < 0)
        !            47:                return r;
        !            48:        if (valp != NULL)
        !            49:                *valp = PEEK_U64(p);
        !            50:        return 0;
        !            51: }
        !            52:
        !            53: int
        !            54: sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp)
        !            55: {
        !            56:        const u_char *p = sshbuf_ptr(buf);
        !            57:        int r;
        !            58:
        !            59:        if ((r = sshbuf_consume(buf, 4)) < 0)
        !            60:                return r;
        !            61:        if (valp != NULL)
        !            62:                *valp = PEEK_U32(p);
        !            63:        return 0;
        !            64: }
        !            65:
        !            66: int
        !            67: sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp)
        !            68: {
        !            69:        const u_char *p = sshbuf_ptr(buf);
        !            70:        int r;
        !            71:
        !            72:        if ((r = sshbuf_consume(buf, 2)) < 0)
        !            73:                return r;
        !            74:        if (valp != NULL)
        !            75:                *valp = PEEK_U16(p);
        !            76:        return 0;
        !            77: }
        !            78:
        !            79: int
        !            80: sshbuf_get_u8(struct sshbuf *buf, u_char *valp)
        !            81: {
        !            82:        const u_char *p = sshbuf_ptr(buf);
        !            83:        int r;
        !            84:
        !            85:        if ((r = sshbuf_consume(buf, 1)) < 0)
        !            86:                return r;
        !            87:        if (valp != NULL)
        !            88:                *valp = (u_int8_t)*p;
        !            89:        return 0;
        !            90: }
        !            91:
        !            92: int
        !            93: sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp)
        !            94: {
        !            95:        const u_char *val;
        !            96:        size_t len;
        !            97:        int r;
        !            98:
        !            99:        if (valp != NULL)
        !           100:                *valp = NULL;
        !           101:        if (lenp != NULL)
        !           102:                *lenp = 0;
        !           103:        if ((r = sshbuf_get_string_direct(buf, &val, &len)) < 0)
        !           104:                return r;
        !           105:        if (valp != NULL) {
        !           106:                if ((*valp = malloc(len + 1)) == NULL) {
        !           107:                        SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
        !           108:                        return SSH_ERR_ALLOC_FAIL;
        !           109:                }
        !           110:                memcpy(*valp, val, len);
        !           111:                (*valp)[len] = '\0';
        !           112:        }
        !           113:        if (lenp != NULL)
        !           114:                *lenp = len;
        !           115:        return 0;
        !           116: }
        !           117:
        !           118: int
        !           119: sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp)
        !           120: {
        !           121:        size_t len;
        !           122:        const u_char *p;
        !           123:        int r;
        !           124:
        !           125:        if (valp != NULL)
        !           126:                *valp = NULL;
        !           127:        if (lenp != NULL)
        !           128:                *lenp = 0;
        !           129:        if ((r = sshbuf_peek_string_direct(buf, &p, &len)) < 0)
        !           130:                return r;
        !           131:        if (valp != 0)
        !           132:                *valp = p;
        !           133:        if (lenp != NULL)
        !           134:                *lenp = len;
        !           135:        if (sshbuf_consume(buf, len + 4) != 0) {
        !           136:                /* Shouldn't happen */
        !           137:                SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
        !           138:                SSHBUF_ABORT();
        !           139:                return SSH_ERR_INTERNAL_ERROR;
        !           140:        }
        !           141:        return 0;
        !           142: }
        !           143:
        !           144: int
        !           145: sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp,
        !           146:     size_t *lenp)
        !           147: {
        !           148:        u_int32_t len;
        !           149:        const u_char *p = sshbuf_ptr(buf);
        !           150:
        !           151:        if (valp != NULL)
        !           152:                *valp = NULL;
        !           153:        if (lenp != NULL)
        !           154:                *lenp = 0;
        !           155:        if (sshbuf_len(buf) < 4) {
        !           156:                SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
        !           157:                return SSH_ERR_MESSAGE_INCOMPLETE;
        !           158:        }
        !           159:        len = PEEK_U32(p);
        !           160:        if (len > SSHBUF_SIZE_MAX - 4) {
        !           161:                SSHBUF_DBG(("SSH_ERR_STRING_TOO_LARGE"));
        !           162:                return SSH_ERR_STRING_TOO_LARGE;
        !           163:        }
        !           164:        if (sshbuf_len(buf) - 4 < len) {
        !           165:                SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
        !           166:                return SSH_ERR_MESSAGE_INCOMPLETE;
        !           167:        }
        !           168:        if (valp != 0)
        !           169:                *valp = p + 4;
        !           170:        if (lenp != NULL)
        !           171:                *lenp = len;
        !           172:        return 0;
        !           173: }
        !           174:
        !           175: int
        !           176: sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp)
        !           177: {
        !           178:        size_t len;
        !           179:        const u_char *p, *z;
        !           180:        int r;
        !           181:
        !           182:        if (valp != NULL)
        !           183:                *valp = NULL;
        !           184:        if (lenp != NULL)
        !           185:                *lenp = 0;
        !           186:        if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0)
        !           187:                return r;
        !           188:        /* Allow a \0 only at the end of the string */
        !           189:        if (len > 0 &&
        !           190:            (z = memchr(p , '\0', len)) != NULL && z < p + len - 1) {
        !           191:                SSHBUF_DBG(("SSH_ERR_INVALID_FORMAT"));
        !           192:                return SSH_ERR_INVALID_FORMAT;
        !           193:        }
        !           194:        if ((r = sshbuf_skip_string(buf)) != 0)
        !           195:                return -1;
        !           196:        if (valp != NULL) {
        !           197:                if ((*valp = malloc(len + 1)) == NULL) {
        !           198:                        SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
        !           199:                        return SSH_ERR_ALLOC_FAIL;
        !           200:                }
        !           201:                memcpy(*valp, p, len);
        !           202:                (*valp)[len] = '\0';
        !           203:        }
        !           204:        if (lenp != NULL)
        !           205:                *lenp = (size_t)len;
        !           206:        return 0;
        !           207: }
        !           208:
        !           209: int
        !           210: sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v)
        !           211: {
        !           212:        u_int32_t len;
        !           213:        u_char *p;
        !           214:        int r;
        !           215:
        !           216:        /*
        !           217:         * Use sshbuf_peek_string_direct() to figure out if there is
        !           218:         * a complete string in 'buf' and copy the string directly
        !           219:         * into 'v'.
        !           220:         */
        !           221:        if ((r = sshbuf_peek_string_direct(buf, NULL, NULL)) != 0 ||
        !           222:            (r = sshbuf_get_u32(buf, &len)) != 0 ||
        !           223:            (r = sshbuf_reserve(v, len, &p)) != 0 ||
        !           224:            (r = sshbuf_get(buf, p, len)) != 0)
        !           225:                return r;
        !           226:        return 0;
        !           227: }
        !           228:
        !           229: int
        !           230: sshbuf_put(struct sshbuf *buf, const void *v, size_t len)
        !           231: {
        !           232:        u_char *p;
        !           233:        int r;
        !           234:
        !           235:        if ((r = sshbuf_reserve(buf, len, &p)) < 0)
        !           236:                return r;
        !           237:        memcpy(p, v, len);
        !           238:        return 0;
        !           239: }
        !           240:
        !           241: int
        !           242: sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v)
        !           243: {
        !           244:        return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v));
        !           245: }
        !           246:
        !           247: int
        !           248: sshbuf_putf(struct sshbuf *buf, const char *fmt, ...)
        !           249: {
        !           250:        va_list ap;
        !           251:        int r;
        !           252:
        !           253:        va_start(ap, fmt);
        !           254:        r = sshbuf_putfv(buf, fmt, ap);
        !           255:        va_end(ap);
        !           256:        return r;
        !           257: }
        !           258:
        !           259: int
        !           260: sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap)
        !           261: {
        !           262:        va_list ap2;
        !           263:        int r, len;
        !           264:        u_char *p;
        !           265:
        !           266:        va_copy(ap2, ap);
        !           267:        if ((len = vsnprintf(NULL, 0, fmt, ap2)) < 0) {
        !           268:                r = SSH_ERR_INVALID_ARGUMENT;
        !           269:                goto out;
        !           270:        }
        !           271:        if (len == 0) {
        !           272:                r = 0;
        !           273:                goto out; /* Nothing to do */
        !           274:        }
        !           275:        va_end(ap2);
        !           276:        va_copy(ap2, ap);
        !           277:        if ((r = sshbuf_reserve(buf, (size_t)len + 1, &p)) < 0)
        !           278:                goto out;
        !           279:        if ((r = vsnprintf((char *)p, len + 1, fmt, ap2)) != len) {
        !           280:                r = SSH_ERR_INTERNAL_ERROR;
        !           281:                goto out; /* Shouldn't happen */
        !           282:        }
        !           283:        /* Consume terminating \0 */
        !           284:        if ((r = sshbuf_consume_end(buf, 1)) != 0)
        !           285:                goto out;
        !           286:        r = 0;
        !           287:  out:
        !           288:        va_end(ap2);
        !           289:        return r;
        !           290: }
        !           291:
        !           292: int
        !           293: sshbuf_put_u64(struct sshbuf *buf, u_int64_t val)
        !           294: {
        !           295:        u_char *p;
        !           296:        int r;
        !           297:
        !           298:        if ((r = sshbuf_reserve(buf, 8, &p)) < 0)
        !           299:                return r;
        !           300:        POKE_U64(p, val);
        !           301:        return 0;
        !           302: }
        !           303:
        !           304: int
        !           305: sshbuf_put_u32(struct sshbuf *buf, u_int32_t val)
        !           306: {
        !           307:        u_char *p;
        !           308:        int r;
        !           309:
        !           310:        if ((r = sshbuf_reserve(buf, 4, &p)) < 0)
        !           311:                return r;
        !           312:        POKE_U32(p, val);
        !           313:        return 0;
        !           314: }
        !           315:
        !           316: int
        !           317: sshbuf_put_u16(struct sshbuf *buf, u_int16_t val)
        !           318: {
        !           319:        u_char *p;
        !           320:        int r;
        !           321:
        !           322:        if ((r = sshbuf_reserve(buf, 2, &p)) < 0)
        !           323:                return r;
        !           324:        POKE_U16(p, val);
        !           325:        return 0;
        !           326: }
        !           327:
        !           328: int
        !           329: sshbuf_put_u8(struct sshbuf *buf, u_char val)
        !           330: {
        !           331:        u_char *p;
        !           332:        int r;
        !           333:
        !           334:        if ((r = sshbuf_reserve(buf, 1, &p)) < 0)
        !           335:                return r;
        !           336:        p[0] = val;
        !           337:        return 0;
        !           338: }
        !           339:
        !           340: int
        !           341: sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len)
        !           342: {
        !           343:        u_char *d;
        !           344:        int r;
        !           345:
        !           346:        if (len > SSHBUF_SIZE_MAX - 4) {
        !           347:                SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE"));
        !           348:                return SSH_ERR_NO_BUFFER_SPACE;
        !           349:        }
        !           350:        if ((r = sshbuf_reserve(buf, len + 4, &d)) < 0)
        !           351:                return r;
        !           352:        POKE_U32(d, len);
        !           353:        memcpy(d + 4, v, len);
        !           354:        return 0;
        !           355: }
        !           356:
        !           357: int
        !           358: sshbuf_put_cstring(struct sshbuf *buf, const char *v)
        !           359: {
        !           360:        return sshbuf_put_string(buf, (u_char *)v, strlen(v));
        !           361: }
        !           362:
        !           363: int
        !           364: sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v)
        !           365: {
        !           366:        return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v));
        !           367: }
        !           368:
        !           369: int
        !           370: sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp)
        !           371: {
        !           372:        const u_char *p;
        !           373:        size_t len;
        !           374:        struct sshbuf *ret;
        !           375:        int r;
        !           376:
        !           377:        if (buf == NULL || bufp == NULL)
        !           378:                return SSH_ERR_INVALID_ARGUMENT;
        !           379:        *bufp = NULL;
        !           380:        if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0)
        !           381:                return r;
        !           382:        if ((ret = sshbuf_from(p, len)) == NULL)
        !           383:                return SSH_ERR_ALLOC_FAIL;
        !           384:        if ((r = sshbuf_consume(buf, len + 4)) != 0 ||  /* Shouldn't happen */
        !           385:            (r = sshbuf_set_parent(ret, buf)) != 0) {
        !           386:                sshbuf_free(ret);
        !           387:                return r;
        !           388:        }
        !           389:        *bufp = ret;
        !           390:        return 0;
        !           391: }
        !           392:
        !           393: int
        !           394: sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len)
        !           395: {
        !           396:        u_char *d;
        !           397:        const u_char *s = (const u_char *)v;
        !           398:        int r, prepend;
        !           399:
        !           400:        if (len > SSHBUF_SIZE_MAX - 5) {
        !           401:                SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE"));
        !           402:                return SSH_ERR_NO_BUFFER_SPACE;
        !           403:        }
        !           404:        /* Skip leading zero bytes */
        !           405:        for (; len > 0 && *s == 0; len--, s++)
        !           406:                ;
        !           407:        /*
        !           408:         * If most significant bit is set then prepend a zero byte to
        !           409:         * avoid interpretation as a negative number.
        !           410:         */
        !           411:        prepend = len > 0 && (s[0] & 0x80) != 0;
        !           412:        if ((r = sshbuf_reserve(buf, len + 4 + prepend, &d)) < 0)
        !           413:                return r;
        !           414:        POKE_U32(d, len + prepend);
        !           415:        if (prepend)
        !           416:                d[4] = 0;
        !           417:        memcpy(d + 4 + prepend, s, len);
        !           418:        return 0;
        !           419: }