From 597a9dc18b943498a3f42065e756e1b0a648987c Mon Sep 17 00:00:00 2001 From: beck <> Date: Sat, 12 Sep 2015 21:00:38 +0000 Subject: Move connection info into it's own private structure allocated and filled in at handshake time. change accessors to return const char * to remove need for caller to free memory. ok jsing@ --- src/lib/libtls/Makefile | 3 +- src/lib/libtls/tls.c | 17 +++-- src/lib/libtls/tls.h | 8 +-- src/lib/libtls/tls_conninfo.c | 149 ++++++++++++++++++++++++++++++++++++++++++ src/lib/libtls/tls_init.3 | 30 +++------ src/lib/libtls/tls_internal.h | 13 +++- src/lib/libtls/tls_peer.c | 108 +++++------------------------- 7 files changed, 208 insertions(+), 120 deletions(-) create mode 100644 src/lib/libtls/tls_conninfo.c (limited to 'src') diff --git a/src/lib/libtls/Makefile b/src/lib/libtls/Makefile index 1d7815f686..6e5914685c 100644 --- a/src/lib/libtls/Makefile +++ b/src/lib/libtls/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.18 2015/09/11 15:17:46 deraadt Exp $ +# $OpenBSD: Makefile,v 1.19 2015/09/12 21:00:38 beck Exp $ CFLAGS+= -Wall -Werror -Wimplicit CFLAGS+= -DLIBRESSL_INTERNAL @@ -15,6 +15,7 @@ HDRS= tls.h SRCS= tls.c \ tls_client.c \ tls_config.c \ + tls_conninfo.c \ tls_peer.c \ tls_server.c \ tls_util.c \ diff --git a/src/lib/libtls/tls.c b/src/lib/libtls/tls.c index 65103f106d..277970c932 100644 --- a/src/lib/libtls/tls.c +++ b/src/lib/libtls/tls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.c,v 1.26 2015/09/12 19:54:31 jsing Exp $ */ +/* $OpenBSD: tls.c,v 1.27 2015/09/12 21:00:38 beck Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -323,6 +323,10 @@ tls_reset(struct tls *ctx) free(ctx->errmsg); ctx->errmsg = NULL; ctx->errnum = 0; + + tls_free_conninfo(ctx->conninfo); + free(ctx->conninfo); + ctx->conninfo = NULL; } int @@ -376,14 +380,19 @@ tls_handshake(struct tls *ctx) { int rv = -1; + if ((ctx->conninfo = calloc(1, sizeof(*ctx->conninfo))) == NULL) + goto out; + if ((ctx->flags & TLS_CLIENT) != 0) rv = tls_handshake_client(ctx); else if ((ctx->flags & TLS_SERVER_CONN) != 0) rv = tls_handshake_server(ctx); - if (rv == 0) - ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn); - + if (rv == 0 && + (ctx->ssl_peer_cert = SSL_get_peer_certificate(ctx->ssl_conn)) && + (tls_get_conninfo(ctx) == -1)) + rv = -1; +out: /* Prevent callers from performing incorrect error handling */ errno = 0; return (rv); diff --git a/src/lib/libtls/tls.h b/src/lib/libtls/tls.h index 1a6cb47544..2f91ea68ba 100644 --- a/src/lib/libtls/tls.h +++ b/src/lib/libtls/tls.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls.h,v 1.21 2015/09/12 16:46:43 jsing Exp $ */ +/* $OpenBSD: tls.h,v 1.22 2015/09/12 21:00:38 beck Exp $ */ /* * Copyright (c) 2014 Joel Sing * @@ -102,9 +102,9 @@ int tls_close(struct tls *_ctx); int tls_peer_cert_provided(struct tls *ctx); int tls_peer_cert_contains_name(struct tls *ctx, const char *name); -int tls_peer_cert_hash(struct tls *_ctx, char **_hash); -int tls_peer_cert_issuer(struct tls *ctx, char **name); -int tls_peer_cert_subject(struct tls *ctx, char **subject); +const char * tls_peer_cert_hash(struct tls *_ctx); +const char * tls_peer_cert_issuer(struct tls *ctx); +const char * tls_peer_cert_subject(struct tls *ctx); uint8_t *tls_load_file(const char *_file, size_t *_len, char *_password); diff --git a/src/lib/libtls/tls_conninfo.c b/src/lib/libtls/tls_conninfo.c new file mode 100644 index 0000000000..267a8747c9 --- /dev/null +++ b/src/lib/libtls/tls_conninfo.c @@ -0,0 +1,149 @@ +/* $OpenBSD: tls_conninfo.c,v 1.1 2015/09/12 21:00:38 beck Exp $ */ +/* + * Copyright (c) 2015 Joel Sing + * Copyright (c) 2015 Bob Beck + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include +#include "tls_internal.h" + +static int +tls_hex_string(const unsigned char *in, size_t inlen, char **out, + size_t *outlen) +{ + static const char hex[] = "0123456789abcdef"; + size_t i, len; + char *p; + + if (outlen != NULL) + *outlen = 0; + + if (inlen >= SIZE_MAX) + return (-1); + if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL) + return (-1); + + p = *out; + len = 0; + for (i = 0; i < inlen; i++) { + p[len++] = hex[(in[i] >> 4) & 0x0f]; + p[len++] = hex[in[i] & 0x0f]; + } + p[len++] = 0; + + if (outlen != NULL) + *outlen = len; + + return (0); +} + +static int +tls_get_peer_cert_hash(struct tls *ctx, char **hash) +{ + char d[EVP_MAX_MD_SIZE], *dhex = NULL; + int dlen, rv = -1; + + *hash = NULL; + if (ctx->ssl_peer_cert == NULL) + return (0); + + if (X509_digest(ctx->ssl_peer_cert, EVP_sha256(), d, &dlen) != 1) { + tls_set_errorx(ctx, "digest failed"); + goto err; + } + + if (tls_hex_string(d, dlen, &dhex, NULL) != 0) { + tls_set_errorx(ctx, "digest hex string failed"); + goto err; + } + + if (asprintf(hash, "SHA256:%s", dhex) == -1) { + tls_set_errorx(ctx, "out of memory"); + *hash = NULL; + goto err; + } + + rv = 0; + +err: + free(dhex); + + return (rv); +} + +static int +tls_get_peer_cert_issuer(struct tls *ctx, char **issuer) +{ + X509_NAME *name = NULL; + + *issuer = NULL; + if (ctx->ssl_peer_cert == NULL) + return (-1); + if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL) + return (-1); + *issuer = X509_NAME_oneline(name, 0, 0); + if (*issuer == NULL) + return (-1); + return (0); +} + +static int +tls_get_peer_cert_subject(struct tls *ctx, char **subject) +{ + X509_NAME *name = NULL; + + *subject = NULL; + if (ctx->ssl_peer_cert == NULL) + return (-1); + if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL) + return (-1); + *subject = X509_NAME_oneline(name, 0, 0); + if (*subject == NULL) + return (-1); + return (0); +} + +int +tls_get_conninfo(struct tls *ctx) { + int rv = -1; + if (ctx->ssl_peer_cert != NULL) { + if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1) + goto err; + if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) + == -1) + goto err; + if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1) + goto err; + } + rv = 0; +err: + return (rv); +} + +void +tls_free_conninfo(struct tls_conninfo *conninfo) { + if (conninfo != NULL) { + free(conninfo->hash); + conninfo->hash = NULL; + free(conninfo->subject); + conninfo->subject = NULL; + free(conninfo->issuer); + conninfo->issuer = NULL; + } +} diff --git a/src/lib/libtls/tls_init.3 b/src/lib/libtls/tls_init.3 index a1fe52c83c..90cbdb3f3b 100644 --- a/src/lib/libtls/tls_init.3 +++ b/src/lib/libtls/tls_init.3 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tls_init.3,v 1.42 2015/09/11 14:22:53 jmc Exp $ +.\" $OpenBSD: tls_init.3,v 1.43 2015/09/12 21:00:38 beck Exp $ .\" .\" Copyright (c) 2014 Ted Unangst .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: September 11 2015 $ +.Dd $Mdocdate: September 12 2015 $ .Dt TLS_INIT 3 .Os .Sh NAME @@ -121,12 +121,12 @@ .Fn tls_peer_cert_provided "struct tls *ctx" .Ft "int" .Fn tls_peer_cert_contains_name "struct tls *ctx" "const char *name" -.Ft "int" -.Fn tls_peer_cert_issuer "struct tls *ctx" "char **issuer" -.Ft "int" -.Fn tls_peer_cert_subject "struct tls *ctx" "char **subject" -.Ft "int" -.Fn tls_peer_cert_hash "struct tls *ctx" "char **hash" +.Ft "const char *" +.Fn tls_peer_cert_issuer "struct tls *ctx" +.Ft "const char *" +.Fn tls_peer_cert_subject "struct tls *ctx" +.Ft "const char *" +.Fn tls_peer_cert_hash "struct tls *ctx" .Ft "uint8_t *" .Fn tls_load_file "const char *file" "size_t *len" "char *password" .Ft "struct tls *" @@ -386,31 +386,23 @@ can only succeed after the handshake is complete. .Em (Server and client) .It .Fn tls_peer_cert_subject -returns a string in -.Ar subject +returns a string corresponding to the subject of the peer certificate from .Ar ctx . .Fn tls_peer_cert_subject will only succeed after the handshake is complete. -Callers must free the string returned in -.Ar subject . .Em (Server and client) .It .Fn tls_peer_cert_issuer -returns a string in -.Ar subject +returns a string corresponding to the issuer of the peer certificate from .Ar ctx . .Fn tls_peer_cert_issuer will only succeed after the handshake is complete. -Callers must free the string returned in -.Ar issuer . .Em (Server and client) .It .Fn tls_peer_cert_hash returns a string -in -.Ar hash corresponding to a hash of the raw peer certificate from .Ar ctx prefixed by a hash name followed by a colon. @@ -426,8 +418,6 @@ printf "SHA256:${h}\\n" .Pp .Fn tls_peer_cert_subject will only succeed after the handshake is complete. -Callers must free the string returned in -.Ar hash . .Em (Server and client) .It .Fn tls_config_verify_client_opional diff --git a/src/lib/libtls/tls_internal.h b/src/lib/libtls/tls_internal.h index 34af0fb48a..e31c39a135 100644 --- a/src/lib/libtls/tls_internal.h +++ b/src/lib/libtls/tls_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_internal.h,v 1.20 2015/09/11 12:56:55 beck Exp $ */ +/* $OpenBSD: tls_internal.h,v 1.21 2015/09/12 21:00:38 beck Exp $ */ /* * Copyright (c) 2014 Jeremie Courreges-Anglas * Copyright (c) 2014 Joel Sing @@ -48,6 +48,14 @@ struct tls_config { int verify_name; }; +struct tls_conninfo { + char *issuer; + char *subject; + char *hash; + char *serial; + char *fingerprint; +}; + #define TLS_CLIENT (1 << 0) #define TLS_SERVER (1 << 1) #define TLS_SERVER_CONN (1 << 2) @@ -68,6 +76,7 @@ struct tls { SSL *ssl_conn; SSL_CTX *ssl_ctx; X509 *ssl_peer_cert; + struct tls_conninfo *conninfo; }; struct tls *tls_new(void); @@ -89,5 +98,7 @@ int tls_set_errorx(struct tls *ctx, const char *fmt, ...) __attribute__((__nonnull__ (2))); int tls_ssl_error(struct tls *ctx, SSL *ssl_conn, int ssl_ret, const char *prefix); +int tls_get_conninfo(struct tls *ctx); +void tls_free_conninfo(struct tls_conninfo *conninfo); #endif /* HEADER_TLS_INTERNAL_H */ diff --git a/src/lib/libtls/tls_peer.c b/src/lib/libtls/tls_peer.c index cd1984f215..3145e500c4 100644 --- a/src/lib/libtls/tls_peer.c +++ b/src/lib/libtls/tls_peer.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls_peer.c,v 1.3 2015/09/11 13:22:39 beck Exp $ */ +/* $OpenBSD: tls_peer.c,v 1.4 2015/09/12 21:00:38 beck Exp $ */ /* * Copyright (c) 2015 Joel Sing * Copyright (c) 2015 Bob Beck @@ -23,68 +23,27 @@ #include #include "tls_internal.h" -static int -tls_hex_string(const unsigned char *in, size_t inlen, char **out, - size_t *outlen) +const char * +tls_peer_cert_hash(struct tls *ctx) { - static const char hex[] = "0123456789abcdef"; - size_t i, len; - char *p; - - if (outlen != NULL) - *outlen = 0; - - if (inlen >= SIZE_MAX) - return (-1); - if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL) - return (-1); - - p = *out; - len = 0; - for (i = 0; i < inlen; i++) { - p[len++] = hex[(in[i] >> 4) & 0x0f]; - p[len++] = hex[in[i] & 0x0f]; - } - p[len++] = 0; - - if (outlen != NULL) - *outlen = len; - - return (0); + if (ctx->conninfo) + return (ctx->conninfo->hash); + return NULL; } - -int -tls_peer_cert_hash(struct tls *ctx, char **hash) +const char * +tls_peer_cert_issuer(struct tls *ctx) { - char d[EVP_MAX_MD_SIZE], *dhex = NULL; - int dlen, rv = -1; - - *hash = NULL; - if (ctx->ssl_peer_cert == NULL) - return (0); - - if (X509_digest(ctx->ssl_peer_cert, EVP_sha256(), d, &dlen) != 1) { - tls_set_errorx(ctx, "digest failed"); - goto err; - } - - if (tls_hex_string(d, dlen, &dhex, NULL) != 0) { - tls_set_errorx(ctx, "digest hex string failed"); - goto err; - } - - if (asprintf(hash, "SHA256:%s", dhex) == -1) { - tls_set_errorx(ctx, "out of memory"); - *hash = NULL; - goto err; - } - - rv = 0; - -err: - free(dhex); + if (ctx->conninfo) + return (ctx->conninfo->issuer); + return NULL; +} - return (rv); +const char * +tls_peer_cert_subject(struct tls *ctx) +{ + if (ctx->conninfo) + return (ctx->conninfo->subject); + return NULL; } int @@ -102,34 +61,3 @@ tls_peer_cert_contains_name(struct tls *ctx, const char *name) return (tls_check_name(ctx, ctx->ssl_peer_cert, name) == 0); } -int -tls_peer_cert_issuer(struct tls *ctx, char **issuer) -{ - X509_NAME *name = NULL; - - *issuer = NULL; - if (ctx->ssl_peer_cert == NULL) - return (-1); - if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL) - return (-1); - *issuer = X509_NAME_oneline(name, 0, 0); - if (*issuer == NULL) - return (-1); - return (0); -} - -int -tls_peer_cert_subject(struct tls *ctx, char **subject) -{ - X509_NAME *name = NULL; - - *subject = NULL; - if (ctx->ssl_peer_cert == NULL) - return (-1); - if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL) - return (-1); - *subject = X509_NAME_oneline(name, 0, 0); - if (*subject == NULL) - return (-1); - return (0); -} -- cgit v1.2.3-55-g6feb