GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libtls/tls_conninfo.c Lines: 116 156 74.4 %
Date: 2017-11-07 Branches: 53 105 50.5 %

Line Branch Exec Source
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>
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 ASN1_time_tm_clamp_notafter(struct tm *tm);
27
28
int
29
tls_hex_string(const unsigned char *in, size_t inlen, char **out,
30
    size_t *outlen)
31
{
32
	static const char hex[] = "0123456789abcdef";
33
	size_t i, len;
34
	char *p;
35
36
64
	if (outlen != NULL)
37
		*outlen = 0;
38
39
32
	if (inlen >= SIZE_MAX)
40
		return (-1);
41
32
	if ((*out = reallocarray(NULL, inlen + 1, 2)) == NULL)
42
		return (-1);
43
44
	p = *out;
45
	len = 0;
46
2112
	for (i = 0; i < inlen; i++) {
47
1024
		p[len++] = hex[(in[i] >> 4) & 0x0f];
48
1024
		p[len++] = hex[in[i] & 0x0f];
49
	}
50
32
	p[len++] = 0;
51
52
32
	if (outlen != NULL)
53
		*outlen = len;
54
55
32
	return (0);
56
32
}
57
58
static int
59
tls_get_peer_cert_hash(struct tls *ctx, char **hash)
60
{
61
32
	*hash = NULL;
62
16
	if (ctx->ssl_peer_cert == NULL)
63
		return (0);
64
65
16
	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;
69
	}
70
16
	return 0;
71
16
}
72
73
static int
74
tls_get_peer_cert_issuer(struct tls *ctx,  char **issuer)
75
{
76
	X509_NAME *name = NULL;
77
78
32
	*issuer = NULL;
79
16
	if (ctx->ssl_peer_cert == NULL)
80
		return (-1);
81
16
	if ((name = X509_get_issuer_name(ctx->ssl_peer_cert)) == NULL)
82
		return (-1);
83
16
	*issuer = X509_NAME_oneline(name, 0, 0);
84
16
	if (*issuer == NULL)
85
		return (-1);
86
16
	return (0);
87
16
}
88
89
static int
90
tls_get_peer_cert_subject(struct tls *ctx, char **subject)
91
{
92
	X509_NAME *name = NULL;
93
94
32
	*subject = NULL;
95
16
	if (ctx->ssl_peer_cert == NULL)
96
		return (-1);
97
16
	if ((name = X509_get_subject_name(ctx->ssl_peer_cert)) == NULL)
98
		return (-1);
99
16
	*subject = X509_NAME_oneline(name, 0, 0);
100
16
	if (*subject == NULL)
101
		return (-1);
102
16
	return (0);
103
16
}
104
105
static int
106
tls_get_peer_cert_times(struct tls *ctx, time_t *notbefore,
107
    time_t *notafter)
108
{
109
32
	struct tm before_tm, after_tm;
110
	ASN1_TIME *before, *after;
111
112
16
	if (ctx->ssl_peer_cert == NULL)
113
		return (-1);
114
115
16
	memset(&before_tm, 0, sizeof(before_tm));
116
16
	memset(&after_tm, 0, sizeof(after_tm));
117
118
16
	if ((before = X509_get_notBefore(ctx->ssl_peer_cert)) == NULL)
119
		goto err;
120
16
	if ((after = X509_get_notAfter(ctx->ssl_peer_cert)) == NULL)
121
		goto err;
122
16
	if (ASN1_time_parse(before->data, before->length, &before_tm, 0) == -1)
123
		goto err;
124
16
	if (ASN1_time_parse(after->data, after->length, &after_tm, 0) == -1)
125
		goto err;
126
16
	if (!ASN1_time_tm_clamp_notafter(&after_tm))
127
		goto err;
128
16
	if ((*notbefore = timegm(&before_tm)) == -1)
129
		goto err;
130
16
	if ((*notafter = timegm(&after_tm)) == -1)
131
		goto err;
132
133
16
	return (0);
134
135
 err:
136
	return (-1);
137
16
}
138
139
static int
140
tls_get_peer_cert_info(struct tls *ctx)
141
{
142
64
	if (ctx->ssl_peer_cert == NULL)
143
16
		return (0);
144
145
16
	if (tls_get_peer_cert_hash(ctx, &ctx->conninfo->hash) == -1)
146
		goto err;
147
16
	if (tls_get_peer_cert_subject(ctx, &ctx->conninfo->subject) == -1)
148
		goto err;
149
16
	if (tls_get_peer_cert_issuer(ctx, &ctx->conninfo->issuer) == -1)
150
		goto err;
151
48
	if (tls_get_peer_cert_times(ctx, &ctx->conninfo->notbefore,
152
32
	    &ctx->conninfo->notafter) == -1)
153
		goto err;
154
155
16
	return (0);
156
157
 err:
158
	return (-1);
159
32
}
160
161
static int
162
tls_conninfo_alpn_proto(struct tls *ctx)
163
{
164
64
	const unsigned char *p;
165
32
	unsigned int len;
166
167
32
	free(ctx->conninfo->alpn);
168
32
	ctx->conninfo->alpn = NULL;
169
170
32
	SSL_get0_alpn_selected(ctx->ssl_conn, &p, &len);
171
32
	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';
176
	}
177
178
32
	return (0);
179
32
}
180
181
static int
182
tls_conninfo_cert_pem(struct tls *ctx)
183
{
184
	int i, rv = -1;
185
	BIO *membio = NULL;
186
64
	BUF_MEM *bptr = NULL;
187
188
32
	if (ctx->conninfo == NULL)
189
		goto err;
190
32
	if (ctx->ssl_peer_cert == NULL)
191
16
		return 0;
192
16
	if ((membio = BIO_new(BIO_s_mem()))== NULL)
193
		goto err;
194
195
	/*
196
	 * We have to write the peer cert out separately, because
197
	 * the certificate chain may or may not contain it.
198
	 */
199
16
	if (!PEM_write_bio_X509(membio, ctx->ssl_peer_cert))
200
		goto err;
201
64
	for (i = 0; i < sk_X509_num(ctx->ssl_peer_chain); i++) {
202
16
		X509 *chaincert = sk_X509_value(ctx->ssl_peer_chain, i);
203

16
		if (chaincert != ctx->ssl_peer_cert &&
204
		    !PEM_write_bio_X509(membio, chaincert))
205
			goto err;
206
16
	}
207
208
16
	BIO_get_mem_ptr(membio, &bptr);
209
16
	free(ctx->conninfo->peer_cert);
210
16
	ctx->conninfo->peer_cert_len = 0;
211
16
	if ((ctx->conninfo->peer_cert = malloc(bptr->length)) == NULL)
212
		goto err;
213
16
	ctx->conninfo->peer_cert_len = bptr->length;
214
32
	memcpy(ctx->conninfo->peer_cert, bptr->data,
215
16
	    ctx->conninfo->peer_cert_len);
216
217
	/* BIO_free() will kill BUF_MEM - because we have not set BIO_NOCLOSE */
218
16
	rv = 0;
219
 err:
220
16
	BIO_free(membio);
221
16
	return rv;
222
32
}
223
224
int
225
tls_conninfo_populate(struct tls *ctx)
226
{
227
	const char *tmp;
228
229
64
	tls_conninfo_free(ctx->conninfo);
230
231
32
	if ((ctx->conninfo = calloc(1, sizeof(struct tls_conninfo))) == NULL) {
232
		tls_set_errorx(ctx, "out of memory");
233
		goto err;
234
	}
235
236
32
	if (tls_conninfo_alpn_proto(ctx) == -1)
237
		goto err;
238
239
32
	if ((tmp = SSL_get_cipher(ctx->ssl_conn)) == NULL)
240
		goto err;
241
32
	ctx->conninfo->cipher = strdup(tmp);
242
32
	if (ctx->conninfo->cipher == NULL)
243
		goto err;
244
245
32
	if (ctx->servername != NULL) {
246
64
		if ((ctx->conninfo->servername =
247
64
		    strdup(ctx->servername)) == NULL)
248
			goto err;
249
	}
250
251
32
	if ((tmp = SSL_get_version(ctx->ssl_conn)) == NULL)
252
		goto err;
253
32
	ctx->conninfo->version = strdup(tmp);
254
32
	if (ctx->conninfo->version == NULL)
255
		goto err;
256
257
32
	if (tls_get_peer_cert_info(ctx) == -1)
258
		goto err;
259
260
32
	if (tls_conninfo_cert_pem(ctx) == -1)
261
		goto err;
262
263
32
	return (0);
264
265
 err:
266
	tls_conninfo_free(ctx->conninfo);
267
	ctx->conninfo = NULL;
268
269
	return (-1);
270
32
}
271
272
void
273
tls_conninfo_free(struct tls_conninfo *conninfo)
274
{
275
688
	if (conninfo == NULL)
276
		return;
277
278
32
	free(conninfo->alpn);
279
32
	conninfo->alpn = NULL;
280
32
	free(conninfo->cipher);
281
32
	conninfo->cipher = NULL;
282
32
	free(conninfo->servername);
283
32
	conninfo->servername = NULL;
284
32
	free(conninfo->version);
285
32
	conninfo->version = NULL;
286
287
32
	free(conninfo->hash);
288
32
	conninfo->hash = NULL;
289
32
	free(conninfo->issuer);
290
32
	conninfo->issuer = NULL;
291
32
	free(conninfo->subject);
292
32
	conninfo->subject = NULL;
293
294
32
	free(conninfo->peer_cert);
295
32
	conninfo->peer_cert = NULL;
296
32
	conninfo->peer_cert_len = 0;
297
298
32
	free(conninfo);
299
376
}
300
301
const char *
302
tls_conn_alpn_selected(struct tls *ctx)
303
{
304
	if (ctx->conninfo == NULL)
305
		return (NULL);
306
	return (ctx->conninfo->alpn);
307
}
308
309
const char *
310
tls_conn_cipher(struct tls *ctx)
311
{
312
	if (ctx->conninfo == NULL)
313
		return (NULL);
314
	return (ctx->conninfo->cipher);
315
}
316
317
const char *
318
tls_conn_servername(struct tls *ctx)
319
{
320
	if (ctx->conninfo == NULL)
321
		return (NULL);
322
	return (ctx->conninfo->servername);
323
}
324
325
const char *
326
tls_conn_version(struct tls *ctx)
327
{
328
	if (ctx->conninfo == NULL)
329
		return (NULL);
330
	return (ctx->conninfo->version);
331
}
332