diff options
author | Alistair Delva <adelva@google.com> | 2020-08-21 00:00:13 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2020-08-21 00:00:13 +0000 |
commit | ed358b3546c776c1c677fd88eb8f716cf6187510 (patch) | |
tree | 3c6134bcb2cda4b9dccc57b4a8b997a945aab62d /sshbuf-getput-basic.c | |
parent | 22246b08952d746a7cc5a292570636cf4277598f (diff) | |
parent | 44a1065de8a58c51a021243a28bfa01e87822e4f (diff) |
Merge changes I934c73d4,I28cdc9a0,I9e734da9,I3c079d86
* changes:
UPSTREAM: depend
UPSTREAM: upstream: avoid possible NULL deref; from Pedro Martelletto
Revert "upstream: fix compilation with DEBUG_KEXDH; bz#3160 ok dtucker@"
Merge upstream-master into master
Diffstat (limited to 'sshbuf-getput-basic.c')
-rw-r--r-- | sshbuf-getput-basic.c | 183 |
1 files changed, 176 insertions, 7 deletions
diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c index 8ff8a0a2..da834d00 100644 --- a/sshbuf-getput-basic.c +++ b/sshbuf-getput-basic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshbuf-getput-basic.c,v 1.4 2015/01/14 15:02:39 djm Exp $ */ +/* $OpenBSD: sshbuf-getput-basic.c,v 1.10 2019/12/13 19:09:37 djm Exp $ */ /* * Copyright (c) 2011 Damien Miller * @@ -19,9 +19,14 @@ #include "includes.h" #include <sys/types.h> + +#include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <string.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif #include "ssherr.h" #include "sshbuf.h" @@ -91,6 +96,93 @@ sshbuf_get_u8(struct sshbuf *buf, u_char *valp) return 0; } +static int +check_offset(const struct sshbuf *buf, int wr, size_t offset, size_t len) +{ + if (sshbuf_ptr(buf) == NULL) /* calls sshbuf_check_sanity() */ + return SSH_ERR_INTERNAL_ERROR; + if (offset >= SIZE_MAX - len) + return SSH_ERR_INVALID_ARGUMENT; + if (offset + len > sshbuf_len(buf)) { + return wr ? + SSH_ERR_NO_BUFFER_SPACE : SSH_ERR_MESSAGE_INCOMPLETE; + } + return 0; +} + +static int +check_roffset(const struct sshbuf *buf, size_t offset, size_t len, + const u_char **p) +{ + int r; + + *p = NULL; + if ((r = check_offset(buf, 0, offset, len)) != 0) + return r; + *p = sshbuf_ptr(buf) + offset; + return 0; +} + +int +sshbuf_peek_u64(const struct sshbuf *buf, size_t offset, u_int64_t *valp) +{ + const u_char *p = NULL; + int r; + + if (valp != NULL) + *valp = 0; + if ((r = check_roffset(buf, offset, 8, &p)) != 0) + return r; + if (valp != NULL) + *valp = PEEK_U64(p); + return 0; +} + +int +sshbuf_peek_u32(const struct sshbuf *buf, size_t offset, u_int32_t *valp) +{ + const u_char *p = NULL; + int r; + + if (valp != NULL) + *valp = 0; + if ((r = check_roffset(buf, offset, 4, &p)) != 0) + return r; + if (valp != NULL) + *valp = PEEK_U32(p); + return 0; +} + +int +sshbuf_peek_u16(const struct sshbuf *buf, size_t offset, u_int16_t *valp) +{ + const u_char *p = NULL; + int r; + + if (valp != NULL) + *valp = 0; + if ((r = check_roffset(buf, offset, 2, &p)) != 0) + return r; + if (valp != NULL) + *valp = PEEK_U16(p); + return 0; +} + +int +sshbuf_peek_u8(const struct sshbuf *buf, size_t offset, u_char *valp) +{ + const u_char *p = NULL; + int r; + + if (valp != NULL) + *valp = 0; + if ((r = check_roffset(buf, offset, 1, &p)) != 0) + return r; + if (valp != NULL) + *valp = *p; + return 0; +} + int sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp) { @@ -131,7 +223,7 @@ sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp) *lenp = 0; if ((r = sshbuf_peek_string_direct(buf, &p, &len)) < 0) return r; - if (valp != 0) + if (valp != NULL) *valp = p; if (lenp != NULL) *lenp = len; @@ -168,7 +260,7 @@ sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp, SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE")); return SSH_ERR_MESSAGE_INCOMPLETE; } - if (valp != 0) + if (valp != NULL) *valp = p + 4; if (lenp != NULL) *lenp = len; @@ -268,7 +360,7 @@ sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap) int r, len; u_char *p; - va_copy(ap2, ap); + VA_COPY(ap2, ap); if ((len = vsnprintf(NULL, 0, fmt, ap2)) < 0) { r = SSH_ERR_INVALID_ARGUMENT; goto out; @@ -278,7 +370,7 @@ sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap) goto out; /* Nothing to do */ } va_end(ap2); - va_copy(ap2, ap); + VA_COPY(ap2, ap); if ((r = sshbuf_reserve(buf, (size_t)len + 1, &p)) < 0) goto out; if ((r = vsnprintf((char *)p, len + 1, fmt, ap2)) != len) { @@ -342,6 +434,80 @@ sshbuf_put_u8(struct sshbuf *buf, u_char val) return 0; } +static int +check_woffset(struct sshbuf *buf, size_t offset, size_t len, u_char **p) +{ + int r; + + *p = NULL; + if ((r = check_offset(buf, 1, offset, len)) != 0) + return r; + if (sshbuf_mutable_ptr(buf) == NULL) + return SSH_ERR_BUFFER_READ_ONLY; + *p = sshbuf_mutable_ptr(buf) + offset; + return 0; +} + +int +sshbuf_poke_u64(struct sshbuf *buf, size_t offset, u_int64_t val) +{ + u_char *p = NULL; + int r; + + if ((r = check_woffset(buf, offset, 8, &p)) != 0) + return r; + POKE_U64(p, val); + return 0; +} + +int +sshbuf_poke_u32(struct sshbuf *buf, size_t offset, u_int32_t val) +{ + u_char *p = NULL; + int r; + + if ((r = check_woffset(buf, offset, 4, &p)) != 0) + return r; + POKE_U32(p, val); + return 0; +} + +int +sshbuf_poke_u16(struct sshbuf *buf, size_t offset, u_int16_t val) +{ + u_char *p = NULL; + int r; + + if ((r = check_woffset(buf, offset, 2, &p)) != 0) + return r; + POKE_U16(p, val); + return 0; +} + +int +sshbuf_poke_u8(struct sshbuf *buf, size_t offset, u_char val) +{ + u_char *p = NULL; + int r; + + if ((r = check_woffset(buf, offset, 1, &p)) != 0) + return r; + *p = val; + return 0; +} + +int +sshbuf_poke(struct sshbuf *buf, size_t offset, void *v, size_t len) +{ + u_char *p = NULL; + int r; + + if ((r = check_woffset(buf, offset, len, &p)) != 0) + return r; + memcpy(p, v, len); + return 0; +} + int sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len) { @@ -363,12 +529,15 @@ sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len) int sshbuf_put_cstring(struct sshbuf *buf, const char *v) { - return sshbuf_put_string(buf, (u_char *)v, v == NULL ? 0 : strlen(v)); + return sshbuf_put_string(buf, v, v == NULL ? 0 : strlen(v)); } int sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v) { + if (v == NULL) + return sshbuf_put_string(buf, NULL, 0); + return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v)); } @@ -448,7 +617,7 @@ sshbuf_get_bignum2_bytes_direct(struct sshbuf *buf, d++; len--; } - if (valp != 0) + if (valp != NULL) *valp = d; if (lenp != NULL) *lenp = len; |