4 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2003, 2004 Markus Friedl <markus@openbsd.org>
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.
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.
25 #include <sys/types.h>
26 #include <sys/socket.h>
36 static int pfkey_send(int, uint8_t, uint8_t, uint8_t,
37 int, union ldpd_addr
*, union ldpd_addr
*,
38 uint32_t, uint8_t, int, char *, uint8_t, int, char *,
40 static int pfkey_reply(int, uint32_t *);
41 static int pfkey_sa_add(int, union ldpd_addr
*, union ldpd_addr
*,
42 uint8_t, char *, uint32_t *);
43 static int pfkey_sa_remove(int, union ldpd_addr
*, union ldpd_addr
*,
45 static int pfkey_md5sig_establish(struct nbr
*, struct nbr_params
*nbrp
);
46 static int pfkey_md5sig_remove(struct nbr
*);
48 #define PFKEY2_CHUNK sizeof(uint64_t)
49 #define ROUNDUP(x) (((x) + (PFKEY2_CHUNK - 1)) & ~(PFKEY2_CHUNK - 1))
52 static uint32_t sadb_msg_seq
;
53 static uint32_t pid
; /* should pid_t but pfkey needs uint32_t */
57 pfkey_send(int sd
, uint8_t satype
, uint8_t mtype
, uint8_t dir
,
58 int af
, union ldpd_addr
*src
, union ldpd_addr
*dst
, uint32_t spi
,
59 uint8_t aalg
, int alen
, char *akey
, uint8_t ealg
, int elen
, char *ekey
,
60 uint16_t sport
, uint16_t dport
)
64 struct sadb_address sa_src
, sa_dst
;
65 struct sadb_key sa_akey
, sa_ekey
;
66 struct sadb_spirange sa_spirange
;
67 struct iovec iov
[IOV_CNT
];
71 struct sockaddr_storage smask
, dmask
;
72 union sockunion su_src
, su_dst
;
77 /* we need clean sockaddr... no ports set */
78 memset(&smask
, 0, sizeof(smask
));
80 addr2sa(af
, src
, 0, &su_src
);
84 memset(&((struct sockaddr_in
*)&smask
)->sin_addr
, 0xff, 32/8);
87 memset(&((struct sockaddr_in6
*)&smask
)->sin6_addr
, 0xff,
93 smask
.ss_family
= su_src
.sa
.sa_family
;
94 smask
.ss_len
= sockaddr_len(&su_src
.sa
);
96 memset(&dmask
, 0, sizeof(dmask
));
98 addr2sa(af
, dst
, 0, &su_dst
);
102 memset(&((struct sockaddr_in
*)&dmask
)->sin_addr
, 0xff, 32/8);
105 memset(&((struct sockaddr_in6
*)&dmask
)->sin6_addr
, 0xff,
111 dmask
.ss_family
= su_dst
.sa
.sa_family
;
112 dmask
.ss_len
= sockaddr_len(&su_dst
.sa
);
114 memset(&smsg
, 0, sizeof(smsg
));
115 smsg
.sadb_msg_version
= PF_KEY_V2
;
116 smsg
.sadb_msg_seq
= ++sadb_msg_seq
;
117 smsg
.sadb_msg_pid
= pid
;
118 smsg
.sadb_msg_len
= sizeof(smsg
) / 8;
119 smsg
.sadb_msg_type
= mtype
;
120 smsg
.sadb_msg_satype
= satype
;
124 memset(&sa_spirange
, 0, sizeof(sa_spirange
));
125 sa_spirange
.sadb_spirange_exttype
= SADB_EXT_SPIRANGE
;
126 sa_spirange
.sadb_spirange_len
= sizeof(sa_spirange
) / 8;
127 sa_spirange
.sadb_spirange_min
= 0x100;
128 sa_spirange
.sadb_spirange_max
= 0xffffffff;
129 sa_spirange
.sadb_spirange_reserved
= 0;
134 memset(&sa
, 0, sizeof(sa
));
135 sa
.sadb_sa_exttype
= SADB_EXT_SA
;
136 sa
.sadb_sa_len
= sizeof(sa
) / 8;
137 sa
.sadb_sa_replay
= 0;
138 sa
.sadb_sa_spi
= htonl(spi
);
139 sa
.sadb_sa_state
= SADB_SASTATE_MATURE
;
143 memset(&sa_src
, 0, sizeof(sa_src
));
144 sa_src
.sadb_address_exttype
= SADB_EXT_ADDRESS_SRC
;
145 sa_src
.sadb_address_len
=
146 (sizeof(sa_src
) + ROUNDUP(sockaddr_len(&su_src
.sa
))) / 8;
148 memset(&sa_dst
, 0, sizeof(sa_dst
));
149 sa_dst
.sadb_address_exttype
= SADB_EXT_ADDRESS_DST
;
150 sa_dst
.sadb_address_len
=
151 (sizeof(sa_dst
) + ROUNDUP(sockaddr_len(&su_dst
.sa
))) / 8;
153 sa
.sadb_sa_auth
= aalg
;
154 sa
.sadb_sa_encrypt
= SADB_X_EALG_AES
; /* XXX */
159 memset(&sa_akey
, 0, sizeof(sa_akey
));
160 sa_akey
.sadb_key_exttype
= SADB_EXT_KEY_AUTH
;
161 sa_akey
.sadb_key_len
= (sizeof(sa_akey
) +
162 ((alen
+ 7) / 8) * 8) / 8;
163 sa_akey
.sadb_key_bits
= 8 * alen
;
165 memset(&sa_ekey
, 0, sizeof(sa_ekey
));
166 sa_ekey
.sadb_key_exttype
= SADB_EXT_KEY_ENCRYPT
;
167 sa_ekey
.sadb_key_len
= (sizeof(sa_ekey
) +
168 ((elen
+ 7) / 8) * 8) / 8;
169 sa_ekey
.sadb_key_bits
= 8 * elen
;
177 iov
[iov_cnt
].iov_base
= &smsg
;
178 iov
[iov_cnt
].iov_len
= sizeof(smsg
);
186 iov
[iov_cnt
].iov_base
= &sa
;
187 iov
[iov_cnt
].iov_len
= sizeof(sa
);
188 smsg
.sadb_msg_len
+= sa
.sadb_sa_len
;
193 iov
[iov_cnt
].iov_base
= &sa_spirange
;
194 iov
[iov_cnt
].iov_len
= sizeof(sa_spirange
);
195 smsg
.sadb_msg_len
+= sa_spirange
.sadb_spirange_len
;
201 iov
[iov_cnt
].iov_base
= &sa_dst
;
202 iov
[iov_cnt
].iov_len
= sizeof(sa_dst
);
204 iov
[iov_cnt
].iov_base
= &su_dst
;
205 iov
[iov_cnt
].iov_len
= ROUNDUP(sockaddr_len(&su_dst
.sa
));
206 smsg
.sadb_msg_len
+= sa_dst
.sadb_address_len
;
210 iov
[iov_cnt
].iov_base
= &sa_src
;
211 iov
[iov_cnt
].iov_len
= sizeof(sa_src
);
213 iov
[iov_cnt
].iov_base
= &su_src
;
214 iov
[iov_cnt
].iov_len
= ROUNDUP(sockaddr_len(&su_src
.sa
));
215 smsg
.sadb_msg_len
+= sa_src
.sadb_address_len
;
223 iov
[iov_cnt
].iov_base
= &sa_akey
;
224 iov
[iov_cnt
].iov_len
= sizeof(sa_akey
);
226 iov
[iov_cnt
].iov_base
= akey
;
227 iov
[iov_cnt
].iov_len
= ((alen
+ 7) / 8) * 8;
228 smsg
.sadb_msg_len
+= sa_akey
.sadb_key_len
;
233 iov
[iov_cnt
].iov_base
= &sa_ekey
;
234 iov
[iov_cnt
].iov_len
= sizeof(sa_ekey
);
236 iov
[iov_cnt
].iov_base
= ekey
;
237 iov
[iov_cnt
].iov_len
= ((elen
+ 7) / 8) * 8;
238 smsg
.sadb_msg_len
+= sa_ekey
.sadb_key_len
;
244 len
= smsg
.sadb_msg_len
* 8;
246 n
= writev(sd
, iov
, iov_cnt
);
247 } while (n
== -1 && (errno
== EAGAIN
|| errno
== EINTR
));
250 log_warn("writev (%d/%d)", iov_cnt
, len
);
258 pfkey_read(int sd
, struct sadb_msg
*h
)
262 if (recv(sd
, &hdr
, sizeof(hdr
), MSG_PEEK
) != sizeof(hdr
)) {
263 if (errno
== EAGAIN
|| errno
== EINTR
)
265 log_warn("pfkey peek");
269 /* XXX: Only one message can be outstanding. */
270 if (hdr
.sadb_msg_seq
== sadb_msg_seq
&&
271 hdr
.sadb_msg_pid
== pid
) {
277 /* not ours, discard */
278 if (read(sd
, &hdr
, sizeof(hdr
)) == -1) {
279 if (errno
== EAGAIN
|| errno
== EINTR
)
281 log_warn("pfkey read");
289 pfkey_reply(int sd
, uint32_t *spi
)
291 struct sadb_msg hdr
, *msg
;
292 struct sadb_ext
*ext
;
299 rv
= pfkey_read(sd
, &hdr
);
304 if (hdr
.sadb_msg_errno
!= 0) {
305 errno
= hdr
.sadb_msg_errno
;
313 if ((data
= reallocarray(NULL
, hdr
.sadb_msg_len
, PFKEY2_CHUNK
)) == NULL
) {
314 log_warn("pfkey malloc");
317 len
= hdr
.sadb_msg_len
* PFKEY2_CHUNK
;
318 if (read(sd
, data
, len
) != len
) {
319 log_warn("pfkey read");
320 explicit_bzero(data
, len
);
325 if (hdr
.sadb_msg_type
== SADB_GETSPI
) {
327 explicit_bzero(data
, len
);
332 msg
= (struct sadb_msg
*)data
;
333 for (ext
= (struct sadb_ext
*)(msg
+ 1);
334 (size_t)((uint8_t *)ext
- (uint8_t *)msg
) <
335 msg
->sadb_msg_len
* PFKEY2_CHUNK
;
336 ext
= (struct sadb_ext
*)((uint8_t *)ext
+
337 ext
->sadb_ext_len
* PFKEY2_CHUNK
)) {
338 if (ext
->sadb_ext_type
== SADB_EXT_SA
) {
339 sa
= (struct sadb_sa
*) ext
;
340 *spi
= ntohl(sa
->sadb_sa_spi
);
345 explicit_bzero(data
, len
);
351 pfkey_sa_add(int af
, union ldpd_addr
*src
, union ldpd_addr
*dst
, uint8_t keylen
,
352 char *key
, uint32_t *spi
)
354 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_GETSPI
, 0,
355 af
, src
, dst
, 0, 0, 0, NULL
, 0, 0, NULL
, 0, 0) < 0)
357 if (pfkey_reply(fd
, spi
) < 0)
359 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_UPDATE
, 0,
360 af
, src
, dst
, *spi
, 0, keylen
, key
, 0, 0, NULL
, 0, 0) < 0)
362 if (pfkey_reply(fd
, NULL
) < 0)
368 pfkey_sa_remove(int af
, union ldpd_addr
*src
, union ldpd_addr
*dst
,
371 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_DELETE
, 0,
372 af
, src
, dst
, *spi
, 0, 0, NULL
, 0, 0, NULL
, 0, 0) < 0)
374 if (pfkey_reply(fd
, NULL
) < 0)
381 pfkey_md5sig_establish(struct nbr
*nbr
, struct nbr_params
*nbrp
)
385 if (!nbr
->auth
.spi_out
)
386 if (pfkey_sa_add(nbr
->af
, &nbr
->laddr
, &nbr
->raddr
,
387 nbrp
->auth
.md5key_len
, nbrp
->auth
.md5key
,
388 &nbr
->auth
.spi_out
) == -1)
390 if (!nbr
->auth
.spi_in
)
391 if (pfkey_sa_add(nbr
->af
, &nbr
->raddr
, &nbr
->laddr
,
392 nbrp
->auth
.md5key_len
, nbrp
->auth
.md5key
,
393 &nbr
->auth
.spi_in
) == -1)
396 nbr
->auth
.established
= 1;
401 pfkey_md5sig_remove(struct nbr
*nbr
)
403 if (nbr
->auth
.spi_out
)
404 if (pfkey_sa_remove(nbr
->af
, &nbr
->laddr
, &nbr
->raddr
,
405 &nbr
->auth
.spi_out
) == -1)
407 if (nbr
->auth
.spi_in
)
408 if (pfkey_sa_remove(nbr
->af
, &nbr
->raddr
, &nbr
->laddr
,
409 &nbr
->auth
.spi_in
) == -1)
412 nbr
->auth
.established
= 0;
413 nbr
->auth
.spi_in
= 0;
414 nbr
->auth
.spi_out
= 0;
415 nbr
->auth
.method
= AUTH_NONE
;
416 memset(nbr
->auth
.md5key
, 0, sizeof(nbr
->auth
.md5key
));
422 pfkey_establish(struct nbr
*nbr
, struct nbr_params
*nbrp
)
424 if (nbrp
->auth
.method
== AUTH_NONE
)
427 switch (nbr
->auth
.method
) {
429 strlcpy(nbr
->auth
.md5key
, nbrp
->auth
.md5key
,
430 sizeof(nbr
->auth
.md5key
));
431 return (pfkey_md5sig_establish(nbr
, nbrp
));
440 pfkey_remove(struct nbr
*nbr
)
442 if (nbr
->auth
.method
== AUTH_NONE
|| !nbr
->auth
.established
)
445 switch (nbr
->auth
.method
) {
447 return (pfkey_md5sig_remove(nbr
));
458 if ((fd
= socket(PF_KEY
, SOCK_RAW
| SOCK_CLOEXEC
| SOCK_NONBLOCK
,
460 if (errno
== EPROTONOSUPPORT
) {
461 log_warnx("PF_KEY not available");
465 fatal("pfkey setup failed");
469 #endif /* __OpenBSD__ */