xref: /openbsd-src/sbin/isakmpd/udp_encap.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: udp_encap.c,v 1.21 2007/04/16 13:01:39 moritz Exp $	*/
2 
3 /*
4  * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist.  All rights reserved.
5  * Copyright (c) 2000 Angelos D. Keromytis.  All rights reserved.
6  * Copyright (c) 2004 H�kan Olsson.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/types.h>
30 #include <sys/ioctl.h>
31 #include <sys/socket.h>
32 #include <sys/sockio.h>
33 #include <net/if.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <ctype.h>
37 #include <limits.h>
38 #include <netdb.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 
43 #include "sysdep.h"
44 
45 #include "conf.h"
46 #include "if.h"
47 #include "ipsec_doi.h"
48 #include "isakmp.h"
49 #include "log.h"
50 #include "message.h"
51 #include "monitor.h"
52 #include "transport.h"
53 #include "udp.h"
54 #include "udp_encap.h"
55 #include "util.h"
56 #include "virtual.h"
57 
58 #define UDP_SIZE 65536
59 
60 /* If a system doesn't have SO_REUSEPORT, SO_REUSEADDR will have to do.  */
61 #ifndef SO_REUSEPORT
62 #define SO_REUSEPORT SO_REUSEADDR
63 #endif
64 
65 /* Reused, from udp.c */
66 struct transport *udp_clone(struct transport *, struct sockaddr *);
67 int		  udp_fd_set(struct transport *, fd_set *, int);
68 int		  udp_fd_isset(struct transport *, fd_set *);
69 void		  udp_get_dst(struct transport *, struct sockaddr **);
70 void		  udp_get_src(struct transport *, struct sockaddr **);
71 char		 *udp_decode_ids(struct transport *);
72 void		  udp_remove(struct transport *);
73 
74 static struct transport *udp_encap_create(char *);
75 static void		 udp_encap_report(struct transport *);
76 static void		 udp_encap_handle_message(struct transport *);
77 static struct transport *udp_encap_make(struct sockaddr *);
78 static int		 udp_encap_send_message(struct message *,
79     struct transport *);
80 
81 static struct transport_vtbl udp_encap_transport_vtbl = {
82 	{ 0 }, "udp_encap",
83 	udp_encap_create,
84 	0,
85 	udp_remove,
86 	udp_encap_report,
87 	udp_fd_set,
88 	udp_fd_isset,
89 	udp_encap_handle_message,
90 	udp_encap_send_message,
91 	udp_get_dst,
92 	udp_get_src,
93 	udp_decode_ids,
94 	udp_clone,
95 	0
96 };
97 
98 char	 *udp_encap_default_port = 0;
99 
100 void
101 udp_encap_init(void)
102 {
103 	transport_method_add(&udp_encap_transport_vtbl);
104 }
105 
106 /* Create a UDP transport structure bound to LADDR just for listening.  */
107 static struct transport *
108 udp_encap_make(struct sockaddr *laddr)
109 {
110 	struct udp_transport *t = 0;
111 	int	 s, on, wildcardaddress = 0;
112 	char	*tstr;
113 
114 	t = calloc(1, sizeof *t);
115 	if (!t) {
116 		log_print("udp_encap_make: malloc (%lu) failed",
117 		    (unsigned long)sizeof *t);
118 		free(laddr);
119 		return 0;
120 	}
121 	t->src = laddr;
122 
123 	s = socket(laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
124 	if (s == -1) {
125 		log_error("udp_encap_make: socket (%d, %d, %d)",
126 		    laddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
127 		goto err;
128 	}
129 
130 	/* Make sure we don't get our traffic encrypted.  */
131 	if (sysdep_cleartext(s, laddr->sa_family) == -1)
132 		goto err;
133 
134 	/* Wildcard address ?  */
135 	switch (laddr->sa_family) {
136 	case AF_INET:
137 		if (((struct sockaddr_in *)laddr)->sin_addr.s_addr
138 		    == INADDR_ANY)
139 			wildcardaddress = 1;
140 		break;
141 	case AF_INET6:
142 		if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)laddr)->sin6_addr))
143 			wildcardaddress = 1;
144 		break;
145 	}
146 
147 	/*
148 	 * In order to have several bound specific address-port combinations
149 	 * with the same port SO_REUSEADDR is needed.
150 	 * If this is a wildcard socket and we are not listening there, but
151 	 * only sending from it make sure it is entirely reuseable with
152 	 * SO_REUSEPORT.
153 	 */
154 	on = 1;
155 	if (setsockopt(s, SOL_SOCKET,
156 	    wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR,
157 	    (void *)&on, sizeof on) == -1) {
158 		log_error("udp_encap_make: setsockopt (%d, %d, %d, %p, %lu)",
159 		    s, SOL_SOCKET,
160 		    wildcardaddress ? SO_REUSEPORT : SO_REUSEADDR, &on,
161 		    (unsigned long)sizeof on);
162 		goto err;
163 	}
164 
165 	t->transport.vtbl = &udp_encap_transport_vtbl;
166 	if (monitor_bind(s, t->src, SA_LEN(t->src))) {
167 		if (sockaddr2text(t->src, &tstr, 0))
168 			log_error("udp_encap_make: bind (%d, %p, %lu)", s,
169 			    &t->src, (unsigned long)sizeof t->src);
170 		else {
171 			log_error("udp_encap_make: bind (%d, %s, %lu)", s,
172 			    tstr, (unsigned long)sizeof t->src);
173 			free(tstr);
174 		}
175 		goto err;
176 	}
177 
178 	t->s = s;
179 	if (sockaddr2text(t->src, &tstr, 0))
180 		LOG_DBG((LOG_MISC, 20, "udp_encap_make: "
181 		    "transport %p socket %d family %d", t, s,
182 		    t->src->sa_family == AF_INET ? 4 : 6));
183 	else {
184 		LOG_DBG((LOG_MISC, 20, "udp_encap_make: "
185 		    "transport %p socket %d ip %s port %d", t, s,
186 		    tstr, ntohs(sockaddr_port(t->src))));
187 		free(tstr);
188 	}
189 	transport_setup(&t->transport, 0);
190 	t->transport.flags |= TRANSPORT_LISTEN;
191 	return &t->transport;
192 
193 err:
194 	if (s >= 0)
195 		close (s);
196 	if (t) {
197 		/* Already closed.  */
198 		t->s = -1;
199 		udp_remove(&t->transport);
200 	}
201 	return 0;
202 }
203 
204 /*
205  * Initialize an object of the UDP transport class.  Fill in the local
206  * IP address and port information and create a server socket bound to
207  * that specific port.  Add the polymorphic transport structure to the
208  * system-wide pools of known ISAKMP transports.
209  */
210 struct transport *
211 udp_encap_bind(const struct sockaddr *addr)
212 {
213 	struct sockaddr	*src;
214 
215 	src = malloc(SA_LEN(addr));
216 	if (!src)
217 		return 0;
218 
219 	memcpy(src, addr, SA_LEN(addr));
220 	return udp_encap_make(src);
221 }
222 
223 /*
224  * NAME is a section name found in the config database.  Setup and return
225  * a transport useable to talk to the peer specified by that name.
226  */
227 static struct transport *
228 udp_encap_create(char *name)
229 {
230 	struct virtual_transport *v;
231 	struct udp_transport	*u;
232 	struct transport	*rv, *t;
233 	struct sockaddr		*dst, *addr;
234 	struct conf_list	*addr_list = 0;
235 	struct conf_list_node	*addr_node;
236 	char	*addr_str, *port_str;
237 
238 	port_str = conf_get_str(name, "Port"); /* XXX "Encap-port" ? */
239 	if (!port_str)
240 		port_str = udp_encap_default_port;
241 	if (!port_str)
242 		port_str = UDP_ENCAP_DEFAULT_PORT_STR;
243 
244 	addr_str = conf_get_str(name, "Address");
245 	if (!addr_str) {
246 		log_print("udp_encap_create: no address configured "
247 		    "for \"%s\"", name);
248 		return 0;
249 	}
250 	if (text2sockaddr(addr_str, port_str, &dst, 0, 0)) {
251 		log_print("udp_encap_create: address \"%s\" not understood",
252 		    addr_str);
253 		return 0;
254 	}
255 
256 	addr_str = conf_get_str(name, "Local-address");
257 	if (!addr_str)
258 		addr_list = conf_get_list("General", "Listen-on");
259 	if (!addr_str && !addr_list) {
260 		v = virtual_get_default(dst->sa_family);
261 		u = (struct udp_transport *)v->encap;
262 
263 		if (!u) {
264 			log_print("udp_encap_create: no default transport");
265 			rv = 0;
266 			goto ret;
267 		} else {
268 			rv = udp_clone((struct transport *)u, dst);
269 			if (rv)
270 				rv->vtbl = &udp_encap_transport_vtbl;
271 			goto ret;
272 		}
273 	}
274 
275 	if (addr_list) {
276 		for (addr_node = TAILQ_FIRST(&addr_list->fields);
277 		    addr_node; addr_node = TAILQ_NEXT(addr_node, link))
278 			if (text2sockaddr(addr_node->field, port_str,
279 			    &addr, 0, 0) == 0) {
280 				v = virtual_listen_lookup(addr);
281 				free(addr);
282 				if (v) {
283 					addr_str = addr_node->field;
284 					break;
285 				}
286 			}
287 		if (!addr_str) {
288 			log_print("udp_encap_create: "
289 			    "no matching listener found");
290 			rv = 0;
291 			goto ret;
292 		}
293 	}
294 	if (text2sockaddr(addr_str, port_str, &addr, 0, 0)) {
295 		log_print("udp_encap_create: "
296 		    "address \"%s\" not understood", addr_str);
297 		rv = 0;
298 		goto ret;
299 	}
300 	v = virtual_listen_lookup(addr);
301 	free(addr);
302 	if (!v) {
303 		log_print("udp_encap_create: "
304 		    "%s:%s must exist as a listener too", addr_str, port_str);
305 		rv = 0;
306 		goto ret;
307 	}
308 	t = (struct transport *)v;
309 	rv = udp_clone(v->encap, dst);
310 	if (rv)
311 		rv->vtbl = &udp_encap_transport_vtbl;
312 
313 ret:
314 	if (addr_list)
315 		conf_free_list(addr_list);
316 	free(dst);
317 	return rv;
318 }
319 
320 /* Report transport-method specifics of the T transport.  */
321 void
322 udp_encap_report(struct transport *t)
323 {
324 	struct udp_transport *u = (struct udp_transport *)t;
325 	char	 *src = NULL, *dst = NULL;
326 	in_port_t sport, dport;
327 
328 	if (sockaddr2text(u->src, &src, 0))
329 		return;
330 	sport = sockaddr_port(u->src);
331 
332 	if (!u->dst || sockaddr2text(u->dst, &dst, 0))
333 		dst = 0;
334 	dport = dst ? sockaddr_port(u->dst) : 0;
335 
336 	LOG_DBG ((LOG_REPORT, 0, "udp_encap_report: fd %d src %s:%u dst %s:%u",
337 	    u->s, src, ntohs(sport), dst ? dst : "*", ntohs(dport)));
338 
339 	free(dst);
340 	free(src);
341 }
342 
343 /*
344  * A message has arrived on transport T's socket.  If T is single-ended,
345  * clone it into a double-ended transport which we will use from now on.
346  * Package the message as we want it and continue processing in the message
347  * module.
348  */
349 static void
350 udp_encap_handle_message(struct transport *t)
351 {
352 	struct udp_transport	*u = (struct udp_transport *)t;
353 	struct sockaddr_storage	 from;
354 	struct message		*msg;
355 	u_int32_t	len = sizeof from;
356 	ssize_t		n;
357 	u_int8_t	buf[UDP_SIZE];
358 
359 	n = recvfrom(u->s, buf, UDP_SIZE, 0, (struct sockaddr *)&from, &len);
360 	if (n == -1) {
361 		log_error("recvfrom (%d, %p, %d, %d, %p, %p)", u->s, buf,
362 		    UDP_SIZE, 0, &from, &len);
363 		return;
364 	}
365 
366 	if (t->virtual == (struct transport *)virtual_get_default(AF_INET) ||
367 	    t->virtual == (struct transport *)virtual_get_default(AF_INET6)) {
368 		t->virtual->vtbl->reinit();
369 
370 		/*
371 		 * As we don't know the actual destination address of the
372 		 * packet, we can't really deal with it. So, just ignore it
373 		 * and hope we catch the retransmission.
374 		 */
375 		return;
376 	}
377 
378 	/*
379 	 * Make a specialized UDP transport structure out of the incoming
380 	 * transport and the address information we got from recvfrom(2).
381 	 */
382 	t = t->virtual->vtbl->clone(t->virtual, (struct sockaddr *)&from);
383 	if (!t)
384 		return;
385 
386 	/* Check NULL-ESP marker.  */
387 	if (n < (ssize_t)sizeof(u_int32_t) || *(u_int32_t *)buf != 0) {
388 		/* Should never happen.  */
389 		log_print("udp_encap_handle_message: "
390 		    "Null-ESP marker not NULL or short message");
391 		return;
392 	}
393 
394 	/* NAT-Keepalive messages should not be processed further.  */
395 	n -= sizeof(u_int32_t);
396 	if (n == 1 && buf[sizeof(u_int32_t)] == 0xFF)
397 		return;
398 
399 	msg = message_alloc(t, buf + sizeof (u_int32_t), n);
400 	if (!msg) {
401 		log_error("failed to allocate message structure, dropping "
402 		    "packet received on transport %p", u);
403 		return;
404 	}
405 
406 	msg->flags |= MSG_NATT;
407 
408 	message_recv(msg);
409 }
410 
411 /*
412  * Physically send the message MSG over its associated transport.
413  * Special: if 'msg' is NULL, send a NAT-T keepalive message.
414  */
415 static int
416 udp_encap_send_message(struct message *msg, struct transport *t)
417 {
418 	struct udp_transport *u = (struct udp_transport *)t;
419 	struct msghdr	 m;
420 	struct iovec	*new_iov = 0, keepalive;
421 	ssize_t		 n;
422 	u_int32_t	 marker = 0;			/* NULL-ESP Marker */
423 
424 	if (msg) {
425 		/* Construct new iov array, prefixing NULL-ESP Marker.  */
426 		new_iov = (struct iovec *)calloc (msg->iovlen + 1,
427 		    sizeof *new_iov);
428 		if (!new_iov) {
429 			log_error ("udp_encap_send_message: "
430 			    "calloc (%lu, %lu) failed",
431 			    (unsigned long)msg->iovlen + 1,
432 			    (unsigned long)sizeof *new_iov);
433 			return -1;
434 		}
435 		new_iov[0].iov_base = &marker;
436 		new_iov[0].iov_len = IPSEC_SPI_SIZE;
437 		memcpy (new_iov + 1, msg->iov, msg->iovlen * sizeof *new_iov);
438 	} else {
439 		marker = ~marker;
440 		keepalive.iov_base = &marker;
441 		keepalive.iov_len = 1;
442 	}
443 
444 	/*
445 	 * Sending on connected sockets requires that no destination address is
446 	 * given, or else EISCONN will occur.
447 	 */
448 	m.msg_name = (caddr_t)u->dst;
449 	m.msg_namelen = SA_LEN(u->dst);
450 	m.msg_iov = msg ? new_iov : &keepalive;
451 	m.msg_iovlen = msg ? msg->iovlen + 1 : 1;
452 	m.msg_control = 0;
453 	m.msg_controllen = 0;
454 	m.msg_flags = 0;
455 	n = sendmsg (u->s, &m, 0);
456 	if (msg)
457 		free (new_iov);
458 	if (n == -1) {
459 		/* XXX We should check whether the address has gone away */
460 		log_error ("sendmsg (%d, %p, %d)", u->s, &m, 0);
461 		return -1;
462 	}
463 	return 0;
464 }
465