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