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