1 /* $OpenBSD: tls_conninfo.c,v 1.15 2017/04/05 03:19:22 beck Exp $ */ 2 /* 3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org> 4 * Copyright (c) 2015 Bob Beck <beck@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <stdio.h> 20 21 #include <openssl/x509.h> 22 23 #include <tls.h> 24 #include "tls_internal.h" 25 26 int 27 tls_hex_string(const unsigned char *in, size_t inlen, char **out, 28 size_t *outlen) 29 { 30 static const char hex[] = "0123456789abcdef"; 31 size_t i, len; 32 char *p; 33 34 if (outlen != NULL) 35 *outlen = 0; 36 37 if (inlen >= SIZE_MAX) 38 return (-1); 39 if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL) 40 return (-1); 41 42 p = *out; 43 len = 0; 44 for (i = 0; i < inlen; i++) { 45 p[len++] = hex[(in[i] >> 4) & 0x0f]; 46 p[len++] = hex[in[i] & 0x0f]; 47 } 48 p[len++] = 0; 49 50 if (outlen != NULL) 51 *outlen = len; 52 53 return (0); 54 } 55 56 static int 57 tls_get_peer_cert_hash(struct tls *ctx, char **hash) 58 { 59 *hash = NULL; 60 if (ctx->ssl_peer_cert == NULL) 61 return (0); 62 63 if (tls_cert_hash(ctx->ssl_peer_cert, hash) == -1) { 64 tls_set_errorx(ctx, "unable to compute peer certificate hash - out of memory"); 65 *hash = NULL; 66 return -1; 67 } 68 return 0; 69 } 70 71 static int 72 tls_get_peer_cert_issuer(struct tls *ctx, char **issuer) 73 { 74 X509_NAME *name = NULL; 75 76 *issuer = NULL; 77 if (ctx->ssl_peer_cert == NULL) 78 return (-1); 79 if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL) 80 return (-1); 81 *issuer = X509_NAME_oneline(name, 0, 0); 82 if (*issuer == NULL) 83 return (-1); 84 return (0); 85 } 86 87 static int 88 tls_get_peer_cert_subject(struct tls *ctx, char **subject) 89 { 90 X509_NAME *name = NULL; 91 92 *subject = NULL; 93 if (ctx->ssl_peer_cert == NULL) 94 return (-1); 95 if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL) 96 return (-1); 97 *subject = X509_NAME_oneline(name, 0, 0); 98 if (*subject == NULL) 99 return (-1); 100 return (0); 101 } 102 103 static int 104 tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, 105 time_t *notafter) 106 { 107 struct tm before_tm, after_tm; 108 ASN1_TIME *before, *after; 109 110 if (ctx->ssl_peer_cert == NULL) 111 return (-1); 112 113 memset(&before_tm, 0, sizeof(before_tm)); 114 memset(&after_tm, 0, sizeof(after_tm)); 115 116 if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL) 117 goto err; 118 if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL) 119 goto err; 120 if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1) 121 goto err; 122 if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1) 123 goto err; 124 if ((*notbefore = timegm(&before_tm)) == -1) 125 goto err; 126 if ((*notafter = timegm(&after_tm)) == -1) 127 goto err; 128 129 return (0); 130 131 err: 132 return (-1); 133 } 134 135 static int 136 tls_get_peer_cert_info(struct tls *ctx) 137 { 138 if (ctx->ssl_peer_cert == NULL) 139 return (0); 140 141 if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1) 142 goto err; 143 if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1) 144 goto err; 145 if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1) 146 goto err; 147 if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore, 148 &ctx->conninfo->notafter) == -1) 149 goto err; 150 151 return (0); 152 153 err: 154 return (-1); 155 } 156 157 static int 158 tls_conninfo_alpn_proto(struct tls *ctx) 159 { 160 const unsigned char *p; 161 unsigned int len; 162 163 free(ctx->conninfo->alpn); 164 ctx->conninfo->alpn = NULL; 165 166 SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len); 167 if (len > 0) { 168 if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL) 169 return (-1); 170 memcpy(ctx->conninfo->alpn, p, len); 171 ctx->conninfo->alpn[len] = '\0'; 172 } 173 174 return (0); 175 } 176 177 static int 178 tls_conninfo_cert_pem(struct tls *ctx) 179 { 180 int i, rv = -1; 181 BIO *membio = NULL; 182 BUF_MEM *bptr = NULL; 183 184 if (ctx->conninfo == NULL) 185 goto err; 186 if (ctx->ssl_peer_cert == NULL) 187 return 0; 188 if ((membio = BIO_new(BIO_s_mem()))== NULL) 189 goto err; 190 191 /* 192 * We have to write the peer cert out separately, because 193 * the certificate chain may or may not contain it. 194 */ 195 if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert)) 196 goto err; 197 for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) { 198 X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i); 199 if (chaincert != ctx->ssl_peer_cert && 200 !PEM_write_bio_X509(membio, chaincert)) 201 goto err; 202 } 203 204 BIO_get_mem_ptr(membio, &bptr); 205 free(ctx->conninfo->peer_cert); 206 ctx->conninfo->peer_cert_len = 0; 207 if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL) 208 goto err; 209 ctx->conninfo->peer_cert_len = bptr->length; 210 memcpy(ctx->conninfo->peer_cert, bptr->data, 211 ctx->conninfo->peer_cert_len); 212 213 /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */ 214 rv = 0; 215 err: 216 BIO_free(membio); 217 return rv; 218 } 219 220 int 221 tls_conninfo_populate(struct tls *ctx) 222 { 223 const char *tmp; 224 225 tls_conninfo_free(ctx->conninfo); 226 227 if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) { 228 tls_set_errorx(ctx, "out of memory"); 229 goto err; 230 } 231 232 if (tls_conninfo_alpn_proto(ctx) == -1) 233 goto err; 234 235 if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL) 236 goto err; 237 ctx->conninfo->cipher = strdup(tmp); 238 if (ctx->conninfo->cipher == NULL) 239 goto err; 240 241 if (ctx->servername != NULL) { 242 if ((ctx->conninfo->servername = 243 strdup(ctx->servername)) == NULL) 244 goto err; 245 } 246 247 if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL) 248 goto err; 249 ctx->conninfo->version = strdup(tmp); 250 if (ctx->conninfo->version == NULL) 251 goto err; 252 253 if (tls_get_peer_cert_info(ctx) == -1) 254 goto err; 255 256 if (tls_conninfo_cert_pem(ctx) == -1) 257 goto err; 258 259 return (0); 260 261 err: 262 tls_conninfo_free(ctx->conninfo); 263 ctx->conninfo = NULL; 264 265 return (-1); 266 } 267 268 void 269 tls_conninfo_free(struct tls_conninfo *conninfo) 270 { 271 if (conninfo == NULL) 272 return; 273 274 free(conninfo->alpn); 275 conninfo->alpn = NULL; 276 free(conninfo->cipher); 277 conninfo->cipher = NULL; 278 free(conninfo->servername); 279 conninfo->servername = NULL; 280 free(conninfo->version); 281 conninfo->version = NULL; 282 283 free(conninfo->hash); 284 conninfo->hash = NULL; 285 free(conninfo->issuer); 286 conninfo->issuer = NULL; 287 free(conninfo->subject); 288 conninfo->subject = NULL; 289 290 free(conninfo->peer_cert); 291 conninfo->peer_cert = NULL; 292 conninfo->peer_cert_len = 0; 293 294 free(conninfo); 295 } 296 297 const char * 298 tls_conn_alpn_selected(struct tls *ctx) 299 { 300 if (ctx->conninfo == NULL) 301 return (NULL); 302 return (ctx->conninfo->alpn); 303 } 304 305 const char * 306 tls_conn_cipher(struct tls *ctx) 307 { 308 if (ctx->conninfo == NULL) 309 return (NULL); 310 return (ctx->conninfo->cipher); 311 } 312 313 const char * 314 tls_conn_servername(struct tls *ctx) 315 { 316 if (ctx->conninfo == NULL) 317 return (NULL); 318 return (ctx->conninfo->servername); 319 } 320 321 const char * 322 tls_conn_version(struct tls *ctx) 323 { 324 if (ctx->conninfo == NULL) 325 return (NULL); 326 return (ctx->conninfo->version); 327 } 328 329