1323124Sdes/* $OpenBSD: sshbuf-misc.c,v 1.6 2016/05/02 08:49:03 djm Exp $ */ 2276707Sdes/* 3276707Sdes * Copyright (c) 2011 Damien Miller 4276707Sdes * 5276707Sdes * Permission to use, copy, modify, and distribute this software for any 6276707Sdes * purpose with or without fee is hereby granted, provided that the above 7276707Sdes * copyright notice and this permission notice appear in all copies. 8276707Sdes * 9276707Sdes * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10276707Sdes * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11276707Sdes * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12276707Sdes * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13276707Sdes * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14276707Sdes * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15276707Sdes * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16276707Sdes */ 17276707Sdes 18276707Sdes#include "includes.h" 19276707Sdes 20276707Sdes#include <sys/types.h> 21276707Sdes#include <sys/socket.h> 22276707Sdes#include <netinet/in.h> 23276707Sdes#include <errno.h> 24276707Sdes#include <stdlib.h> 25295367Sdes#ifdef HAVE_STDINT_H 26295367Sdes#include <stdint.h> 27295367Sdes#endif 28276707Sdes#include <stdio.h> 29276707Sdes#include <limits.h> 30276707Sdes#include <string.h> 31276707Sdes#include <resolv.h> 32276707Sdes#include <ctype.h> 33276707Sdes 34276707Sdes#include "ssherr.h" 35276707Sdes#define SSHBUF_INTERNAL 36276707Sdes#include "sshbuf.h" 37276707Sdes 38276707Sdesvoid 39276707Sdessshbuf_dump_data(const void *s, size_t len, FILE *f) 40276707Sdes{ 41276707Sdes size_t i, j; 42276707Sdes const u_char *p = (const u_char *)s; 43276707Sdes 44276707Sdes for (i = 0; i < len; i += 16) { 45295367Sdes fprintf(f, "%.4zu: ", i); 46276707Sdes for (j = i; j < i + 16; j++) { 47276707Sdes if (j < len) 48276707Sdes fprintf(f, "%02x ", p[j]); 49276707Sdes else 50276707Sdes fprintf(f, " "); 51276707Sdes } 52276707Sdes fprintf(f, " "); 53276707Sdes for (j = i; j < i + 16; j++) { 54276707Sdes if (j < len) { 55276707Sdes if (isascii(p[j]) && isprint(p[j])) 56276707Sdes fprintf(f, "%c", p[j]); 57276707Sdes else 58276707Sdes fprintf(f, "."); 59276707Sdes } 60276707Sdes } 61276707Sdes fprintf(f, "\n"); 62276707Sdes } 63276707Sdes} 64276707Sdes 65276707Sdesvoid 66276707Sdessshbuf_dump(struct sshbuf *buf, FILE *f) 67276707Sdes{ 68276707Sdes fprintf(f, "buffer %p len = %zu\n", buf, sshbuf_len(buf)); 69276707Sdes sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f); 70276707Sdes} 71276707Sdes 72276707Sdeschar * 73276707Sdessshbuf_dtob16(struct sshbuf *buf) 74276707Sdes{ 75276707Sdes size_t i, j, len = sshbuf_len(buf); 76276707Sdes const u_char *p = sshbuf_ptr(buf); 77276707Sdes char *ret; 78276707Sdes const char hex[] = "0123456789abcdef"; 79276707Sdes 80276707Sdes if (len == 0) 81276707Sdes return strdup(""); 82276707Sdes if (SIZE_MAX / 2 <= len || (ret = malloc(len * 2 + 1)) == NULL) 83276707Sdes return NULL; 84276707Sdes for (i = j = 0; i < len; i++) { 85276707Sdes ret[j++] = hex[(p[i] >> 4) & 0xf]; 86276707Sdes ret[j++] = hex[p[i] & 0xf]; 87276707Sdes } 88276707Sdes ret[j] = '\0'; 89276707Sdes return ret; 90276707Sdes} 91276707Sdes 92276707Sdeschar * 93276707Sdessshbuf_dtob64(struct sshbuf *buf) 94276707Sdes{ 95276707Sdes size_t len = sshbuf_len(buf), plen; 96276707Sdes const u_char *p = sshbuf_ptr(buf); 97276707Sdes char *ret; 98276707Sdes int r; 99276707Sdes 100276707Sdes if (len == 0) 101276707Sdes return strdup(""); 102276707Sdes plen = ((len + 2) / 3) * 4 + 1; 103276707Sdes if (SIZE_MAX / 2 <= len || (ret = malloc(plen)) == NULL) 104276707Sdes return NULL; 105276707Sdes if ((r = b64_ntop(p, len, ret, plen)) == -1) { 106295367Sdes explicit_bzero(ret, plen); 107276707Sdes free(ret); 108276707Sdes return NULL; 109276707Sdes } 110276707Sdes return ret; 111276707Sdes} 112276707Sdes 113276707Sdesint 114276707Sdessshbuf_b64tod(struct sshbuf *buf, const char *b64) 115276707Sdes{ 116276707Sdes size_t plen = strlen(b64); 117276707Sdes int nlen, r; 118276707Sdes u_char *p; 119276707Sdes 120276707Sdes if (plen == 0) 121276707Sdes return 0; 122276707Sdes if ((p = malloc(plen)) == NULL) 123276707Sdes return SSH_ERR_ALLOC_FAIL; 124276707Sdes if ((nlen = b64_pton(b64, p, plen)) < 0) { 125295367Sdes explicit_bzero(p, plen); 126276707Sdes free(p); 127276707Sdes return SSH_ERR_INVALID_FORMAT; 128276707Sdes } 129276707Sdes if ((r = sshbuf_put(buf, p, nlen)) < 0) { 130295367Sdes explicit_bzero(p, plen); 131276707Sdes free(p); 132276707Sdes return r; 133276707Sdes } 134295367Sdes explicit_bzero(p, plen); 135276707Sdes free(p); 136276707Sdes return 0; 137276707Sdes} 138276707Sdes 139323124Sdeschar * 140323124Sdessshbuf_dup_string(struct sshbuf *buf) 141323124Sdes{ 142323124Sdes const u_char *p = NULL, *s = sshbuf_ptr(buf); 143323124Sdes size_t l = sshbuf_len(buf); 144323124Sdes char *r; 145323124Sdes 146323124Sdes if (s == NULL || l > SIZE_MAX) 147323124Sdes return NULL; 148323124Sdes /* accept a nul only as the last character in the buffer */ 149323124Sdes if (l > 0 && (p = memchr(s, '\0', l)) != NULL) { 150323124Sdes if (p != s + l - 1) 151323124Sdes return NULL; 152323124Sdes l--; /* the nul is put back below */ 153323124Sdes } 154323124Sdes if ((r = malloc(l + 1)) == NULL) 155323124Sdes return NULL; 156323124Sdes if (l > 0) 157323124Sdes memcpy(r, s, l); 158323124Sdes r[l] = '\0'; 159323124Sdes return r; 160323124Sdes} 161323124Sdes 162