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