preprocessor cleanup: __lint
[unleashed/tickless.git] / lib / libtls / tls_conninfo.c
blob5cdd0f77c8f9c6a4c67d249bee036a6031f7d3dd
1 /* $OpenBSD: tls_conninfo.c,v 1.13 2017/01/09 15:31:20 jsing Exp $ */
2 /*
3 * Copyright (c) 2015 Joel Sing <jsing@openbsd.org>
4 * Copyright (c) 2015 Bob Beck <beck@openbsd.org>
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.
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.
19 #include <stdio.h>
21 #include <openssl/x509.h>
23 #include <tls.h>
24 #include "tls_internal.h"
26 static int
27 tls_hex_string(const unsigned char *in, size_t inlen, char **out,
28 size_t *outlen)
30 static const char hex[] = "0123456789abcdef";
31 size_t i, len;
32 char *p;
34 if (outlen != NULL)
35 *outlen = 0;
37 if (inlen >= SIZE_MAX)
38 return (-1);
39 if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL)
40 return (-1);
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];
48 p[len++] = 0;
50 if (outlen != NULL)
51 *outlen = len;
53 return (0);
56 static int
57 tls_get_peer_cert_hash(struct tls *ctx, char **hash)
59 char d[EVP_MAX_MD_SIZE], *dhex = NULL;
60 int dlen, rv = -1;
62 *hash = NULL;
63 if (ctx->ssl_peer_cert == NULL)
64 return (0);
66 if (X509_digest(ctx->ssl_peer_cert, EVP_sha256(), d, &dlen) != 1) {
67 tls_set_errorx(ctx, "digest failed");
68 goto err;
71 if (tls_hex_string(d, dlen, &dhex, NULL) != 0) {
72 tls_set_errorx(ctx, "digest hex string failed");
73 goto err;
76 if (asprintf(hash, "SHA256:%s", dhex) == -1) {
77 tls_set_errorx(ctx, "out of memory");
78 *hash = NULL;
79 goto err;
82 rv = 0;
84 err:
85 free(dhex);
87 return (rv);
90 static int
91 tls_get_peer_cert_issuer(struct tls *ctx, char **issuer)
93 X509_NAME *name = NULL;
95 *issuer = NULL;
96 if (ctx->ssl_peer_cert == NULL)
97 return (-1);
98 if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL)
99 return (-1);
100 *issuer = X509_NAME_oneline(name, 0, 0);
101 if (*issuer == NULL)
102 return (-1);
103 return (0);
106 static int
107 tls_get_peer_cert_subject(struct tls *ctx, char **subject)
109 X509_NAME *name = NULL;
111 *subject = NULL;
112 if (ctx->ssl_peer_cert == NULL)
113 return (-1);
114 if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL)
115 return (-1);
116 *subject = X509_NAME_oneline(name, 0, 0);
117 if (*subject == NULL)
118 return (-1);
119 return (0);
122 static int
123 tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore,
124 time_t *notafter)
126 struct tm before_tm, after_tm;
127 ASN1_TIME *before, *after;
129 if (ctx->ssl_peer_cert == NULL)
130 return (-1);
132 memset(&before_tm, 0, sizeof(before_tm));
133 memset(&after_tm, 0, sizeof(after_tm));
135 if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL)
136 goto err;
137 if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL)
138 goto err;
139 if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1)
140 goto err;
141 if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1)
142 goto err;
143 if ((*notbefore = timegm(&before_tm)) == -1)
144 goto err;
145 if ((*notafter = timegm(&after_tm)) == -1)
146 goto err;
148 return (0);
150 err:
151 return (-1);
154 static int
155 tls_get_peer_cert_info(struct tls *ctx)
157 if (ctx->ssl_peer_cert == NULL)
158 return (0);
160 if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1)
161 goto err;
162 if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1)
163 goto err;
164 if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1)
165 goto err;
166 if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore,
167 &ctx->conninfo->notafter) == -1)
168 goto err;
170 return (0);
172 err:
173 return (-1);
176 static int
177 tls_conninfo_alpn_proto(struct tls *ctx)
179 const unsigned char *p;
180 unsigned int len;
182 free(ctx->conninfo->alpn);
183 ctx->conninfo->alpn = NULL;
185 SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len);
186 if (len > 0) {
187 if ((ctx->conninfo->alpn = malloc(len + 1)) == NULL)
188 return (-1);
189 memcpy(ctx->conninfo->alpn, p, len);
190 ctx->conninfo->alpn[len] = '\0';
193 return (0);
197 tls_conninfo_populate(struct tls *ctx)
199 const char *tmp;
201 tls_conninfo_free(ctx->conninfo);
203 if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) {
204 tls_set_errorx(ctx, "out of memory");
205 goto err;
208 if (tls_conninfo_alpn_proto(ctx) == -1)
209 goto err;
211 if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL)
212 goto err;
213 ctx->conninfo->cipher = strdup(tmp);
214 if (ctx->conninfo->cipher == NULL)
215 goto err;
217 if (ctx->servername != NULL) {
218 if ((ctx->conninfo->servername =
219 strdup(ctx->servername)) == NULL)
220 goto err;
223 if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL)
224 goto err;
225 ctx->conninfo->version = strdup(tmp);
226 if (ctx->conninfo->version == NULL)
227 goto err;
229 if (tls_get_peer_cert_info(ctx) == -1)
230 goto err;
232 return (0);
234 err:
235 tls_conninfo_free(ctx->conninfo);
236 ctx->conninfo = NULL;
238 return (-1);
241 void
242 tls_conninfo_free(struct tls_conninfo *conninfo)
244 if (conninfo == NULL)
245 return;
247 free(conninfo->alpn);
248 conninfo->alpn = NULL;
249 free(conninfo->cipher);
250 conninfo->cipher = NULL;
251 free(conninfo->servername);
252 conninfo->servername = NULL;
253 free(conninfo->version);
254 conninfo->version = NULL;
256 free(conninfo->hash);
257 conninfo->hash = NULL;
258 free(conninfo->issuer);
259 conninfo->issuer = NULL;
260 free(conninfo->subject);
261 conninfo->subject = NULL;
263 free(conninfo);
266 const char *
267 tls_conn_alpn_selected(struct tls *ctx)
269 if (ctx->conninfo == NULL)
270 return (NULL);
271 return (ctx->conninfo->alpn);
274 const char *
275 tls_conn_cipher(struct tls *ctx)
277 if (ctx->conninfo == NULL)
278 return (NULL);
279 return (ctx->conninfo->cipher);
282 const char *
283 tls_conn_servername(struct tls *ctx)
285 if (ctx->conninfo == NULL)
286 return (NULL);
287 return (ctx->conninfo->servername);
290 const char *
291 tls_conn_version(struct tls *ctx)
293 if (ctx->conninfo == NULL)
294 return (NULL);
295 return (ctx->conninfo->version);