import less(1)
[unleashed/tickless.git] / lib / libtls / tls_conninfo.c
blobe3820988e82b55e0ce7b99e43b857a50099dcc72
1 /* $OpenBSD: tls_conninfo.c,v 1.16 2017/08/27 01:39:26 beck 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 int ASN1_time_tm_clamp_notafter(struct tm *tm);
28 int
29 tls_hex_string(const unsigned char *in, size_t inlen, char **out,
30 size_t *outlen)
32 static const char hex[] = "0123456789abcdef";
33 size_t i, len;
34 char *p;
36 if (outlen != NULL)
37 *outlen = 0;
39 if (inlen >= SIZE_MAX)
40 return (-1);
41 if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL)
42 return (-1);
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];
50 p[len++] = 0;
52 if (outlen != NULL)
53 *outlen = len;
55 return (0);
58 static int
59 tls_get_peer_cert_hash(struct tls *ctx, char **hash)
61 *hash = NULL;
62 if (ctx->ssl_peer_cert == NULL)
63 return (0);
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;
70 return 0;
73 static int
74 tls_get_peer_cert_issuer(struct tls *ctx, char **issuer)
76 X509_NAME *name = NULL;
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);
89 static int
90 tls_get_peer_cert_subject(struct tls *ctx, char **subject)
92 X509_NAME *name = NULL;
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);
105 static int
106 tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore,
107 time_t *notafter)
109 struct tm before_tm, after_tm;
110 ASN1_TIME *before, *after;
112 if (ctx->ssl_peer_cert == NULL)
113 return (-1);
115 memset(&before_tm, 0, sizeof(before_tm));
116 memset(&after_tm, 0, sizeof(after_tm));
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;
133 return (0);
135 err:
136 return (-1);
139 static int
140 tls_get_peer_cert_info(struct tls *ctx)
142 if (ctx->ssl_peer_cert == NULL)
143 return (0);
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;
155 return (0);
157 err:
158 return (-1);
161 static int
162 tls_conninfo_alpn_proto(struct tls *ctx)
164 const unsigned char *p;
165 unsigned int len;
167 free(ctx->conninfo->alpn);
168 ctx->conninfo->alpn = NULL;
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';
178 return (0);
181 static int
182 tls_conninfo_cert_pem(struct tls *ctx)
184 int i, rv = -1;
185 BIO *membio = NULL;
186 BUF_MEM *bptr = NULL;
188 if (ctx->conninfo == NULL)
189 goto err;
190 if (ctx->ssl_peer_cert == NULL)
191 return 0;
192 if ((membio = BIO_new(BIO_s_mem()))== NULL)
193 goto err;
196 * We have to write the peer cert out separately, because
197 * the certificate chain may or may not contain it.
199 if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert))
200 goto err;
201 for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) {
202 X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i);
203 if (chaincert != ctx->ssl_peer_cert &&
204 !PEM_write_bio_X509(membio, chaincert))
205 goto err;
208 BIO_get_mem_ptr(membio, &bptr);
209 free(ctx->conninfo->peer_cert);
210 ctx->conninfo->peer_cert_len = 0;
211 if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL)
212 goto err;
213 ctx->conninfo->peer_cert_len = bptr->length;
214 memcpy(ctx->conninfo->peer_cert, bptr->data,
215 ctx->conninfo->peer_cert_len);
217 /* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */
218 rv = 0;
219 err:
220 BIO_free(membio);
221 return rv;
225 tls_conninfo_populate(struct tls *ctx)
227 const char *tmp;
229 tls_conninfo_free(ctx->conninfo);
231 if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) {
232 tls_set_errorx(ctx, "out of memory");
233 goto err;
236 if (tls_conninfo_alpn_proto(ctx) == -1)
237 goto err;
239 if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL)
240 goto err;
241 ctx->conninfo->cipher = strdup(tmp);
242 if (ctx->conninfo->cipher == NULL)
243 goto err;
245 if (ctx->servername != NULL) {
246 if ((ctx->conninfo->servername =
247 strdup(ctx->servername)) == NULL)
248 goto err;
251 if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL)
252 goto err;
253 ctx->conninfo->version = strdup(tmp);
254 if (ctx->conninfo->version == NULL)
255 goto err;
257 if (tls_get_peer_cert_info(ctx) == -1)
258 goto err;
260 if (tls_conninfo_cert_pem(ctx) == -1)
261 goto err;
263 return (0);
265 err:
266 tls_conninfo_free(ctx->conninfo);
267 ctx->conninfo = NULL;
269 return (-1);
272 void
273 tls_conninfo_free(struct tls_conninfo *conninfo)
275 if (conninfo == NULL)
276 return;
278 free(conninfo->alpn);
279 conninfo->alpn = NULL;
280 free(conninfo->cipher);
281 conninfo->cipher = NULL;
282 free(conninfo->servername);
283 conninfo->servername = NULL;
284 free(conninfo->version);
285 conninfo->version = NULL;
287 free(conninfo->hash);
288 conninfo->hash = NULL;
289 free(conninfo->issuer);
290 conninfo->issuer = NULL;
291 free(conninfo->subject);
292 conninfo->subject = NULL;
294 free(conninfo->peer_cert);
295 conninfo->peer_cert = NULL;
296 conninfo->peer_cert_len = 0;
298 free(conninfo);
301 const char *
302 tls_conn_alpn_selected(struct tls *ctx)
304 if (ctx->conninfo == NULL)
305 return (NULL);
306 return (ctx->conninfo->alpn);
309 const char *
310 tls_conn_cipher(struct tls *ctx)
312 if (ctx->conninfo == NULL)
313 return (NULL);
314 return (ctx->conninfo->cipher);
317 const char *
318 tls_conn_servername(struct tls *ctx)
320 if (ctx->conninfo == NULL)
321 return (NULL);
322 return (ctx->conninfo->servername);
325 const char *
326 tls_conn_version(struct tls *ctx)
328 if (ctx->conninfo == NULL)
329 return (NULL);
330 return (ctx->conninfo->version);