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 ssrc
, sdst
, smask
, dmask
;
68 struct sockaddr
*saptr
;
73 /* we need clean sockaddr... no ports set */
74 memset(&ssrc
, 0, sizeof(ssrc
));
75 memset(&smask
, 0, sizeof(smask
));
76 if ((saptr
= addr2sa(af
, src
, 0)))
77 memcpy(&ssrc
, saptr
, sizeof(ssrc
));
80 memset(&((struct sockaddr_in
*)&smask
)->sin_addr
, 0xff, 32/8);
83 memset(&((struct sockaddr_in6
*)&smask
)->sin6_addr
, 0xff,
89 smask
.ss_family
= ssrc
.ss_family
;
90 smask
.ss_len
= ssrc
.ss_len
;
92 memset(&sdst
, 0, sizeof(sdst
));
93 memset(&dmask
, 0, sizeof(dmask
));
94 if ((saptr
= addr2sa(af
, dst
, 0)))
95 memcpy(&sdst
, saptr
, sizeof(sdst
));
98 memset(&((struct sockaddr_in
*)&dmask
)->sin_addr
, 0xff, 32/8);
101 memset(&((struct sockaddr_in6
*)&dmask
)->sin6_addr
, 0xff,
107 dmask
.ss_family
= sdst
.ss_family
;
108 dmask
.ss_len
= sdst
.ss_len
;
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
= (sizeof(sa_src
) + ROUNDUP(ssrc
.ss_len
)) / 8;
143 memset(&sa_dst
, 0, sizeof(sa_dst
));
144 sa_dst
.sadb_address_exttype
= SADB_EXT_ADDRESS_DST
;
145 sa_dst
.sadb_address_len
= (sizeof(sa_dst
) + ROUNDUP(sdst
.ss_len
)) / 8;
147 sa
.sadb_sa_auth
= aalg
;
148 sa
.sadb_sa_encrypt
= SADB_X_EALG_AES
; /* XXX */
153 memset(&sa_akey
, 0, sizeof(sa_akey
));
154 sa_akey
.sadb_key_exttype
= SADB_EXT_KEY_AUTH
;
155 sa_akey
.sadb_key_len
= (sizeof(sa_akey
) +
156 ((alen
+ 7) / 8) * 8) / 8;
157 sa_akey
.sadb_key_bits
= 8 * alen
;
159 memset(&sa_ekey
, 0, sizeof(sa_ekey
));
160 sa_ekey
.sadb_key_exttype
= SADB_EXT_KEY_ENCRYPT
;
161 sa_ekey
.sadb_key_len
= (sizeof(sa_ekey
) +
162 ((elen
+ 7) / 8) * 8) / 8;
163 sa_ekey
.sadb_key_bits
= 8 * elen
;
171 iov
[iov_cnt
].iov_base
= &smsg
;
172 iov
[iov_cnt
].iov_len
= sizeof(smsg
);
180 iov
[iov_cnt
].iov_base
= &sa
;
181 iov
[iov_cnt
].iov_len
= sizeof(sa
);
182 smsg
.sadb_msg_len
+= sa
.sadb_sa_len
;
187 iov
[iov_cnt
].iov_base
= &sa_spirange
;
188 iov
[iov_cnt
].iov_len
= sizeof(sa_spirange
);
189 smsg
.sadb_msg_len
+= sa_spirange
.sadb_spirange_len
;
195 iov
[iov_cnt
].iov_base
= &sa_dst
;
196 iov
[iov_cnt
].iov_len
= sizeof(sa_dst
);
198 iov
[iov_cnt
].iov_base
= &sdst
;
199 iov
[iov_cnt
].iov_len
= ROUNDUP(sdst
.ss_len
);
200 smsg
.sadb_msg_len
+= sa_dst
.sadb_address_len
;
204 iov
[iov_cnt
].iov_base
= &sa_src
;
205 iov
[iov_cnt
].iov_len
= sizeof(sa_src
);
207 iov
[iov_cnt
].iov_base
= &ssrc
;
208 iov
[iov_cnt
].iov_len
= ROUNDUP(ssrc
.ss_len
);
209 smsg
.sadb_msg_len
+= sa_src
.sadb_address_len
;
217 iov
[iov_cnt
].iov_base
= &sa_akey
;
218 iov
[iov_cnt
].iov_len
= sizeof(sa_akey
);
220 iov
[iov_cnt
].iov_base
= akey
;
221 iov
[iov_cnt
].iov_len
= ((alen
+ 7) / 8) * 8;
222 smsg
.sadb_msg_len
+= sa_akey
.sadb_key_len
;
227 iov
[iov_cnt
].iov_base
= &sa_ekey
;
228 iov
[iov_cnt
].iov_len
= sizeof(sa_ekey
);
230 iov
[iov_cnt
].iov_base
= ekey
;
231 iov
[iov_cnt
].iov_len
= ((elen
+ 7) / 8) * 8;
232 smsg
.sadb_msg_len
+= sa_ekey
.sadb_key_len
;
238 len
= smsg
.sadb_msg_len
* 8;
240 n
= writev(sd
, iov
, iov_cnt
);
241 } while (n
== -1 && (errno
== EAGAIN
|| errno
== EINTR
));
244 log_warn("writev (%d/%d)", iov_cnt
, len
);
252 pfkey_read(int sd
, struct sadb_msg
*h
)
256 if (recv(sd
, &hdr
, sizeof(hdr
), MSG_PEEK
) != sizeof(hdr
)) {
257 if (errno
== EAGAIN
|| errno
== EINTR
)
259 log_warn("pfkey peek");
263 /* XXX: Only one message can be outstanding. */
264 if (hdr
.sadb_msg_seq
== sadb_msg_seq
&&
265 hdr
.sadb_msg_pid
== pid
) {
271 /* not ours, discard */
272 if (read(sd
, &hdr
, sizeof(hdr
)) == -1) {
273 if (errno
== EAGAIN
|| errno
== EINTR
)
275 log_warn("pfkey read");
283 pfkey_reply(int sd
, uint32_t *spi
)
285 struct sadb_msg hdr
, *msg
;
286 struct sadb_ext
*ext
;
293 rv
= pfkey_read(sd
, &hdr
);
298 if (hdr
.sadb_msg_errno
!= 0) {
299 errno
= hdr
.sadb_msg_errno
;
307 if ((data
= reallocarray(NULL
, hdr
.sadb_msg_len
, PFKEY2_CHUNK
)) == NULL
) {
308 log_warn("pfkey malloc");
311 len
= hdr
.sadb_msg_len
* PFKEY2_CHUNK
;
312 if (read(sd
, data
, len
) != len
) {
313 log_warn("pfkey read");
314 explicit_bzero(data
, len
);
319 if (hdr
.sadb_msg_type
== SADB_GETSPI
) {
321 explicit_bzero(data
, len
);
326 msg
= (struct sadb_msg
*)data
;
327 for (ext
= (struct sadb_ext
*)(msg
+ 1);
328 (size_t)((uint8_t *)ext
- (uint8_t *)msg
) <
329 msg
->sadb_msg_len
* PFKEY2_CHUNK
;
330 ext
= (struct sadb_ext
*)((uint8_t *)ext
+
331 ext
->sadb_ext_len
* PFKEY2_CHUNK
)) {
332 if (ext
->sadb_ext_type
== SADB_EXT_SA
) {
333 sa
= (struct sadb_sa
*) ext
;
334 *spi
= ntohl(sa
->sadb_sa_spi
);
339 explicit_bzero(data
, len
);
345 pfkey_sa_add(int af
, union ldpd_addr
*src
, union ldpd_addr
*dst
, uint8_t keylen
,
346 char *key
, uint32_t *spi
)
348 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_GETSPI
, 0,
349 af
, src
, dst
, 0, 0, 0, NULL
, 0, 0, NULL
, 0, 0) < 0)
351 if (pfkey_reply(fd
, spi
) < 0)
353 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_UPDATE
, 0,
354 af
, src
, dst
, *spi
, 0, keylen
, key
, 0, 0, NULL
, 0, 0) < 0)
356 if (pfkey_reply(fd
, NULL
) < 0)
362 pfkey_sa_remove(int af
, union ldpd_addr
*src
, union ldpd_addr
*dst
,
365 if (pfkey_send(fd
, SADB_X_SATYPE_TCPSIGNATURE
, SADB_DELETE
, 0,
366 af
, src
, dst
, *spi
, 0, 0, NULL
, 0, 0, NULL
, 0, 0) < 0)
368 if (pfkey_reply(fd
, NULL
) < 0)
375 pfkey_md5sig_establish(struct nbr
*nbr
, struct nbr_params
*nbrp
)
379 if (!nbr
->auth
.spi_out
)
380 if (pfkey_sa_add(nbr
->af
, &nbr
->laddr
, &nbr
->raddr
,
381 nbrp
->auth
.md5key_len
, nbrp
->auth
.md5key
,
382 &nbr
->auth
.spi_out
) == -1)
384 if (!nbr
->auth
.spi_in
)
385 if (pfkey_sa_add(nbr
->af
, &nbr
->raddr
, &nbr
->laddr
,
386 nbrp
->auth
.md5key_len
, nbrp
->auth
.md5key
,
387 &nbr
->auth
.spi_in
) == -1)
390 nbr
->auth
.established
= 1;
395 pfkey_md5sig_remove(struct nbr
*nbr
)
397 if (nbr
->auth
.spi_out
)
398 if (pfkey_sa_remove(nbr
->af
, &nbr
->laddr
, &nbr
->raddr
,
399 &nbr
->auth
.spi_out
) == -1)
401 if (nbr
->auth
.spi_in
)
402 if (pfkey_sa_remove(nbr
->af
, &nbr
->raddr
, &nbr
->laddr
,
403 &nbr
->auth
.spi_in
) == -1)
406 nbr
->auth
.established
= 0;
407 nbr
->auth
.spi_in
= 0;
408 nbr
->auth
.spi_out
= 0;
409 nbr
->auth
.method
= AUTH_NONE
;
410 memset(nbr
->auth
.md5key
, 0, sizeof(nbr
->auth
.md5key
));
416 pfkey_establish(struct nbr
*nbr
, struct nbr_params
*nbrp
)
418 if (nbrp
->auth
.method
== AUTH_NONE
)
421 switch (nbr
->auth
.method
) {
423 strlcpy(nbr
->auth
.md5key
, nbrp
->auth
.md5key
,
424 sizeof(nbr
->auth
.md5key
));
425 return (pfkey_md5sig_establish(nbr
, nbrp
));
434 pfkey_remove(struct nbr
*nbr
)
436 if (nbr
->auth
.method
== AUTH_NONE
|| !nbr
->auth
.established
)
439 switch (nbr
->auth
.method
) {
441 return (pfkey_md5sig_remove(nbr
));
452 if ((fd
= socket(PF_KEY
, SOCK_RAW
| SOCK_CLOEXEC
| SOCK_NONBLOCK
,
454 if (errno
== EPROTONOSUPPORT
) {
455 log_warnx("PF_KEY not available");
459 fatal("pfkey setup failed");
463 #endif /* __OpenBSD__ */