1 /* $OpenBSD: tls_conninfo.c,v 1.21 2019/11/02 13:37:59 jsing 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 ASN1_time_tm_clamp_notafter(struct tm *tm); 27 28 int 29 tls_hex_string(const unsigned char *in, size_t inlen, char **out, 30 size_t *outlen) 31 { 32 static const char hex[] = "0123456789abcdef"; 33 size_t i, len; 34 char *p; 35 36 if (outlen != NULL) 37 *outlen = 0; 38 39 if (inlen >= SIZE_MAX) 40 return (-1); 41 if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL) 42 return (-1); 43 44 p = *out; 45 len = 0; 46 for (i = 0; i < inlen; i++) { 47 p[len++] = hex[(in[i] >> 4) & 0x0f]; 48 p[len++] = hex[in[i] & 0x0f]; 49 } 50 p[len++] = 0; 51 52 if (outlen != NULL) 53 *outlen = len; 54 55 return (0); 56 } 57 58 static int 59 tls_get_peer_cert_hash(struct tls *ctx, char **hash) 60 { 61 *hash = NULL; 62 if (ctx->ssl_peer_cert == NULL) 63 return (0); 64 65 if (tls_cert_hash(ctx->ssl_peer_cert, hash) == -1) { 66 tls_set_errorx(ctx, "unable to compute peer certificate hash - out of memory"); 67 *hash = NULL; 68 return -1; 69 } 70 return 0; 71 } 72 73 static int 74 tls_get_peer_cert_issuer(struct tls *ctx, char **issuer) 75 { 76 X509_NAME *name = NULL; 77 78 *issuer = NULL; 79 if (ctx->ssl_peer_cert == NULL) 80 return (-1); 81 if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL) 82 return (-1); 83 *issuer = X509_NAME_oneline(name, 0, 0); 84 if (*issuer == NULL) 85 return (-1); 86 return (0); 87 } 88 89 static int 90 tls_get_peer_cert_subject(struct tls *ctx, char **subject) 91 { 92 X509_NAME *name = NULL; 93 94 *subject = NULL; 95 if (ctx->ssl_peer_cert == NULL) 96 return (-1); 97 if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL) 98 return (-1); 99 *subject = X509_NAME_oneline(name, 0, 0); 100 if (*subject == NULL) 101 return (-1); 102 return (0); 103 } 104 105 static int 106 tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore, 107 time_t *notafter) 108 { 109 struct tm before_tm, after_tm; 110 ASN1_TIME *before, *after; 111 112 if (ctx->ssl_peer_cert == NULL) 113 return (-1); 114 115 memset(&before_tm, 0, sizeof(before_tm)); 116 memset(&after_tm, 0, sizeof(after_tm)); 117 118 if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL) 119 goto err; 120 if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL) 121 goto err; 122 if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1) 123 goto err; 124 if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1) 125 goto err; 126 if (!ASN1_time_tm_clamp_notafter(&after_tm)) 127 goto err; 128 if ((*notbefore = timegm(&before_tm)) == -1) 129 goto err; 130 if ((*notafter = timegm(&after_tm)) == -1) 131 goto err; 132 133 return (0); 134 135 err: 136 return (-1); 137 } 138 139 static int 140 tls_get_peer_cert_info(struct tls *ctx) 141 { 142 if (ctx->ssl_peer_cert == NULL) 143 return (0); 144 145 if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1) 146 goto err; 147 if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1) 148 goto err; 149 if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1) 150 goto err; 151 if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore, 152 &ctx->conninfo->notafter) == -1) 153 goto err; 154 155 return (0); 156 157 err: 158 return (-1); 159 } 160 161 static int 162 tls_conninfo_alpn_proto(struct tls *ctx) 163 { 164 const unsigned char *p; 165 unsigned int len; 166 167 free(ctx->conninfo->alpn); 168 ctx->conninfo->alpn = NULL; 169 170 SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len); 171 if (len > 0) { 172 if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL) 173 return (-1); 174 memcpy(ctx->conninfo->alpn, p, len); 175 ctx->conninfo->alpn[len] = '\0'; 176 } 177 178 return (0); 179 } 180 181 static int 182 tls_conninfo_cert_pem(struct tls *ctx) 183 { 184 int i, rv = -1; 185 BIO *membio = NULL; 186 BUF_MEM *bptr = NULL; 187 188 if (ctx->ssl_peer_cert == NULL) 189 return 0; 190 if ((membio = BIO_new(BIO_s_mem()))== NULL) 191 goto err; 192 193 /* 194 * We have to write the peer cert out separately, because 195 * the certificate chain may or may not contain it. 196 */ 197 if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert)) 198 goto err; 199 for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) { 200 X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i); 201 if (chaincert != ctx->ssl_peer_cert && 202 !PEM_write_bio_X509(membio, chaincert)) 203 goto err; 204 } 205 206 BIO_get_mem_ptr(membio, &bptr); 207 free(ctx->conninfo->peer_cert); 208 ctx->conninfo->peer_cert_len = 0; 209 if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL) 210 goto err; 211 ctx->conninfo->peer_cert_len = bptr->length; 212 memcpy(ctx->conninfo->peer_cert, bptr->data, 213 ctx->conninfo->peer_cert_len); 214 215 /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */ 216 rv = 0; 217 err: 218 BIO_free(membio); 219 return rv; 220 } 221 222 static int 223 tls_conninfo_session(struct tls *ctx) 224 { 225 ctx->conninfo->session_resumed = SSL_session_reused(ctx->ssl_conn); 226 227 return 0; 228 } 229 230 int 231 tls_conninfo_populate(struct tls *ctx) 232 { 233 const char *tmp; 234 235 tls_conninfo_free(ctx->conninfo); 236 237 if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) { 238 tls_set_errorx(ctx, "out of memory"); 239 goto err; 240 } 241 242 if (tls_conninfo_alpn_proto(ctx) == -1) 243 goto err; 244 245 if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL) 246 goto err; 247 if ((ctx->conninfo->cipher = strdup(tmp)) == NULL) 248 goto err; 249 ctx->conninfo->cipher_strength = SSL_get_cipher_bits(ctx->ssl_conn, NULL); 250 251 if (ctx->servername != NULL) { 252 if ((ctx->conninfo->servername = 253 strdup(ctx->servername)) == NULL) 254 goto err; 255 } 256 257 if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL) 258 goto err; 259 if ((ctx->conninfo->version = strdup(tmp)) == NULL) 260 goto err; 261 262 if (tls_get_peer_cert_info(ctx) == -1) 263 goto err; 264 265 if (tls_conninfo_cert_pem(ctx) == -1) 266 goto err; 267 268 if (tls_conninfo_session(ctx) == -1) 269 goto err; 270 271 return (0); 272 273 err: 274 tls_conninfo_free(ctx->conninfo); 275 ctx->conninfo = NULL; 276 277 return (-1); 278 } 279 280 void 281 tls_conninfo_free(struct tls_conninfo *conninfo) 282 { 283 if (conninfo == NULL) 284 return; 285 286 free(conninfo->alpn); 287 free(conninfo->cipher); 288 free(conninfo->servername); 289 free(conninfo->version); 290 291 free(conninfo->hash); 292 free(conninfo->issuer); 293 free(conninfo->subject); 294 295 free(conninfo->peer_cert); 296 297 free(conninfo); 298 } 299 300 const char * 301 tls_conn_alpn_selected(struct tls *ctx) 302 { 303 if (ctx->conninfo == NULL) 304 return (NULL); 305 return (ctx->conninfo->alpn); 306 } 307 308 const char * 309 tls_conn_cipher(struct tls *ctx) 310 { 311 if (ctx->conninfo == NULL) 312 return (NULL); 313 return (ctx->conninfo->cipher); 314 } 315 316 int 317 tls_conn_cipher_strength(struct tls *ctx) 318 { 319 if (ctx->conninfo == NULL) 320 return (0); 321 return (ctx->conninfo->cipher_strength); 322 } 323 324 const char * 325 tls_conn_servername(struct tls *ctx) 326 { 327 if (ctx->conninfo == NULL) 328 return (NULL); 329 return (ctx->conninfo->servername); 330 } 331 332 int 333 tls_conn_session_resumed(struct tls *ctx) 334 { 335 if (ctx->conninfo == NULL) 336 return (0); 337 return (ctx->conninfo->session_resumed); 338 } 339 340 const char * 341 tls_conn_version(struct tls *ctx) 342 { 343 if (ctx->conninfo == NULL) 344 return (NULL); 345 return (ctx->conninfo->version); 346 } 347