xref: /openbsd-src/usr.sbin/bgpd/pfkey.c (revision 25c4e8bd056e974b28f4a0ffd39d76c190a56013)
1 /*	$OpenBSD: pfkey.c,v 1.65 2022/06/16 09:51:07 claudio 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 <sys/socket.h>
22 #include <sys/uio.h>
23 #include <net/pfkeyv2.h>
24 #include <netinet/ip_ipsp.h>
25 #include <netinet/in.h>
26 #include <netinet/tcp.h>
27 #include <ctype.h>
28 #include <errno.h>
29 #include <limits.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 
34 #include "bgpd.h"
35 #include "session.h"
36 #include "log.h"
37 
38 extern struct bgpd_sysdep sysdep;
39 
40 #define	PFKEY2_CHUNK sizeof(uint64_t)
41 #define	ROUNDUP(x) (((x) + (PFKEY2_CHUNK - 1)) & ~(PFKEY2_CHUNK - 1))
42 #define	IOV_CNT	20
43 
44 static uint32_t	sadb_msg_seq = 0;
45 static uint32_t	pid = 0; /* should pid_t but pfkey needs uint32_t */
46 static int		pfkey_fd;
47 
48 int	pfkey_reply(int, uint32_t *);
49 int	pfkey_send(int, uint8_t, uint8_t, uint8_t,
50 	    struct bgpd_addr *, struct bgpd_addr *,
51 	    uint32_t, uint8_t, int, char *, uint8_t, int, char *,
52 	    uint16_t, uint16_t);
53 
54 #define pfkey_flow(fd, satype, cmd, dir, from, to, sport, dport) \
55 	pfkey_send(fd, satype, cmd, dir, from, to, \
56 	    0, 0, 0, NULL, 0, 0, NULL, sport, dport)
57 
58 static struct bgpd_addr *
59 pfkey_localaddr(struct peer *p)
60 {
61 	switch (p->conf.remote_addr.aid) {
62 	case AID_INET:
63 		return &p->conf.local_addr_v4;
64 	case AID_INET6:
65 		return &p->conf.local_addr_v6;
66 	}
67 	fatalx("Unknown AID in pfkey_localaddr");
68 }
69 
70 int
71 pfkey_send(int sd, uint8_t satype, uint8_t mtype, uint8_t dir,
72     struct bgpd_addr *src, struct bgpd_addr *dst, uint32_t spi,
73     uint8_t aalg, int alen, char *akey, uint8_t ealg, int elen, char *ekey,
74     uint16_t sport, uint16_t dport)
75 {
76 	struct sadb_msg		smsg;
77 	struct sadb_sa		sa;
78 	struct sadb_address	sa_src, sa_dst, sa_peer, sa_smask, sa_dmask;
79 	struct sadb_key		sa_akey, sa_ekey;
80 	struct sadb_spirange	sa_spirange;
81 	struct sadb_protocol	sa_flowtype, sa_protocol;
82 	struct iovec		iov[IOV_CNT];
83 	ssize_t			n;
84 	int			len = 0;
85 	int			iov_cnt;
86 	struct sockaddr_storage	ssrc, sdst, speer, smask, dmask;
87 	struct sockaddr		*saptr;
88 	socklen_t		 salen;
89 
90 	if (!pid)
91 		pid = getpid();
92 
93 	/* we need clean sockaddr... no ports set */
94 	bzero(&ssrc, sizeof(ssrc));
95 	bzero(&smask, sizeof(smask));
96 	if ((saptr = addr2sa(src, 0, &salen))) {
97 		memcpy(&ssrc, saptr, salen);
98 		ssrc.ss_len = salen;
99 	}
100 	switch (src->aid) {
101 	case AID_INET:
102 		memset(&((struct sockaddr_in *)&smask)->sin_addr, 0xff, 32/8);
103 		break;
104 	case AID_INET6:
105 		memset(&((struct sockaddr_in6 *)&smask)->sin6_addr, 0xff,
106 		    128/8);
107 		break;
108 	case AID_UNSPEC:
109 		ssrc.ss_len = sizeof(struct sockaddr);
110 		break;
111 	default:
112 		return (-1);
113 	}
114 	smask.ss_family = ssrc.ss_family;
115 	smask.ss_len = ssrc.ss_len;
116 
117 	bzero(&sdst, sizeof(sdst));
118 	bzero(&dmask, sizeof(dmask));
119 	if ((saptr = addr2sa(dst, 0, &salen))) {
120 		memcpy(&sdst, saptr, salen);
121 		sdst.ss_len = salen;
122 	}
123 	switch (dst->aid) {
124 	case AID_INET:
125 		memset(&((struct sockaddr_in *)&dmask)->sin_addr, 0xff, 32/8);
126 		break;
127 	case AID_INET6:
128 		memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr, 0xff,
129 		    128/8);
130 		break;
131 	case AID_UNSPEC:
132 		sdst.ss_len = sizeof(struct sockaddr);
133 		break;
134 	default:
135 		return (-1);
136 	}
137 	dmask.ss_family = sdst.ss_family;
138 	dmask.ss_len = sdst.ss_len;
139 
140 	bzero(&smsg, sizeof(smsg));
141 	smsg.sadb_msg_version = PF_KEY_V2;
142 	smsg.sadb_msg_seq = ++sadb_msg_seq;
143 	smsg.sadb_msg_pid = pid;
144 	smsg.sadb_msg_len = sizeof(smsg) / 8;
145 	smsg.sadb_msg_type = mtype;
146 	smsg.sadb_msg_satype = satype;
147 
148 	switch (mtype) {
149 	case SADB_GETSPI:
150 		bzero(&sa_spirange, sizeof(sa_spirange));
151 		sa_spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
152 		sa_spirange.sadb_spirange_len = sizeof(sa_spirange) / 8;
153 		sa_spirange.sadb_spirange_min = 0x100;
154 		sa_spirange.sadb_spirange_max = 0xffffffff;
155 		sa_spirange.sadb_spirange_reserved = 0;
156 		break;
157 	case SADB_ADD:
158 	case SADB_UPDATE:
159 	case SADB_DELETE:
160 		bzero(&sa, sizeof(sa));
161 		sa.sadb_sa_exttype = SADB_EXT_SA;
162 		sa.sadb_sa_len = sizeof(sa) / 8;
163 		sa.sadb_sa_replay = 0;
164 		sa.sadb_sa_spi = htonl(spi);
165 		sa.sadb_sa_state = SADB_SASTATE_MATURE;
166 		break;
167 	case SADB_X_ADDFLOW:
168 	case SADB_X_DELFLOW:
169 		bzero(&sa_flowtype, sizeof(sa_flowtype));
170 		sa_flowtype.sadb_protocol_exttype = SADB_X_EXT_FLOW_TYPE;
171 		sa_flowtype.sadb_protocol_len = sizeof(sa_flowtype) / 8;
172 		sa_flowtype.sadb_protocol_direction = dir;
173 		sa_flowtype.sadb_protocol_proto = SADB_X_FLOW_TYPE_REQUIRE;
174 
175 		bzero(&sa_protocol, sizeof(sa_protocol));
176 		sa_protocol.sadb_protocol_exttype = SADB_X_EXT_PROTOCOL;
177 		sa_protocol.sadb_protocol_len = sizeof(sa_protocol) / 8;
178 		sa_protocol.sadb_protocol_direction = 0;
179 		sa_protocol.sadb_protocol_proto = 6;
180 		break;
181 	}
182 
183 	bzero(&sa_src, sizeof(sa_src));
184 	sa_src.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
185 	sa_src.sadb_address_len = (sizeof(sa_src) + ROUNDUP(ssrc.ss_len)) / 8;
186 
187 	bzero(&sa_dst, sizeof(sa_dst));
188 	sa_dst.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
189 	sa_dst.sadb_address_len = (sizeof(sa_dst) + ROUNDUP(sdst.ss_len)) / 8;
190 
191 	sa.sadb_sa_auth = aalg;
192 	sa.sadb_sa_encrypt = SADB_X_EALG_AES; /* XXX */
193 
194 	switch (mtype) {
195 	case SADB_ADD:
196 	case SADB_UPDATE:
197 		bzero(&sa_akey, sizeof(sa_akey));
198 		sa_akey.sadb_key_exttype = SADB_EXT_KEY_AUTH;
199 		sa_akey.sadb_key_len = (sizeof(sa_akey) +
200 		    ((alen + 7) / 8) * 8) / 8;
201 		sa_akey.sadb_key_bits = 8 * alen;
202 
203 		bzero(&sa_ekey, sizeof(sa_ekey));
204 		sa_ekey.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
205 		sa_ekey.sadb_key_len = (sizeof(sa_ekey) +
206 		    ((elen + 7) / 8) * 8) / 8;
207 		sa_ekey.sadb_key_bits = 8 * elen;
208 
209 		break;
210 	case SADB_X_ADDFLOW:
211 	case SADB_X_DELFLOW:
212 		/* sa_peer always points to the remote machine */
213 		if (dir == IPSP_DIRECTION_IN) {
214 			speer = ssrc;
215 			sa_peer = sa_src;
216 		} else {
217 			speer = sdst;
218 			sa_peer = sa_dst;
219 		}
220 		sa_peer.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
221 		sa_peer.sadb_address_len =
222 		    (sizeof(sa_peer) + ROUNDUP(speer.ss_len)) / 8;
223 
224 		/* for addflow we also use src/dst as the flow destination */
225 		sa_src.sadb_address_exttype = SADB_X_EXT_SRC_FLOW;
226 		sa_dst.sadb_address_exttype = SADB_X_EXT_DST_FLOW;
227 
228 		bzero(&smask, sizeof(smask));
229 		switch (src->aid) {
230 		case AID_INET:
231 			smask.ss_len = sizeof(struct sockaddr_in);
232 			smask.ss_family = AF_INET;
233 			memset(&((struct sockaddr_in *)&smask)->sin_addr,
234 			    0xff, 32/8);
235 			if (sport) {
236 				((struct sockaddr_in *)&ssrc)->sin_port =
237 				    htons(sport);
238 				((struct sockaddr_in *)&smask)->sin_port =
239 				    htons(0xffff);
240 			}
241 			break;
242 		case AID_INET6:
243 			smask.ss_len = sizeof(struct sockaddr_in6);
244 			smask.ss_family = AF_INET6;
245 			memset(&((struct sockaddr_in6 *)&smask)->sin6_addr,
246 			    0xff, 128/8);
247 			if (sport) {
248 				((struct sockaddr_in6 *)&ssrc)->sin6_port =
249 				    htons(sport);
250 				((struct sockaddr_in6 *)&smask)->sin6_port =
251 				    htons(0xffff);
252 			}
253 			break;
254 		}
255 		bzero(&dmask, sizeof(dmask));
256 		switch (dst->aid) {
257 		case AID_INET:
258 			dmask.ss_len = sizeof(struct sockaddr_in);
259 			dmask.ss_family = AF_INET;
260 			memset(&((struct sockaddr_in *)&dmask)->sin_addr,
261 			    0xff, 32/8);
262 			if (dport) {
263 				((struct sockaddr_in *)&sdst)->sin_port =
264 				    htons(dport);
265 				((struct sockaddr_in *)&dmask)->sin_port =
266 				    htons(0xffff);
267 			}
268 			break;
269 		case AID_INET6:
270 			dmask.ss_len = sizeof(struct sockaddr_in6);
271 			dmask.ss_family = AF_INET6;
272 			memset(&((struct sockaddr_in6 *)&dmask)->sin6_addr,
273 			    0xff, 128/8);
274 			if (dport) {
275 				((struct sockaddr_in6 *)&sdst)->sin6_port =
276 				    htons(dport);
277 				((struct sockaddr_in6 *)&dmask)->sin6_port =
278 				    htons(0xffff);
279 			}
280 			break;
281 		}
282 
283 		bzero(&sa_smask, sizeof(sa_smask));
284 		sa_smask.sadb_address_exttype = SADB_X_EXT_SRC_MASK;
285 		sa_smask.sadb_address_len =
286 		    (sizeof(sa_smask) + ROUNDUP(smask.ss_len)) / 8;
287 
288 		bzero(&sa_dmask, sizeof(sa_dmask));
289 		sa_dmask.sadb_address_exttype = SADB_X_EXT_DST_MASK;
290 		sa_dmask.sadb_address_len =
291 		    (sizeof(sa_dmask) + ROUNDUP(dmask.ss_len)) / 8;
292 		break;
293 	}
294 
295 	iov_cnt = 0;
296 
297 	/* msghdr */
298 	iov[iov_cnt].iov_base = &smsg;
299 	iov[iov_cnt].iov_len = sizeof(smsg);
300 	iov_cnt++;
301 
302 	switch (mtype) {
303 	case SADB_ADD:
304 	case SADB_UPDATE:
305 	case SADB_DELETE:
306 		/* SA hdr */
307 		iov[iov_cnt].iov_base = &sa;
308 		iov[iov_cnt].iov_len = sizeof(sa);
309 		smsg.sadb_msg_len += sa.sadb_sa_len;
310 		iov_cnt++;
311 		break;
312 	case SADB_GETSPI:
313 		/* SPI range */
314 		iov[iov_cnt].iov_base = &sa_spirange;
315 		iov[iov_cnt].iov_len = sizeof(sa_spirange);
316 		smsg.sadb_msg_len += sa_spirange.sadb_spirange_len;
317 		iov_cnt++;
318 		break;
319 	case SADB_X_ADDFLOW:
320 		/* sa_peer always points to the remote machine */
321 		iov[iov_cnt].iov_base = &sa_peer;
322 		iov[iov_cnt].iov_len = sizeof(sa_peer);
323 		iov_cnt++;
324 		iov[iov_cnt].iov_base = &speer;
325 		iov[iov_cnt].iov_len = ROUNDUP(speer.ss_len);
326 		smsg.sadb_msg_len += sa_peer.sadb_address_len;
327 		iov_cnt++;
328 
329 		/* FALLTHROUGH */
330 	case SADB_X_DELFLOW:
331 		/* add flow type */
332 		iov[iov_cnt].iov_base = &sa_flowtype;
333 		iov[iov_cnt].iov_len = sizeof(sa_flowtype);
334 		smsg.sadb_msg_len += sa_flowtype.sadb_protocol_len;
335 		iov_cnt++;
336 
337 		/* add protocol */
338 		iov[iov_cnt].iov_base = &sa_protocol;
339 		iov[iov_cnt].iov_len = sizeof(sa_protocol);
340 		smsg.sadb_msg_len += sa_protocol.sadb_protocol_len;
341 		iov_cnt++;
342 
343 		/* add flow masks */
344 		iov[iov_cnt].iov_base = &sa_smask;
345 		iov[iov_cnt].iov_len = sizeof(sa_smask);
346 		iov_cnt++;
347 		iov[iov_cnt].iov_base = &smask;
348 		iov[iov_cnt].iov_len = ROUNDUP(smask.ss_len);
349 		smsg.sadb_msg_len += sa_smask.sadb_address_len;
350 		iov_cnt++;
351 
352 		iov[iov_cnt].iov_base = &sa_dmask;
353 		iov[iov_cnt].iov_len = sizeof(sa_dmask);
354 		iov_cnt++;
355 		iov[iov_cnt].iov_base = &dmask;
356 		iov[iov_cnt].iov_len = ROUNDUP(dmask.ss_len);
357 		smsg.sadb_msg_len += sa_dmask.sadb_address_len;
358 		iov_cnt++;
359 		break;
360 	}
361 
362 	/* dest addr */
363 	iov[iov_cnt].iov_base = &sa_dst;
364 	iov[iov_cnt].iov_len = sizeof(sa_dst);
365 	iov_cnt++;
366 	iov[iov_cnt].iov_base = &sdst;
367 	iov[iov_cnt].iov_len = ROUNDUP(sdst.ss_len);
368 	smsg.sadb_msg_len += sa_dst.sadb_address_len;
369 	iov_cnt++;
370 
371 	/* src addr */
372 	iov[iov_cnt].iov_base = &sa_src;
373 	iov[iov_cnt].iov_len = sizeof(sa_src);
374 	iov_cnt++;
375 	iov[iov_cnt].iov_base = &ssrc;
376 	iov[iov_cnt].iov_len = ROUNDUP(ssrc.ss_len);
377 	smsg.sadb_msg_len += sa_src.sadb_address_len;
378 	iov_cnt++;
379 
380 	switch (mtype) {
381 	case SADB_ADD:
382 	case SADB_UPDATE:
383 		if (alen) {
384 			/* auth key */
385 			iov[iov_cnt].iov_base = &sa_akey;
386 			iov[iov_cnt].iov_len = sizeof(sa_akey);
387 			iov_cnt++;
388 			iov[iov_cnt].iov_base = akey;
389 			iov[iov_cnt].iov_len = ((alen + 7) / 8) * 8;
390 			smsg.sadb_msg_len += sa_akey.sadb_key_len;
391 			iov_cnt++;
392 		}
393 		if (elen) {
394 			/* encryption key */
395 			iov[iov_cnt].iov_base = &sa_ekey;
396 			iov[iov_cnt].iov_len = sizeof(sa_ekey);
397 			iov_cnt++;
398 			iov[iov_cnt].iov_base = ekey;
399 			iov[iov_cnt].iov_len = ((elen + 7) / 8) * 8;
400 			smsg.sadb_msg_len += sa_ekey.sadb_key_len;
401 			iov_cnt++;
402 		}
403 		break;
404 	}
405 
406 	len = smsg.sadb_msg_len * 8;
407 	do {
408 		n = writev(sd, iov, iov_cnt);
409 	} while (n == -1 && (errno == EAGAIN || errno == EINTR));
410 
411 	if (n == -1) {
412 		log_warn("%s: writev (%d/%d)", __func__, iov_cnt, len);
413 		return (-1);
414 	}
415 
416 	return (0);
417 }
418 
419 int
420 pfkey_read(int sd, struct sadb_msg *h)
421 {
422 	struct sadb_msg hdr;
423 
424 	if (recv(sd, &hdr, sizeof(hdr), MSG_PEEK) != sizeof(hdr)) {
425 		if (errno == EAGAIN || errno == EINTR)
426 			return (0);
427 		log_warn("pfkey peek");
428 		return (-1);
429 	}
430 
431 	/* XXX: Only one message can be outstanding. */
432 	if (hdr.sadb_msg_seq == sadb_msg_seq &&
433 	    hdr.sadb_msg_pid == pid) {
434 		if (h)
435 			bcopy(&hdr, h, sizeof(hdr));
436 		return (0);
437 	}
438 
439 	/* not ours, discard */
440 	if (read(sd, &hdr, sizeof(hdr)) == -1) {
441 		if (errno == EAGAIN || errno == EINTR)
442 			return (0);
443 		log_warn("pfkey read");
444 		return (-1);
445 	}
446 
447 	return (1);
448 }
449 
450 int
451 pfkey_reply(int sd, uint32_t *spi)
452 {
453 	struct sadb_msg hdr, *msg;
454 	struct sadb_ext *ext;
455 	struct sadb_sa *sa;
456 	uint8_t *data;
457 	ssize_t len;
458 	int rv;
459 
460 	do {
461 		rv = pfkey_read(sd, &hdr);
462 		if (rv == -1)
463 			return (-1);
464 	} while (rv);
465 
466 	if (hdr.sadb_msg_errno != 0) {
467 		errno = hdr.sadb_msg_errno;
468 		if (errno == ESRCH)
469 			return (0);
470 		else {
471 			log_warn("pfkey");
472 			/* discard error message */
473 			if (read(sd, &hdr, sizeof(hdr)) == -1)
474 				log_warn("pfkey read");
475 			return (-1);
476 		}
477 	}
478 	if ((data = reallocarray(NULL, hdr.sadb_msg_len, PFKEY2_CHUNK))
479 	    == NULL) {
480 		log_warn("pfkey malloc");
481 		return (-1);
482 	}
483 	len = hdr.sadb_msg_len * PFKEY2_CHUNK;
484 	if (read(sd, data, len) != len) {
485 		log_warn("pfkey read");
486 		freezero(data, len);
487 		return (-1);
488 	}
489 
490 	if (hdr.sadb_msg_type == SADB_GETSPI) {
491 		if (spi == NULL) {
492 			freezero(data, len);
493 			return (0);
494 		}
495 
496 		msg = (struct sadb_msg *)data;
497 		for (ext = (struct sadb_ext *)(msg + 1);
498 		    (size_t)((uint8_t *)ext - (uint8_t *)msg) <
499 		    msg->sadb_msg_len * PFKEY2_CHUNK;
500 		    ext = (struct sadb_ext *)((uint8_t *)ext +
501 		    ext->sadb_ext_len * PFKEY2_CHUNK)) {
502 			if (ext->sadb_ext_type == SADB_EXT_SA) {
503 				sa = (struct sadb_sa *) ext;
504 				*spi = ntohl(sa->sadb_sa_spi);
505 				break;
506 			}
507 		}
508 	}
509 	freezero(data, len);
510 	return (0);
511 }
512 
513 static int
514 pfkey_sa_add(struct bgpd_addr *src, struct bgpd_addr *dst, uint8_t keylen,
515     char *key, uint32_t *spi)
516 {
517 	if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_GETSPI, 0,
518 	    src, dst, 0, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
519 		return (-1);
520 	if (pfkey_reply(pfkey_fd, spi) == -1)
521 		return (-1);
522 	if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_UPDATE, 0,
523 		src, dst, *spi, 0, keylen, key, 0, 0, NULL, 0, 0) == -1)
524 		return (-1);
525 	if (pfkey_reply(pfkey_fd, NULL) == -1)
526 		return (-1);
527 	return (0);
528 }
529 
530 static int
531 pfkey_sa_remove(struct bgpd_addr *src, struct bgpd_addr *dst, uint32_t *spi)
532 {
533 	if (pfkey_send(pfkey_fd, SADB_X_SATYPE_TCPSIGNATURE, SADB_DELETE, 0,
534 	    src, dst, *spi, 0, 0, NULL, 0, 0, NULL, 0, 0) == -1)
535 		return (-1);
536 	if (pfkey_reply(pfkey_fd, NULL) == -1)
537 		return (-1);
538 	*spi = 0;
539 	return (0);
540 }
541 
542 static int
543 pfkey_md5sig_establish(struct peer *p)
544 {
545 	uint32_t spi_out = 0;
546 	uint32_t spi_in = 0;
547 
548 	if (pfkey_sa_add(pfkey_localaddr(p), &p->conf.remote_addr,
549 	    p->conf.auth.md5key_len, p->conf.auth.md5key,
550 	    &spi_out) == -1)
551 		goto fail;
552 
553 	if (pfkey_sa_add(&p->conf.remote_addr, pfkey_localaddr(p),
554 	    p->conf.auth.md5key_len, p->conf.auth.md5key,
555 	    &spi_in) == -1)
556 		goto fail;
557 
558 	/* cleanup old flow if one was present */
559 	if (p->auth.established) {
560 		if (pfkey_remove(p) == -1)
561 			return (-1);
562 	}
563 
564 	p->auth.established = 1;
565 	p->auth.spi_out = spi_out;
566 	p->auth.spi_in = spi_in;
567 	return (0);
568 
569 fail:
570 	log_peer_warn(&p->conf, "failed to insert md5sig");
571 	return (-1);
572 }
573 
574 static int
575 pfkey_md5sig_remove(struct peer *p)
576 {
577 	if (p->auth.spi_out)
578 		if (pfkey_sa_remove(&p->auth.local_addr, &p->conf.remote_addr,
579 		    &p->auth.spi_out) == -1)
580 			goto fail;
581 	if (p->auth.spi_in)
582 		if (pfkey_sa_remove(&p->conf.remote_addr, &p->auth.local_addr,
583 		    &p->auth.spi_in) == -1)
584 			goto fail;
585 
586 	p->auth.established = 0;
587 	p->auth.spi_out = 0;
588 	p->auth.spi_in = 0;
589 	return (0);
590 
591 fail:
592 	log_peer_warn(&p->conf, "failed to remove md5sig");
593 	return (-1);
594 }
595 
596 static uint8_t
597 pfkey_auth_alg(enum auth_alg alg)
598 {
599 	switch (alg) {
600 	case AUTH_AALG_SHA1HMAC:
601 		return SADB_AALG_SHA1HMAC;
602 	case AUTH_AALG_MD5HMAC:
603 		return SADB_AALG_MD5HMAC;
604 	default:
605 		return SADB_AALG_NONE;
606 	}
607 }
608 
609 static uint8_t
610 pfkey_enc_alg(enum auth_enc_alg alg)
611 {
612 	switch (alg) {
613 	case AUTH_EALG_3DESCBC:
614 		return SADB_EALG_3DESCBC;
615 	case AUTH_EALG_AES:
616 		return SADB_X_EALG_AES;
617 	default:
618 		return SADB_AALG_NONE;
619 	}
620 }
621 
622 static int
623 pfkey_ipsec_establish(struct peer *p)
624 {
625 	uint8_t satype = SADB_SATYPE_ESP;
626 	struct bgpd_addr *local_addr = pfkey_localaddr(p);
627 
628 	/* cleanup first, unlike in the TCP MD5 case */
629 	if (p->auth.established) {
630 		if (pfkey_remove(p) == -1)
631 			return (-1);
632 	}
633 
634 	switch (p->auth.method) {
635 	case AUTH_IPSEC_IKE_ESP:
636 		satype = SADB_SATYPE_ESP;
637 		break;
638 	case AUTH_IPSEC_IKE_AH:
639 		satype = SADB_SATYPE_AH;
640 		break;
641 	case AUTH_IPSEC_MANUAL_ESP:
642 	case AUTH_IPSEC_MANUAL_AH:
643 		satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
644 		    SADB_SATYPE_ESP : SADB_SATYPE_AH;
645 		if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
646 		    local_addr, &p->conf.remote_addr,
647 		    p->conf.auth.spi_out,
648 		    pfkey_auth_alg(p->conf.auth.auth_alg_out),
649 		    p->conf.auth.auth_keylen_out,
650 		    p->conf.auth.auth_key_out,
651 		    pfkey_enc_alg(p->conf.auth.enc_alg_out),
652 		    p->conf.auth.enc_keylen_out,
653 		    p->conf.auth.enc_key_out,
654 		    0, 0) == -1)
655 			goto fail_key;
656 		if (pfkey_reply(pfkey_fd, NULL) == -1)
657 			goto fail_key;
658 		if (pfkey_send(pfkey_fd, satype, SADB_ADD, 0,
659 		    &p->conf.remote_addr, local_addr,
660 		    p->conf.auth.spi_in,
661 		    pfkey_auth_alg(p->conf.auth.auth_alg_in),
662 		    p->conf.auth.auth_keylen_in,
663 		    p->conf.auth.auth_key_in,
664 		    pfkey_enc_alg(p->conf.auth.enc_alg_in),
665 		    p->conf.auth.enc_keylen_in,
666 		    p->conf.auth.enc_key_in,
667 		    0, 0) == -1)
668 			goto fail_key;
669 		if (pfkey_reply(pfkey_fd, NULL) == -1)
670 			goto fail_key;
671 		break;
672 	default:
673 		return (-1);
674 	}
675 
676 	if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
677 	    local_addr, &p->conf.remote_addr, 0, BGP_PORT) == -1)
678 		goto fail_flow;
679 	if (pfkey_reply(pfkey_fd, NULL) == -1)
680 		goto fail_flow;
681 
682 	if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_OUT,
683 	    local_addr, &p->conf.remote_addr, BGP_PORT, 0) == -1)
684 		goto fail_flow;
685 	if (pfkey_reply(pfkey_fd, NULL) == -1)
686 		goto fail_flow;
687 
688 	if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
689 	    &p->conf.remote_addr, local_addr, 0, BGP_PORT) == -1)
690 		goto fail_flow;
691 	if (pfkey_reply(pfkey_fd, NULL) == -1)
692 		goto fail_flow;
693 
694 	if (pfkey_flow(pfkey_fd, satype, SADB_X_ADDFLOW, IPSP_DIRECTION_IN,
695 	    &p->conf.remote_addr, local_addr, BGP_PORT, 0) == -1)
696 		goto fail_flow;
697 	if (pfkey_reply(pfkey_fd, NULL) == -1)
698 		goto fail_flow;
699 
700 	/* save SPI so that they can be removed later on */
701 	p->auth.spi_in = p->conf.auth.spi_in;
702 	p->auth.spi_out = p->conf.auth.spi_out;
703 	p->auth.established = 1;
704 	return (0);
705 
706 fail_key:
707 	log_peer_warn(&p->conf, "failed to insert ipsec key");
708 	return (-1);
709 fail_flow:
710 	log_peer_warn(&p->conf, "failed to insert ipsec flow");
711 	return (-1);
712 }
713 
714 static int
715 pfkey_ipsec_remove(struct peer *p)
716 {
717 	uint8_t satype;
718 
719 	switch (p->auth.method) {
720 	case AUTH_IPSEC_IKE_ESP:
721 		satype = SADB_SATYPE_ESP;
722 		break;
723 	case AUTH_IPSEC_IKE_AH:
724 		satype = SADB_SATYPE_AH;
725 		break;
726 	case AUTH_IPSEC_MANUAL_ESP:
727 	case AUTH_IPSEC_MANUAL_AH:
728 		satype = p->auth.method == AUTH_IPSEC_MANUAL_ESP ?
729 		    SADB_SATYPE_ESP : SADB_SATYPE_AH;
730 		if (pfkey_send(pfkey_fd, satype, SADB_DELETE, 0,
731 		    &p->auth.local_addr, &p->conf.remote_addr,
732 		    p->auth.spi_out, 0, 0, NULL, 0, 0, NULL,
733 		    0, 0) == -1)
734 			goto fail_key;
735 		if (pfkey_reply(pfkey_fd, NULL) == -1)
736 			goto fail_key;
737 
738 		if (pfkey_send(pfkey_fd, satype, SADB_DELETE, 0,
739 		    &p->conf.remote_addr, &p->auth.local_addr,
740 		    p->auth.spi_in, 0, 0, NULL, 0, 0, NULL,
741 		    0, 0) == -1)
742 			goto fail_key;
743 		if (pfkey_reply(pfkey_fd, NULL) == -1)
744 			goto fail_key;
745 		break;
746 	default:
747 		return (-1);
748 	}
749 
750 	if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
751 	    &p->auth.local_addr, &p->conf.remote_addr, 0, BGP_PORT) == -1)
752 		goto fail_flow;
753 	if (pfkey_reply(pfkey_fd, NULL) == -1)
754 		goto fail_flow;
755 
756 	if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_OUT,
757 	    &p->auth.local_addr, &p->conf.remote_addr, BGP_PORT, 0) == -1)
758 		goto fail_flow;
759 	if (pfkey_reply(pfkey_fd, NULL) == -1)
760 		goto fail_flow;
761 
762 	if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
763 	    &p->conf.remote_addr, &p->auth.local_addr, 0, BGP_PORT) == -1)
764 		goto fail_flow;
765 	if (pfkey_reply(pfkey_fd, NULL) == -1)
766 		goto fail_flow;
767 
768 	if (pfkey_flow(pfkey_fd, satype, SADB_X_DELFLOW, IPSP_DIRECTION_IN,
769 	    &p->conf.remote_addr, &p->auth.local_addr, BGP_PORT, 0) == -1)
770 		goto fail_flow;
771 	if (pfkey_reply(pfkey_fd, NULL) == -1)
772 		goto fail_flow;
773 
774 	p->auth.established = 0;
775 	p->auth.spi_out = 0;
776 	p->auth.spi_in = 0;
777 	return (0);
778 
779 fail_key:
780 	log_peer_warn(&p->conf, "failed to remove ipsec key");
781 	return (-1);
782 fail_flow:
783 	log_peer_warn(&p->conf, "failed to remove ipsec flow");
784 	return (-1);
785 }
786 
787 int
788 pfkey_establish(struct peer *p)
789 {
790 	int rv;
791 
792 	switch (p->conf.auth.method) {
793 	case AUTH_NONE:
794 		rv = 0;
795 		if (p->auth.established)
796 			rv = pfkey_remove(p);
797 		break;
798 	case AUTH_MD5SIG:
799 		rv = pfkey_md5sig_establish(p);
800 		break;
801 	default:
802 		rv = pfkey_ipsec_establish(p);
803 		break;
804 	}
805 	/*
806 	 * make sure we keep copies of everything we need to
807 	 * remove SAs and flows later again, even if the
808 	 * info in p->conf changed due to reload.
809 	 * We need: SPIs, method, local_addr, remote_addr.
810 	 * remote_addr cannot change, so no copy, SPI are
811 	 * handled by the method specific functions.
812 	 */
813 	memcpy(&p->auth.local_addr, pfkey_localaddr(p),
814 	    sizeof(p->auth.local_addr));
815 	p->auth.method = p->conf.auth.method;
816 
817 	return (rv);
818 }
819 
820 int
821 pfkey_remove(struct peer *p)
822 {
823 	if (p->auth.established == 0)
824 		return (0);
825 
826 	switch (p->auth.method) {
827 	case AUTH_NONE:
828 		return (0);
829 	case AUTH_MD5SIG:
830 		return (pfkey_md5sig_remove(p));
831 	default:
832 		return (pfkey_ipsec_remove(p));
833 	}
834 }
835 
836 int
837 pfkey_init(void)
838 {
839 	if ((pfkey_fd = socket(PF_KEY, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
840 	    PF_KEY_V2)) == -1) {
841 		if (errno == EPROTONOSUPPORT) {
842 			log_warnx("PF_KEY not available, disabling ipsec");
843 			return (-1);
844 		} else
845 			fatal("pfkey setup failed");
846 	}
847 	return (pfkey_fd);
848 }
849 
850 /* verify that connection is using TCP MD5UM if required by config */
851 int
852 tcp_md5_check(int fd, struct peer *p)
853 {
854 	socklen_t len;
855 	int opt;
856 
857 	if (p->conf.auth.method == AUTH_MD5SIG) {
858 		if (sysdep.no_md5sig) {
859 			log_peer_warnx(&p->conf,
860 			    "md5sig configured but not available");
861 			return -1;
862 		}
863 		len = sizeof(opt);
864 		if (getsockopt(fd, IPPROTO_TCP, TCP_MD5SIG,
865 		    &opt, &len) == -1)
866 			fatal("getsockopt TCP_MD5SIG");
867 		if (!opt) {     /* non-md5'd connection! */
868 			log_peer_warnx(&p->conf,
869 			    "connection attempt without md5 signature");
870 			return -1;
871 		}
872 	}
873 	return 0;
874 }
875 
876 /* enable or set TCP MD5SIG on a new client connection */
877 int
878 tcp_md5_set(int fd, struct peer *p)
879 {
880 	int opt = 1;
881 
882 	if (p->conf.auth.method == AUTH_MD5SIG) {
883 		if (sysdep.no_md5sig) {
884 			log_peer_warnx(&p->conf,
885 			    "md5sig configured but not available");
886 			return -1;
887 		}
888 		if (setsockopt(fd, IPPROTO_TCP, TCP_MD5SIG,
889 		    &opt, sizeof(opt)) == -1) {
890 			log_peer_warn(&p->conf, "setsockopt md5sig");
891 			return -1;
892 		}
893 	}
894 	return 0;
895 }
896 
897 /* enable or prepare a new listening socket for TCP MD5SIG usage */
898 int
899 tcp_md5_prep_listener(struct listen_addr *la, struct peer_head *p)
900 {
901 	int opt = 1;
902 
903 	if (setsockopt(la->fd, IPPROTO_TCP, TCP_MD5SIG,
904 	    &opt, sizeof(opt)) == -1) {
905 		if (errno == ENOPROTOOPT) {	/* system w/o md5sig */
906 			log_warnx("md5sig not available, disabling");
907 			sysdep.no_md5sig = 1;
908 			return 0;
909 		}
910 		return -1;
911 	}
912 	return 0;
913 }
914 
915 /* add md5 key to all listening sockets, dummy function for portable */
916 void
917 tcp_md5_add_listener(struct bgpd_config *conf, struct peer *p)
918 {
919 }
920 
921 /* delete md5 key form all listening sockets, dummy function for portable */
922 void
923 tcp_md5_del_listener(struct bgpd_config *conf, struct peer *p)
924 {
925 }
926