GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ldpd/pfkey.c Lines: 0 243 0.0 %
Date: 2017-11-07 Branches: 0 118 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: pfkey.c,v 1.11 2017/04/18 02:29:56 deraadt Exp $ */
2
3
/*
4
 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5
 * Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org>
6
 *
7
 * Permission to use, copy, modify, and distribute this software for any
8
 * purpose with or without fee is hereby granted, provided that the above
9
 * copyright notice and this permission notice appear in all copies.
10
 *
11
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
 */
19
20
#include <sys/types.h>
21
#include <errno.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <unistd.h>
25
26
#include "ldpd.h"
27
#include "ldpe.h"
28
#include "log.h"
29
30
static int	 pfkey_send(int, uint8_t, uint8_t, uint8_t,
31
		    int, union ldpd_addr *, union ldpd_addr *,
32
		    uint32_t, uint8_t, int, char *, uint8_t, int, char *,
33
		    uint16_t, uint16_t);
34
static int	 pfkey_reply(int, uint32_t *);
35
static int	 pfkey_sa_add(int, union ldpd_addr *, union ldpd_addr *,
36
		    uint8_t, char *, uint32_t *);
37
static int	 pfkey_sa_remove(int, union ldpd_addr *, union ldpd_addr *,
38
		    uint32_t *);
39
static int	 pfkey_md5sig_establish(struct nbr *, struct nbr_params *nbrp);
40
static int	 pfkey_md5sig_remove(struct nbr *);
41
42
#define	PFKEY2_CHUNK sizeof(uint64_t)
43
#define	ROUNDUP(x) (((x) + (PFKEY2_CHUNK - 1)) & ~(PFKEY2_CHUNK - 1))
44
#define	IOV_CNT	20
45
46
static uint32_t	 sadb_msg_seq;
47
static uint32_t	 pid; /* should pid_t but pfkey needs uint32_t */
48
static int	 fd;
49
50
static int
51
pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
52
    int af, union ldpd_addr *src, union ldpd_addr *dst, uint32_t spi,
53
    uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey,
54
    uint16_t sport, uint16_t dport)
55
{
56
	struct sadb_msg		smsg;
57
	struct sadb_sa		sa;
58
	struct sadb_address	sa_src, sa_dst;
59
	struct sadb_key		sa_akey, sa_ekey;
60
	struct sadb_spirange	sa_spirange;
61
	struct iovec		iov[IOV_CNT];
62
	ssize_t			n;
63
	int			len = 0;
64
	int			iov_cnt;
65
	struct sockaddr_storage	ssrc, sdst, smask, dmask;
66
	struct sockaddr		*saptr;
67
68
	if (!pid)
69
		pid = getpid();
70
71
	/* we need clean sockaddr... no ports set */
72
	memset(&ssrc, 0, sizeof(ssrc));
73
	memset(&smask, 0, sizeof(smask));
74
	if ((saptr = addr2sa(af, src, 0)))
75
		memcpy(&ssrc, saptr, sizeof(ssrc));
76
	switch (af) {
77
	case AF_INET:
78
		memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8);
79
		break;
80
	case AF_INET6:
81
		memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff,
82
		    128/8);
83
		break;
84
	default:
85
		return (-1);
86
	}
87
	smask.ss_family = ssrc.ss_family;
88
	smask.ss_len = ssrc.ss_len;
89
90
	memset(&sdst, 0, sizeof(sdst));
91
	memset(&dmask, 0, sizeof(dmask));
92
	if ((saptr = addr2sa(af, dst, 0)))
93
		memcpy(&sdst, saptr, sizeof(sdst));
94
	switch (af) {
95
	case AF_INET:
96
		memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8);
97
		break;
98
	case AF_INET6:
99
		memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff,
100
		    128/8);
101
		break;
102
	default:
103
		return (-1);
104
	}
105
	dmask.ss_family = sdst.ss_family;
106
	dmask.ss_len = sdst.ss_len;
107
108
	memset(&smsg, 0, sizeof(smsg));
109
	smsg.sadb_msg_version = PF_KEY_V2;
110
	smsg.sadb_msg_seq = ++sadb_msg_seq;
111
	smsg.sadb_msg_pid = pid;
112
	smsg.sadb_msg_len = sizeof(smsg) / 8;
113
	smsg.sadb_msg_type = mtype;
114
	smsg.sadb_msg_satype = satype;
115
116
	switch (mtype) {
117
	case SADB_GETSPI:
118
		memset(&sa_spirange, 0, sizeof(sa_spirange));
119
		sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
120
		sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8;
121
		sa_spirange.sadb_spirange_min = 0x100;
122
		sa_spirange.sadb_spirange_max = 0xffffffff;
123
		sa_spirange.sadb_spirange_reserved = 0;
124
		break;
125
	case SADB_ADD:
126
	case SADB_UPDATE:
127
	case SADB_DELETE:
128
		memset(&sa, 0, sizeof(sa));
129
		sa.sadb_sa_exttype = SADB_EXT_SA;
130
		sa.sadb_sa_len = sizeof(sa) / 8;
131
		sa.sadb_sa_replay = 0;
132
		sa.sadb_sa_spi = spi;
133
		sa.sadb_sa_state = SADB_SASTATE_MATURE;
134
		break;
135
	}
136
137
	memset(&sa_src, 0, sizeof(sa_src));
138
	sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
139
	sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8;
140
141
	memset(&sa_dst, 0, sizeof(sa_dst));
142
	sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
143
	sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8;
144
145
	sa.sadb_sa_auth = aalg;
146
	sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */
147
148
	switch (mtype) {
149
	case SADB_ADD:
150
	case SADB_UPDATE:
151
		memset(&sa_akey, 0, sizeof(sa_akey));
152
		sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH;
153
		sa_akey.sadb_key_len = (sizeof(sa_akey) +
154
		    ((alen + 7) / 8) * 8) / 8;
155
		sa_akey.sadb_key_bits = 8 * alen;
156
157
		memset(&sa_ekey, 0, sizeof(sa_ekey));
158
		sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
159
		sa_ekey.sadb_key_len = (sizeof(sa_ekey) +
160
		    ((elen + 7) / 8) * 8) / 8;
161
		sa_ekey.sadb_key_bits = 8 * elen;
162
163
		break;
164
	}
165
166
	iov_cnt = 0;
167
168
	/* msghdr */
169
	iov[iov_cnt].iov_base = &smsg;
170
	iov[iov_cnt].iov_len = sizeof(smsg);
171
	iov_cnt++;
172
173
	switch (mtype) {
174
	case SADB_ADD:
175
	case SADB_UPDATE:
176
	case SADB_DELETE:
177
		/* SA hdr */
178
		iov[iov_cnt].iov_base = &sa;
179
		iov[iov_cnt].iov_len = sizeof(sa);
180
		smsg.sadb_msg_len += sa.sadb_sa_len;
181
		iov_cnt++;
182
		break;
183
	case SADB_GETSPI:
184
		/* SPI range */
185
		iov[iov_cnt].iov_base = &sa_spirange;
186
		iov[iov_cnt].iov_len = sizeof(sa_spirange);
187
		smsg.sadb_msg_len += sa_spirange.sadb_spirange_len;
188
		iov_cnt++;
189
		break;
190
	}
191
192
	/* dest addr */
193
	iov[iov_cnt].iov_base = &sa_dst;
194
	iov[iov_cnt].iov_len = sizeof(sa_dst);
195
	iov_cnt++;
196
	iov[iov_cnt].iov_base = &sdst;
197
	iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len);
198
	smsg.sadb_msg_len += sa_dst.sadb_address_len;
199
	iov_cnt++;
200
201
	/* src addr */
202
	iov[iov_cnt].iov_base = &sa_src;
203
	iov[iov_cnt].iov_len = sizeof(sa_src);
204
	iov_cnt++;
205
	iov[iov_cnt].iov_base = &ssrc;
206
	iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len);
207
	smsg.sadb_msg_len += sa_src.sadb_address_len;
208
	iov_cnt++;
209
210
	switch (mtype) {
211
	case SADB_ADD:
212
	case SADB_UPDATE:
213
		if (alen) {
214
			/* auth key */
215
			iov[iov_cnt].iov_base = &sa_akey;
216
			iov[iov_cnt].iov_len = sizeof(sa_akey);
217
			iov_cnt++;
218
			iov[iov_cnt].iov_base = akey;
219
			iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8;
220
			smsg.sadb_msg_len += sa_akey.sadb_key_len;
221
			iov_cnt++;
222
		}
223
		if (elen) {
224
			/* encryption key */
225
			iov[iov_cnt].iov_base = &sa_ekey;
226
			iov[iov_cnt].iov_len = sizeof(sa_ekey);
227
			iov_cnt++;
228
			iov[iov_cnt].iov_base = ekey;
229
			iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8;
230
			smsg.sadb_msg_len += sa_ekey.sadb_key_len;
231
			iov_cnt++;
232
		}
233
		break;
234
	}
235
236
	len = smsg.sadb_msg_len * 8;
237
	do {
238
		n = writev(sd, iov, iov_cnt);
239
	} while (n == -1 && (errno == EAGAIN || errno == EINTR));
240
241
	if (n == -1) {
242
		log_warn("writev (%d/%d)", iov_cnt, len);
243
		return (-1);
244
	}
245
246
	return (0);
247
}
248
249
int
250
pfkey_read(int sd, struct sadb_msg *h)
251
{
252
	struct sadb_msg hdr;
253
254
	if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
255
		if (errno == EAGAIN || errno == EINTR)
256
			return (0);
257
		log_warn("pfkey peek");
258
		return (-1);
259
	}
260
261
	/* XXX: Only one message can be outstanding. */
262
	if (hdr.sadb_msg_seq == sadb_msg_seq &&
263
	    hdr.sadb_msg_pid == pid) {
264
		if (h)
265
			*h = hdr;
266
		return (0);
267
	}
268
269
	/* not ours, discard */
270
	if (read(sd, &hdr, sizeof(hdr)) == -1) {
271
		if (errno == EAGAIN || errno == EINTR)
272
			return (0);
273
		log_warn("pfkey read");
274
		return (-1);
275
	}
276
277
	return (1);
278
}
279
280
static int
281
pfkey_reply(int sd, uint32_t *spip)
282
{
283
	struct sadb_msg hdr, *msg;
284
	struct sadb_ext *ext;
285
	struct sadb_sa *sa;
286
	uint8_t *data;
287
	ssize_t len;
288
	int rv;
289
290
	do {
291
		rv = pfkey_read(sd, &hdr);
292
		if (rv == -1)
293
			return (-1);
294
	} while (rv);
295
296
	if (hdr.sadb_msg_errno != 0) {
297
		errno = hdr.sadb_msg_errno;
298
		if (errno == ESRCH)
299
			return (0);
300
		else {
301
			log_warn("pfkey");
302
			return (-1);
303
		}
304
	}
305
	if ((data = reallocarray(NULL, hdr.sadb_msg_len, PFKEY2_CHUNK)) == NULL) {
306
		log_warn("pfkey malloc");
307
		return (-1);
308
	}
309
	len = hdr.sadb_msg_len * PFKEY2_CHUNK;
310
	if (read(sd, data, len) != len) {
311
		log_warn("pfkey read");
312
		freezero(data, len);
313
		return (-1);
314
	}
315
316
	if (hdr.sadb_msg_type == SADB_GETSPI) {
317
		if (spip == NULL) {
318
			freezero(data, len);
319
			return (0);
320
		}
321
322
		msg = (struct sadb_msg *)data;
323
		for (ext = (struct sadb_ext *)(msg + 1);
324
		    (size_t)((uint8_t *)ext - (uint8_t *)msg) <
325
		    msg->sadb_msg_len * PFKEY2_CHUNK;
326
		    ext = (struct sadb_ext *)((uint8_t *)ext +
327
		    ext->sadb_ext_len * PFKEY2_CHUNK)) {
328
			if (ext->sadb_ext_type == SADB_EXT_SA) {
329
				sa = (struct sadb_sa *) ext;
330
				*spip = sa->sadb_sa_spi;
331
				break;
332
			}
333
		}
334
	}
335
	freezero(data, len);
336
	return (0);
337
}
338
339
static int
340
pfkey_sa_add(int af, union ldpd_addr *src, union ldpd_addr *dst, uint8_t keylen,
341
    char *key, uint32_t *spi)
342
{
343
	if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0,
344
	    af, src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0)
345
		return (-1);
346
	if (pfkey_reply(fd, spi) < 0)
347
		return (-1);
348
	if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0,
349
	    af, src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) < 0)
350
		return (-1);
351
	if (pfkey_reply(fd, NULL) < 0)
352
		return (-1);
353
	return (0);
354
}
355
356
static int
357
pfkey_sa_remove(int af, union ldpd_addr *src, union ldpd_addr *dst,
358
    uint32_t *spi)
359
{
360
	if (pfkey_send(fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0,
361
	    af, src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) < 0)
362
		return (-1);
363
	if (pfkey_reply(fd, NULL) < 0)
364
		return (-1);
365
	*spi = 0;
366
	return (0);
367
}
368
369
static int
370
pfkey_md5sig_establish(struct nbr *nbr, struct nbr_params *nbrp)
371
{
372
	sleep(1);
373
374
	if (!nbr->auth.spi_out)
375
		if (pfkey_sa_add(nbr->af, &nbr->laddr, &nbr->raddr,
376
		    nbrp->auth.md5key_len, nbrp->auth.md5key,
377
		    &nbr->auth.spi_out) == -1)
378
			return (-1);
379
	if (!nbr->auth.spi_in)
380
		if (pfkey_sa_add(nbr->af, &nbr->raddr, &nbr->laddr,
381
		    nbrp->auth.md5key_len, nbrp->auth.md5key,
382
		    &nbr->auth.spi_in) == -1)
383
			return (-1);
384
385
	nbr->auth.established = 1;
386
	return (0);
387
}
388
389
static int
390
pfkey_md5sig_remove(struct nbr *nbr)
391
{
392
	if (nbr->auth.spi_out)
393
		if (pfkey_sa_remove(nbr->af, &nbr->laddr, &nbr->raddr,
394
		    &nbr->auth.spi_out) == -1)
395
			return (-1);
396
	if (nbr->auth.spi_in)
397
		if (pfkey_sa_remove(nbr->af, &nbr->raddr, &nbr->laddr,
398
		    &nbr->auth.spi_in) == -1)
399
			return (-1);
400
401
	nbr->auth.established = 0;
402
	nbr->auth.spi_in = 0;
403
	nbr->auth.spi_out = 0;
404
	nbr->auth.method = AUTH_NONE;
405
	memset(nbr->auth.md5key, 0, sizeof(nbr->auth.md5key));
406
407
	return (0);
408
}
409
410
int
411
pfkey_establish(struct nbr *nbr, struct nbr_params *nbrp)
412
{
413
	if (nbrp->auth.method == AUTH_NONE)
414
		return (0);
415
416
	/*
417
	 * make sure we keep copies of everything we need to
418
	 * remove SAs and flows later again.
419
	 */
420
	nbr->auth.method = nbrp->auth.method;
421
422
	switch (nbr->auth.method) {
423
	case AUTH_MD5SIG:
424
		strlcpy(nbr->auth.md5key, nbrp->auth.md5key,
425
		    sizeof(nbr->auth.md5key));
426
		return (pfkey_md5sig_establish(nbr, nbrp));
427
	default:
428
		break;
429
	}
430
431
	return (0);
432
}
433
434
int
435
pfkey_remove(struct nbr *nbr)
436
{
437
	if (nbr->auth.method == AUTH_NONE || !nbr->auth.established)
438
		return (0);
439
440
	switch (nbr->auth.method) {
441
	case AUTH_MD5SIG:
442
		return (pfkey_md5sig_remove(nbr));
443
	default:
444
		break;
445
	}
446
447
	return (0);
448
}
449
450
int
451
pfkey_init(void)
452
{
453
	if ((fd = socket(PF_KEY, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
454
	    PF_KEY_V2)) == -1) {
455
		if (errno == EPROTONOSUPPORT) {
456
			log_warnx("PF_KEY not available");
457
			sysdep.no_pfkey = 1;
458
			return (-1);
459
		} else
460
			fatal("pfkey setup failed");
461
	}
462
	return (fd);
463
}