xref: /openbsd/lib/libtls/tls_conninfo.c (revision 6f40fd34)
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