1 /* $OpenBSD: sshbuf-misc.c,v 1.7 2019/07/07 01:05:00 dtucker Exp $ */ 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 <sys/socket.h> 20 #include <netinet/in.h> 21 #include <errno.h> 22 #include <stdlib.h> 23 #include <stdint.h> 24 #include <stdio.h> 25 #include <limits.h> 26 #include <string.h> 27 #include <resolv.h> 28 #include <ctype.h> 29 30 #include "ssherr.h" 31 #define SSHBUF_INTERNAL 32 #include "sshbuf.h" 33 34 void 35 sshbuf_dump_data(const void *s, size_t len, FILE *f) 36 { 37 size_t i, j; 38 const u_char *p = (const u_char *)s; 39 40 for (i = 0; i < len; i += 16) { 41 fprintf(f, "%.4zu: ", i); 42 for (j = i; j < i + 16; j++) { 43 if (j < len) 44 fprintf(f, "%02x ", p[j]); 45 else 46 fprintf(f, " "); 47 } 48 fprintf(f, " "); 49 for (j = i; j < i + 16; j++) { 50 if (j < len) { 51 if (isascii(p[j]) && isprint(p[j])) 52 fprintf(f, "%c", p[j]); 53 else 54 fprintf(f, "."); 55 } 56 } 57 fprintf(f, "\n"); 58 } 59 } 60 61 void 62 sshbuf_dump(struct sshbuf *buf, FILE *f) 63 { 64 fprintf(f, "buffer %p len = %zu\n", buf, sshbuf_len(buf)); 65 sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f); 66 } 67 68 char * 69 sshbuf_dtob16(struct sshbuf *buf) 70 { 71 size_t i, j, len = sshbuf_len(buf); 72 const u_char *p = sshbuf_ptr(buf); 73 char *ret; 74 const char hex[] = "0123456789abcdef"; 75 76 if (len == 0) 77 return strdup(""); 78 if (SIZE_MAX / 2 <= len || (ret = malloc(len * 2 + 1)) == NULL) 79 return NULL; 80 for (i = j = 0; i < len; i++) { 81 ret[j++] = hex[(p[i] >> 4) & 0xf]; 82 ret[j++] = hex[p[i] & 0xf]; 83 } 84 ret[j] = '\0'; 85 return ret; 86 } 87 88 char * 89 sshbuf_dtob64(struct sshbuf *buf) 90 { 91 size_t len = sshbuf_len(buf), plen; 92 const u_char *p = sshbuf_ptr(buf); 93 char *ret; 94 95 if (len == 0) 96 return strdup(""); 97 plen = ((len + 2) / 3) * 4 + 1; 98 if (SIZE_MAX / 2 <= len || (ret = malloc(plen)) == NULL) 99 return NULL; 100 if (b64_ntop(p, len, ret, plen) == -1) { 101 explicit_bzero(ret, plen); 102 free(ret); 103 return NULL; 104 } 105 return ret; 106 } 107 108 int 109 sshbuf_b64tod(struct sshbuf *buf, const char *b64) 110 { 111 size_t plen = strlen(b64); 112 int nlen, r; 113 u_char *p; 114 115 if (plen == 0) 116 return 0; 117 if ((p = malloc(plen)) == NULL) 118 return SSH_ERR_ALLOC_FAIL; 119 if ((nlen = b64_pton(b64, p, plen)) < 0) { 120 explicit_bzero(p, plen); 121 free(p); 122 return SSH_ERR_INVALID_FORMAT; 123 } 124 if ((r = sshbuf_put(buf, p, nlen)) < 0) { 125 explicit_bzero(p, plen); 126 free(p); 127 return r; 128 } 129 explicit_bzero(p, plen); 130 free(p); 131 return 0; 132 } 133 134 char * 135 sshbuf_dup_string(struct sshbuf *buf) 136 { 137 const u_char *p = NULL, *s = sshbuf_ptr(buf); 138 size_t l = sshbuf_len(buf); 139 char *r; 140 141 if (s == NULL || l > SIZE_MAX) 142 return NULL; 143 /* accept a nul only as the last character in the buffer */ 144 if (l > 0 && (p = memchr(s, '\0', l)) != NULL) { 145 if (p != s + l - 1) 146 return NULL; 147 l--; /* the nul is put back below */ 148 } 149 if ((r = malloc(l + 1)) == NULL) 150 return NULL; 151 if (l > 0) 152 memcpy(r, s, l); 153 r[l] = '\0'; 154 return r; 155 } 156 157