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.
21 #include <sys/types.h>
22 #include <sys/socket.h>
32 static int pfkey_send(int, uint8_t, uint8_t, uint8_t,
33 int, union ldpd_addr
*, union ldpd_addr
*,
34 uint32_t, uint8_t, int, char *, uint8_t, int, char *,
36 static int pfkey_reply(int, uint32_t *);
37 static int pfkey_sa_add(int, union ldpd_addr
*, union ldpd_addr
*,
38 uint8_t, char *, uint32_t *);
39 static int pfkey_sa_remove(int, union ldpd_addr
*, union ldpd_addr
*,
41 static int pfkey_md5sig_establish(struct nbr
*, struct nbr_params
*nbrp
);
42 static int pfkey_md5sig_remove(struct nbr
*);
44 #define PFKEY2_CHUNK sizeof(uint64_t)
45 #define ROUNDUP(x) (((x) + (PFKEY2_CHUNK - 1)) & ~(PFKEY2_CHUNK - 1))
48 static uint32_t sadb_msg_seq
;
49 static uint32_t pid
; /* should pid_t but pfkey needs uint32_t */
53 pfkey_send(int sd
, uint8_t satype
, uint8_t mtype
, uint8_t dir
,
54 int af
, union ldpd_addr
*src
, union ldpd_addr
*dst
, uint32_t spi
,
55 uint8_t aalg
, int alen
, char *akey
, uint8_t ealg
, int elen
, char *ekey
,
56 uint16_t sport
, uint16_t dport
)
60 struct sadb_address sa_src
, sa_dst
;
61 struct sadb_key sa_akey
, sa_ekey
;
62 struct sadb_spirange sa_spirange
;
63 struct iovec iov
[IOV_CNT
];
67 struct sockaddr_storage smask
, dmask
;
68 union sockunion su_src
, su_dst
;
73 /* we need clean sockaddr... no ports set */
74 memset(&smask
, 0, sizeof(smask
));
76 addr2sa(af
, src
, 0, &su_src
);
80 memset(&((struct sockaddr_in
*)&smask
)->sin_addr
, 0xff, 32/8);
83 memset(&((struct sockaddr_in6
*)&smask
)->sin6_addr
, 0xff,
89 smask
.ss_family
= su_src
.sa
.sa_family
;
90 smask
.ss_len
= sockaddr_len(&su_src
.sa
);
92 memset(&dmask
, 0, sizeof(dmask
));
94 addr2sa(af
, dst
, 0, &su_dst
);
98 memset(&((struct sockaddr_in
*)&dmask
)->sin_addr
, 0xff, 32/8);
101 memset(&((struct sockaddr_in6
*)&dmask
)->sin6_addr
, 0xff,
107 dmask
.ss_family
= su_dst
.sa
.sa_family
;
108 dmask
.ss_len
= sockaddr_len(&su_dst
.sa
);
110 memset(&smsg
, 0, sizeof(smsg
));
111 smsg
.sadb_msg_version
= PF_KEY_V2
;
112 smsg
.sadb_msg_seq
= ++sadb_msg_seq
;
113 smsg
.sadb_msg_pid
= pid
;
114 smsg
.sadb_msg_len
= sizeof(smsg
) / 8;
115 smsg
.sadb_msg_type
= mtype
;
116 smsg
.sadb_msg_satype
= satype
;
120 memset(&sa_spirange
, 0, sizeof(sa_spirange
));
121 sa_spirange
.sadb_spirange_exttype
= SADB_EXT_SPIRANGE
;
122 sa_spirange
.sadb_spirange_len
= sizeof(sa_spirange
) / 8;
123 sa_spirange
.sadb_spirange_min
= 0x100;
124 sa_spirange
.sadb_spirange_max
= 0xffffffff;
125 sa_spirange
.sadb_spirange_reserved
= 0;
130 memset(&sa
, 0, sizeof(sa
));
131 sa
.sadb_sa_exttype
= SADB_EXT_SA
;
132 sa
.sadb_sa_len
= sizeof(sa
) / 8;
133 sa
.sadb_sa_replay
= 0;
134 sa
.sadb_sa_spi
= htonl(spi
);
135 sa
.sadb_sa_state
= SADB_SASTATE_MATURE
;
139 memset(&sa_src
, 0, sizeof(sa_src
));
140 sa_src
.sadb_address_exttype
= SADB_EXT_ADDRESS_SRC
;
141 sa_src
.sadb_address_len
=
142 (sizeof(sa_src
) + ROUNDUP(sockaddr_len(&su_src
.sa
))) / 8;
144 memset(&sa_dst
, 0, sizeof(sa_dst
));
145 sa_dst
.sadb_address_exttype
= SADB_EXT_ADDRESS_DST
;
146 sa_dst
.sadb_address_len
=
147 (sizeof(sa_dst
) + ROUNDUP(sockaddr_len(&su_dst
.sa
))) / 8;
149 sa
.sadb_sa_auth
= aalg
;
150 sa
.sadb_sa_encrypt
= SADB_X_EALG_AES
; /* XXX */
155 memset(&sa_akey
, 0, sizeof(sa_akey
));
156 sa_akey
.sadb_key_exttype
= SADB_EXT_KEY_AUTH
;
157 sa_akey
.sadb_key_len
= (sizeof(sa_akey
) +
158 ((alen
+ 7) / 8) * 8) / 8;
159 sa_akey
.sadb_key_bits
= 8 * alen
;
161 memset(&sa_ekey
, 0, sizeof(sa_ekey
));
162 sa_ekey
.sadb_key_exttype
= SADB_EXT_KEY_ENCRYPT
;
163 sa_ekey
.sadb_key_len
= (sizeof(sa_ekey
) +
164 ((elen
+ 7) / 8) * 8) / 8;
165 sa_ekey
.sadb_key_bits
= 8 * elen
;
173 iov
[iov_cnt
].iov_base
= &smsg
;
174 iov
[iov_cnt
].iov_len
= sizeof(smsg
);
182 iov
[iov_cnt
].iov_base
= &sa
;
183 iov
[iov_cnt
].iov_len
= sizeof(sa
);
184 smsg
.sadb_msg_len
+= sa
.sadb_sa_len
;
189 iov
[iov_cnt
].iov_base
= &sa_spirange
;
190 iov
[iov_cnt
].iov_len
= sizeof(sa_spirange
);
191 smsg
.sadb_msg_len
+= sa_spirange
.sadb_spirange_len
;
197 iov
[iov_cnt
].iov_base
= &sa_dst
;
198 iov
[iov_cnt
].iov_len
= sizeof(sa_dst
);
200 iov
[iov_cnt
].iov_base
= &su_dst
;
201 iov
[iov_cnt
].iov_len
= ROUNDUP(sockaddr_len(&su_dst
.sa
));
202 smsg
.sadb_msg_len
+= sa_dst
.sadb_address_len
;
206 iov
[iov_cnt
].iov_base
= &sa_src
;
207 iov
[iov_cnt
].iov_len
= sizeof(sa_src
);
209 iov
[iov_cnt
].iov_base
= &su_src
;
210 iov
[iov_cnt
].iov_len
= ROUNDUP(sockaddr_len(&su_src
.sa
));
211 smsg
.sadb_msg_len
+= sa_src
.sadb_address_len
;
219 iov
[iov_cnt
].iov_base
= &sa_akey
;
220 iov
[iov_cnt
].iov_len
= sizeof(sa_akey
);
222 iov
[iov_cnt
].iov_base
= akey
;
223 iov
[iov_cnt
].iov_len
= ((alen
+ 7) / 8) * 8;
224 smsg
.sadb_msg_len
+= sa_akey
.sadb_key_len
;
229 iov
[iov_cnt
].iov_base
= &sa_ekey
;
230 iov
[iov_cnt
].iov_len
= sizeof(sa_ekey
);
232 iov
[iov_cnt
].iov_base
= ekey
;
233 iov
[iov_cnt
].iov_len
= ((elen
+ 7) / 8) * 8;
234 smsg
.sadb_msg_len
+= sa_ekey
.sadb_key_len
;
240 len
= smsg
.sadb_msg_len
* 8;
242 n
= writev(sd
, iov
, iov_cnt
);
243 } while (n
== -1 && (errno
== EAGAIN
|| errno
== EINTR
));
246 log_warn("writev (%d/%d)", iov_cnt
, len
);
254 pfkey_read(int sd
, struct sadb_msg
*h
)
258 if (recv(sd
, &hdr
, sizeof(hdr
), MSG_PEEK
) != sizeof(hdr
)) {
259 if (errno
== EAGAIN
|| errno
== EINTR
)
261 log_warn("pfkey peek");
265 /* XXX: Only one message can be outstanding. */
266 if (hdr
.sadb_msg_seq
== sadb_msg_seq
&&
267 hdr
.sadb_msg_pid
== pid
) {
273 /* not ours, discard */
274 if (read(sd
, &hdr
, sizeof(hdr
)) == -1) {
275 if (errno
== EAGAIN
|| errno
== EINTR
)
277 log_warn("pfkey read");
285 pfkey_reply(int sd
, uint32_t *spi
)
287 struct sadb_msg hdr
, *msg
;
288 struct sadb_ext
*ext
;
295 rv
= pfkey_read(sd
, &hdr
);
300 if (hdr
.sadb_msg_errno
!= 0) {
301 errno
= hdr
.sadb_msg_errno
;
309 if ((data
= reallocarray(NULL
, hdr
.sadb_msg_len
, PFKEY2_CHUNK
)) == NULL
) {
310 log_warn("pfkey malloc");
313 len
= hdr
.sadb_msg_len
* PFKEY2_CHUNK
;
314 if (read(sd
, data
, len
) != len
) {
315 log_warn("pfkey read");
316 explicit_bzero(data
, len
);
321 if (hdr
.sadb_msg_type
== SADB_GETSPI
) {
323 explicit_bzero(data
, len
);
328 msg
= (struct sadb_msg
*)data
;
329 for (ext
= (struct sadb_ext
*)(msg
+ 1);
330 (size_t)((uint8_t *)ext
- (uint8_t *)msg
) <
331 msg
->sadb_msg_len
* PFKEY2_CHUNK
;
332 ext
= (struct sadb_ext
*)((uint8_t *)ext
+
333 ext
->sadb_ext_len
* PFKEY2_CHUNK
)) {
334 if (ext
->sadb_ext_type
== SADB_EXT_SA
) {
335 sa
= (struct sadb_sa
*) ext
;
336 *spi
= ntohl(sa
->sadb_sa_spi
);
341 explicit_bzero(data
, len
);
347 pfkey_sa_add(int af
, union ldpd_addr
*src
, union ldpd_addr
*dst
, uint8_t keylen
,
348 char *key
, uint32_t *spi
)
350 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_GETSPI
, 0,
351 af
, src
, dst
, 0, 0, 0, NULL
, 0, 0, NULL
, 0, 0) < 0)
353 if (pfkey_reply(fd
, spi
) < 0)
355 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_UPDATE
, 0,
356 af
, src
, dst
, *spi
, 0, keylen
, key
, 0, 0, NULL
, 0, 0) < 0)
358 if (pfkey_reply(fd
, NULL
) < 0)
364 pfkey_sa_remove(int af
, union ldpd_addr
*src
, union ldpd_addr
*dst
,
367 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_DELETE
, 0,
368 af
, src
, dst
, *spi
, 0, 0, NULL
, 0, 0, NULL
, 0, 0) < 0)
370 if (pfkey_reply(fd
, NULL
) < 0)
377 pfkey_md5sig_establish(struct nbr
*nbr
, struct nbr_params
*nbrp
)
381 if (!nbr
->auth
.spi_out
)
382 if (pfkey_sa_add(nbr
->af
, &nbr
->laddr
, &nbr
->raddr
,
383 nbrp
->auth
.md5key_len
, nbrp
->auth
.md5key
,
384 &nbr
->auth
.spi_out
) == -1)
386 if (!nbr
->auth
.spi_in
)
387 if (pfkey_sa_add(nbr
->af
, &nbr
->raddr
, &nbr
->laddr
,
388 nbrp
->auth
.md5key_len
, nbrp
->auth
.md5key
,
389 &nbr
->auth
.spi_in
) == -1)
392 nbr
->auth
.established
= 1;
397 pfkey_md5sig_remove(struct nbr
*nbr
)
399 if (nbr
->auth
.spi_out
)
400 if (pfkey_sa_remove(nbr
->af
, &nbr
->laddr
, &nbr
->raddr
,
401 &nbr
->auth
.spi_out
) == -1)
403 if (nbr
->auth
.spi_in
)
404 if (pfkey_sa_remove(nbr
->af
, &nbr
->raddr
, &nbr
->laddr
,
405 &nbr
->auth
.spi_in
) == -1)
408 nbr
->auth
.established
= 0;
409 nbr
->auth
.spi_in
= 0;
410 nbr
->auth
.spi_out
= 0;
411 nbr
->auth
.method
= AUTH_NONE
;
412 memset(nbr
->auth
.md5key
, 0, sizeof(nbr
->auth
.md5key
));
418 pfkey_establish(struct nbr
*nbr
, struct nbr_params
*nbrp
)
420 if (nbrp
->auth
.method
== AUTH_NONE
)
423 switch (nbr
->auth
.method
) {
425 strlcpy(nbr
->auth
.md5key
, nbrp
->auth
.md5key
,
426 sizeof(nbr
->auth
.md5key
));
427 return (pfkey_md5sig_establish(nbr
, nbrp
));
436 pfkey_remove(struct nbr
*nbr
)
438 if (nbr
->auth
.method
== AUTH_NONE
|| !nbr
->auth
.established
)
441 switch (nbr
->auth
.method
) {
443 return (pfkey_md5sig_remove(nbr
));
454 if ((fd
= socket(PF_KEY
, SOCK_RAW
| SOCK_CLOEXEC
| SOCK_NONBLOCK
,
456 if (errno
== EPROTONOSUPPORT
) {
457 log_warnx("PF_KEY not available");
461 fatal("pfkey setup failed");
465 #endif /* __OpenBSD__ */