]> git.ipfire.org Git - thirdparty/openvpn.git/blob - src/openvpn/mudp.c
Fix various 'Uninitialized scalar variable' warnings from Coverity
[thirdparty/openvpn.git] / src / openvpn / mudp.c
1 /*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2023 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "syshead.h"
29
30 #include "multi.h"
31 #include <inttypes.h>
32 #include "forward.h"
33
34 #include "memdbg.h"
35 #include "ssl_pkt.h"
36
37 #ifdef HAVE_SYS_INOTIFY_H
38 #include <sys/inotify.h>
39 #endif
40
41 static void
42 send_hmac_reset_packet(struct multi_context *m,
43 struct tls_pre_decrypt_state *state,
44 struct tls_auth_standalone *tas,
45 struct session_id *sid,
46 bool request_resend_wkc)
47 {
48 reset_packet_id_send(&state->tls_wrap_tmp.opt.packet_id.send);
49 state->tls_wrap_tmp.opt.packet_id.rec.initialized = true;
50 uint8_t header = 0 | (P_CONTROL_HARD_RESET_SERVER_V2 << P_OPCODE_SHIFT);
51 struct buffer buf = tls_reset_standalone(&state->tls_wrap_tmp, tas, sid,
52 &state->peer_session_id, header,
53 request_resend_wkc);
54
55 struct context *c = &m->top;
56
57 buf_reset_len(&c->c2.buffers->aux_buf);
58 buf_copy(&c->c2.buffers->aux_buf, &buf);
59 m->hmac_reply = c->c2.buffers->aux_buf;
60 m->hmac_reply_dest = &m->top.c2.from;
61 msg(D_MULTI_DEBUG, "Reset packet from client, sending HMAC based reset challenge");
62 }
63
64
65 /* Returns true if this packet should create a new session */
66 static bool
67 do_pre_decrypt_check(struct multi_context *m,
68 struct tls_pre_decrypt_state *state,
69 struct mroute_addr addr)
70 {
71 ASSERT(m->top.c2.tls_auth_standalone);
72
73 enum first_packet_verdict verdict;
74
75 struct tls_auth_standalone *tas = m->top.c2.tls_auth_standalone;
76
77 verdict = tls_pre_decrypt_lite(tas, state, &m->top.c2.from, &m->top.c2.buf);
78
79 hmac_ctx_t *hmac = m->top.c2.session_id_hmac;
80 struct openvpn_sockaddr *from = &m->top.c2.from.dest;
81 int handwindow = m->top.options.handshake_window;
82
83 if (verdict == VERDICT_VALID_RESET_V3 || verdict == VERDICT_VALID_RESET_V2)
84 {
85 /* Check if we are still below our limit for sending out
86 * responses */
87 if (!reflect_filter_rate_limit_check(m->initial_rate_limiter))
88 {
89 return false;
90 }
91 }
92
93 if (verdict == VERDICT_VALID_RESET_V3)
94 {
95 /* Extract the packet id to check if it has the special format that
96 * indicates early negotiation support */
97 struct packet_id_net pin;
98 struct buffer tmp = m->top.c2.buf;
99 ASSERT(buf_advance(&tmp, 1 + SID_SIZE));
100 ASSERT(packet_id_read(&pin, &tmp, true));
101
102 /* The most significant byte is 0x0f if early negotiation is supported */
103 bool early_neg_support = ((pin.id & EARLY_NEG_MASK) & EARLY_NEG_START) == EARLY_NEG_START;
104
105 /* All clients that support early negotiation and tls-crypt are assumed
106 * to also support resending the WKc in the 2nd packet */
107 if (early_neg_support)
108 {
109 /* Calculate the session ID HMAC for our reply and create reset packet */
110 struct session_id sid = calculate_session_id_hmac(state->peer_session_id,
111 from, hmac, handwindow, 0);
112 send_hmac_reset_packet(m, state, tas, &sid, true);
113
114 return false;
115 }
116 else
117 {
118 /* For tls-crypt-v2 we need to keep the state of the first packet
119 * to store the unwrapped key if the client doesn't support resending
120 * the wrapped key. Unless the user specifically disallowed
121 * compatibility with such clients to avoid state exhaustion */
122 if (tas->tls_wrap.opt.flags & CO_FORCE_TLSCRYPTV2_COOKIE)
123 {
124 struct gc_arena gc = gc_new();
125 const char *peer = print_link_socket_actual(&m->top.c2.from, &gc);
126 msg(D_MULTI_DEBUG, "tls-crypt-v2 force-cookie is enabled, "
127 "ignoring connection attempt from old client (%s)", peer);
128 gc_free(&gc);
129 return false;
130 }
131 else
132 {
133 return true;
134 }
135 }
136 }
137 else if (verdict == VERDICT_VALID_RESET_V2)
138 {
139 /* Calculate the session ID HMAC for our reply and create reset packet */
140 struct session_id sid = calculate_session_id_hmac(state->peer_session_id,
141 from, hmac, handwindow, 0);
142
143 send_hmac_reset_packet(m, state, tas, &sid, false);
144
145 /* We have a reply do not create a new session */
146 return false;
147
148 }
149 else if (verdict == VERDICT_VALID_CONTROL_V1 || verdict == VERDICT_VALID_ACK_V1
150 || verdict == VERDICT_VALID_WKC_V1)
151 {
152 /* ACK_V1 contains the peer id (our id) while CONTROL_V1 can but does not
153 * need to contain the peer id */
154 struct gc_arena gc = gc_new();
155
156 bool ret = check_session_id_hmac(state, from, hmac, handwindow);
157
158 const char *peer = print_link_socket_actual(&m->top.c2.from, &gc);
159 uint8_t pkt_firstbyte = *BPTR( &m->top.c2.buf);
160 int op = pkt_firstbyte >> P_OPCODE_SHIFT;
161
162 if (!ret)
163 {
164 msg(D_MULTI_MEDIUM, "Packet (%s) with invalid or missing SID from %s",
165 packet_opcode_name(op), peer);
166 }
167 else
168 {
169 msg(D_MULTI_DEBUG, "Valid packet (%s) with HMAC challenge from peer (%s), "
170 "accepting new connection.", packet_opcode_name(op), peer);
171 }
172 gc_free(&gc);
173
174 return ret;
175 }
176
177 /* VERDICT_INVALID */
178 return false;
179 }
180
181 /*
182 * Get a client instance based on real address. If
183 * the instance doesn't exist, create it while
184 * maintaining real address hash table atomicity.
185 */
186
187 struct multi_instance *
188 multi_get_create_instance_udp(struct multi_context *m, bool *floated)
189 {
190 struct gc_arena gc = gc_new();
191 struct mroute_addr real = {0};
192 struct multi_instance *mi = NULL;
193 struct hash *hash = m->hash;
194
195 if (mroute_extract_openvpn_sockaddr(&real, &m->top.c2.from.dest, true)
196 && m->top.c2.buf.len > 0)
197 {
198 struct hash_element *he;
199 const uint32_t hv = hash_value(hash, &real);
200 struct hash_bucket *bucket = hash_bucket(hash, hv);
201 uint8_t *ptr = BPTR(&m->top.c2.buf);
202 uint8_t op = ptr[0] >> P_OPCODE_SHIFT;
203 bool v2 = (op == P_DATA_V2) && (m->top.c2.buf.len >= (1 + 3));
204 bool peer_id_disabled = false;
205
206 /* make sure buffer has enough length to read opcode (1 byte) and peer-id (3 bytes) */
207 if (v2)
208 {
209 uint32_t peer_id = ntohl(*(uint32_t *)ptr) & 0xFFFFFF;
210 peer_id_disabled = (peer_id == MAX_PEER_ID);
211
212 if (!peer_id_disabled && (peer_id < m->max_clients) && (m->instances[peer_id]))
213 {
214 mi = m->instances[peer_id];
215
216 *floated = !link_socket_actual_match(&mi->context.c2.from, &m->top.c2.from);
217
218 if (*floated)
219 {
220 /* reset prefix, since here we are not sure peer is the one it claims to be */
221 ungenerate_prefix(mi);
222 msg(D_MULTI_MEDIUM, "Float requested for peer %" PRIu32 " to %s", peer_id,
223 mroute_addr_print(&real, &gc));
224 }
225 }
226 }
227 if (!v2 || peer_id_disabled)
228 {
229 he = hash_lookup_fast(hash, bucket, &real, hv);
230 if (he)
231 {
232 mi = (struct multi_instance *) he->value;
233 }
234 }
235
236 /* we have no existing multi instance for this connection */
237 if (!mi)
238 {
239 struct tls_pre_decrypt_state state = {0};
240 if (m->deferred_shutdown_signal.signal_received)
241 {
242 msg(D_MULTI_ERRORS,
243 "MULTI: Connection attempt from %s ignored while server is "
244 "shutting down", mroute_addr_print(&real, &gc));
245 }
246 else if (do_pre_decrypt_check(m, &state, real))
247 {
248 /* This is an unknown session but with valid tls-auth/tls-crypt
249 * (or no auth at all). If this is the initial packet of a
250 * session, we just send a reply with a HMAC session id and
251 * do not generate a session slot */
252
253 if (frequency_limit_event_allowed(m->new_connection_limiter))
254 {
255 /* a successful three-way handshake only counts against
256 * connect-freq but not against connect-freq-initial */
257 reflect_filter_rate_limit_decrease(m->initial_rate_limiter);
258
259 mi = multi_create_instance(m, &real);
260 if (mi)
261 {
262 hash_add_fast(hash, bucket, &mi->real, hv, mi);
263 mi->did_real_hash = true;
264 multi_assign_peer_id(m, mi);
265
266 /* If we have a session id already, ensure that the
267 * state is using the same */
268 if (session_id_defined(&state.server_session_id)
269 && session_id_defined((&state.peer_session_id)))
270 {
271 mi->context.c2.tls_multi->n_sessions++;
272 struct tls_session *session = &mi->context.c2.tls_multi->session[TM_INITIAL];
273 session_skip_to_pre_start(session, &state, &m->top.c2.from);
274 }
275 }
276 }
277 else
278 {
279 msg(D_MULTI_ERRORS,
280 "MULTI: Connection from %s would exceed new connection frequency limit as controlled by --connect-freq",
281 mroute_addr_print(&real, &gc));
282 }
283 }
284 free_tls_pre_decrypt_state(&state);
285 }
286
287 #ifdef ENABLE_DEBUG
288 if (check_debug_level(D_MULTI_DEBUG))
289 {
290 const char *status = mi ? "[ok]" : "[failed]";
291
292 dmsg(D_MULTI_DEBUG, "GET INST BY REAL: %s %s",
293 mroute_addr_print(&real, &gc),
294 status);
295 }
296 #endif
297 }
298
299 gc_free(&gc);
300 ASSERT(!(mi && mi->halt));
301 return mi;
302 }
303
304 /*
305 * Send a packet to UDP socket.
306 */
307 static inline void
308 multi_process_outgoing_link(struct multi_context *m, const unsigned int mpp_flags)
309 {
310 struct multi_instance *mi = multi_process_outgoing_link_pre(m);
311 if (mi)
312 {
313 multi_process_outgoing_link_dowork(m, mi, mpp_flags);
314 }
315 if (m->hmac_reply_dest && m->hmac_reply.len > 0)
316 {
317 msg_set_prefix("Connection Attempt");
318 m->top.c2.to_link = m->hmac_reply;
319 m->top.c2.to_link_addr = m->hmac_reply_dest;
320 process_outgoing_link(&m->top);
321 m->hmac_reply_dest = NULL;
322 }
323 }
324
325 /*
326 * Process an I/O event.
327 */
328 static void
329 multi_process_io_udp(struct multi_context *m)
330 {
331 const unsigned int status = m->top.c2.event_set_status;
332 const unsigned int mpp_flags = m->top.c2.fast_io
333 ? (MPP_CONDITIONAL_PRE_SELECT | MPP_CLOSE_ON_SIGNAL)
334 : (MPP_PRE_SELECT | MPP_CLOSE_ON_SIGNAL);
335
336 #ifdef MULTI_DEBUG_EVENT_LOOP
337 char buf[16];
338 buf[0] = 0;
339 if (status & SOCKET_READ)
340 {
341 strcat(buf, "SR/");
342 }
343 else if (status & SOCKET_WRITE)
344 {
345 strcat(buf, "SW/");
346 }
347 else if (status & TUN_READ)
348 {
349 strcat(buf, "TR/");
350 }
351 else if (status & TUN_WRITE)
352 {
353 strcat(buf, "TW/");
354 }
355 else if (status & FILE_CLOSED)
356 {
357 strcat(buf, "FC/");
358 }
359 printf("IO %s\n", buf);
360 #endif /* ifdef MULTI_DEBUG_EVENT_LOOP */
361
362 #ifdef ENABLE_MANAGEMENT
363 if (status & (MANAGEMENT_READ|MANAGEMENT_WRITE))
364 {
365 ASSERT(management);
366 management_io(management);
367 }
368 #endif
369
370 /* UDP port ready to accept write */
371 if (status & SOCKET_WRITE)
372 {
373 multi_process_outgoing_link(m, mpp_flags);
374 }
375 /* TUN device ready to accept write */
376 else if (status & TUN_WRITE)
377 {
378 multi_process_outgoing_tun(m, mpp_flags);
379 }
380 /* Incoming data on UDP port */
381 else if (status & SOCKET_READ)
382 {
383 read_incoming_link(&m->top);
384 if (!IS_SIG(&m->top))
385 {
386 multi_process_incoming_link(m, NULL, mpp_flags);
387 }
388 }
389 /* Incoming data on TUN device */
390 else if (status & TUN_READ)
391 {
392 read_incoming_tun(&m->top);
393 if (!IS_SIG(&m->top))
394 {
395 multi_process_incoming_tun(m, mpp_flags);
396 }
397 }
398 #ifdef ENABLE_ASYNC_PUSH
399 /* INOTIFY callback */
400 else if (status & FILE_CLOSED)
401 {
402 multi_process_file_closed(m, mpp_flags);
403 }
404 #endif
405 #if defined(ENABLE_DCO) && (defined(TARGET_LINUX) || defined(TARGET_FREEBSD))
406 else if (status & DCO_READ)
407 {
408 if (!IS_SIG(&m->top))
409 {
410 bool ret = true;
411 while (ret)
412 {
413 ret = multi_process_incoming_dco(m);
414 }
415 }
416 }
417 #endif
418 }
419
420 /*
421 * Return the io_wait() flags appropriate for
422 * a point-to-multipoint tunnel.
423 */
424 static inline unsigned int
425 p2mp_iow_flags(const struct multi_context *m)
426 {
427 unsigned int flags = IOW_WAIT_SIGNAL;
428 if (m->pending)
429 {
430 if (TUN_OUT(&m->pending->context))
431 {
432 flags |= IOW_TO_TUN;
433 }
434 if (LINK_OUT(&m->pending->context))
435 {
436 flags |= IOW_TO_LINK;
437 }
438 }
439 else if (mbuf_defined(m->mbuf))
440 {
441 flags |= IOW_MBUF;
442 }
443 else if (m->hmac_reply_dest)
444 {
445 flags |= IOW_TO_LINK;
446 }
447 else
448 {
449 flags |= IOW_READ;
450 }
451 #ifdef _WIN32
452 if (tuntap_ring_empty(m->top.c1.tuntap))
453 {
454 flags &= ~IOW_READ_TUN;
455 }
456 #endif
457 return flags;
458 }
459
460
461 void
462 tunnel_server_udp(struct context *top)
463 {
464 struct multi_context multi;
465
466 top->mode = CM_TOP;
467 context_clear_2(top);
468
469 /* initialize top-tunnel instance */
470 init_instance_handle_signals(top, top->es, CC_HARD_USR1_TO_HUP);
471 if (IS_SIG(top))
472 {
473 return;
474 }
475
476 /* initialize global multi_context object */
477 multi_init(&multi, top, false);
478
479 /* initialize our cloned top object */
480 multi_top_init(&multi, top);
481
482 /* initialize management interface */
483 init_management_callback_multi(&multi);
484
485 /* finished with initialization */
486 initialization_sequence_completed(top, ISC_SERVER); /* --mode server --proto udp */
487
488 #ifdef ENABLE_ASYNC_PUSH
489 multi.top.c2.inotify_fd = inotify_init();
490 if (multi.top.c2.inotify_fd < 0)
491 {
492 msg(D_MULTI_ERRORS | M_ERRNO, "MULTI: inotify_init error");
493 }
494 #endif
495
496 /* per-packet event loop */
497 while (true)
498 {
499 perf_push(PERF_EVENT_LOOP);
500
501 /* set up and do the io_wait() */
502 multi_get_timeout(&multi, &multi.top.c2.timeval);
503 io_wait(&multi.top, p2mp_iow_flags(&multi));
504 MULTI_CHECK_SIG(&multi);
505
506 /* check on status of coarse timers */
507 multi_process_per_second_timers(&multi);
508
509 /* timeout? */
510 if (multi.top.c2.event_set_status == ES_TIMEOUT)
511 {
512 multi_process_timeout(&multi, MPP_PRE_SELECT|MPP_CLOSE_ON_SIGNAL);
513 }
514 else
515 {
516 /* process I/O */
517 multi_process_io_udp(&multi);
518 MULTI_CHECK_SIG(&multi);
519 }
520
521 perf_pop();
522 }
523
524 #ifdef ENABLE_ASYNC_PUSH
525 close(top->c2.inotify_fd);
526 #endif
527
528 /* shut down management interface */
529 uninit_management_callback();
530
531 /* save ifconfig-pool */
532 multi_ifconfig_pool_persist(&multi, true);
533
534 /* tear down tunnel instance (unless --persist-tun) */
535 multi_uninit(&multi);
536 multi_top_free(&multi);
537 close_instance(top);
538 }