diff options
Diffstat (limited to 'occ.c')
-rw-r--r-- | occ.c | 393 |
1 files changed, 0 insertions, 393 deletions
@@ -1,393 +0,0 @@ -/* - * OpenVPN -- An application to securely tunnel IP networks - * over a single TCP/UDP port, with support for SSL/TLS-based - * session authentication and key exchange, - * packet encryption, packet authentication, and - * packet compression. - * - * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program (see the file COPYING included with this - * distribution); if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "syshead.h" - -#ifdef ENABLE_OCC - -#include "occ.h" - -#include "memdbg.h" - -#include "forward-inline.h" -#include "occ-inline.h" - -/* - * This random string identifies an OpenVPN - * Configuration Control packet. - * It should be of sufficient length and randomness - * so as not to collide with other tunnel data. - * - * The OCC protocol is as follows: - * - * occ_magic -- (16 octets) - * - * type [OCC_REQUEST | OCC_REPLY] (1 octet) - * null terminated options string if OCC_REPLY (variable) - * - * When encryption is used, the OCC packet - * is encapsulated within the encrypted - * envelope. - * - * OCC_STRING_SIZE must be set to sizeof (occ_magic) - */ - -const uint8_t occ_magic[] = { - 0x28, 0x7f, 0x34, 0x6b, 0xd4, 0xef, 0x7a, 0x81, - 0x2d, 0x56, 0xb8, 0xd3, 0xaf, 0xc5, 0x45, 0x9c -}; - -static const struct mtu_load_test mtu_load_test_sequence[] = { - - {OCC_MTU_LOAD_REQUEST, -1000}, - {OCC_MTU_LOAD, -1000}, - {OCC_MTU_LOAD_REQUEST, -1000}, - {OCC_MTU_LOAD, -1000}, - {OCC_MTU_LOAD_REQUEST, -1000}, - {OCC_MTU_LOAD, -1000}, - - {OCC_MTU_LOAD_REQUEST, -750}, - {OCC_MTU_LOAD, -750}, - {OCC_MTU_LOAD_REQUEST, -750}, - {OCC_MTU_LOAD, -750}, - {OCC_MTU_LOAD_REQUEST, -750}, - {OCC_MTU_LOAD, -750}, - - {OCC_MTU_LOAD_REQUEST, -500}, - {OCC_MTU_LOAD, -500}, - {OCC_MTU_LOAD_REQUEST, -500}, - {OCC_MTU_LOAD, -500}, - {OCC_MTU_LOAD_REQUEST, -500}, - {OCC_MTU_LOAD, -500}, - - {OCC_MTU_LOAD_REQUEST, -400}, - {OCC_MTU_LOAD, -400}, - {OCC_MTU_LOAD_REQUEST, -400}, - {OCC_MTU_LOAD, -400}, - {OCC_MTU_LOAD_REQUEST, -400}, - {OCC_MTU_LOAD, -400}, - - {OCC_MTU_LOAD_REQUEST, -300}, - {OCC_MTU_LOAD, -300}, - {OCC_MTU_LOAD_REQUEST, -300}, - {OCC_MTU_LOAD, -300}, - {OCC_MTU_LOAD_REQUEST, -300}, - {OCC_MTU_LOAD, -300}, - - {OCC_MTU_LOAD_REQUEST, -200}, - {OCC_MTU_LOAD, -200}, - {OCC_MTU_LOAD_REQUEST, -200}, - {OCC_MTU_LOAD, -200}, - {OCC_MTU_LOAD_REQUEST, -200}, - {OCC_MTU_LOAD, -200}, - - {OCC_MTU_LOAD_REQUEST, -150}, - {OCC_MTU_LOAD, -150}, - {OCC_MTU_LOAD_REQUEST, -150}, - {OCC_MTU_LOAD, -150}, - {OCC_MTU_LOAD_REQUEST, -150}, - {OCC_MTU_LOAD, -150}, - - {OCC_MTU_LOAD_REQUEST, -100}, - {OCC_MTU_LOAD, -100}, - {OCC_MTU_LOAD_REQUEST, -100}, - {OCC_MTU_LOAD, -100}, - {OCC_MTU_LOAD_REQUEST, -100}, - {OCC_MTU_LOAD, -100}, - - {OCC_MTU_LOAD_REQUEST, -50}, - {OCC_MTU_LOAD, -50}, - {OCC_MTU_LOAD_REQUEST, -50}, - {OCC_MTU_LOAD, -50}, - {OCC_MTU_LOAD_REQUEST, -50}, - {OCC_MTU_LOAD, -50}, - - {OCC_MTU_LOAD_REQUEST, 0}, - {OCC_MTU_LOAD, 0}, - {OCC_MTU_LOAD_REQUEST, 0}, - {OCC_MTU_LOAD, 0}, - {OCC_MTU_LOAD_REQUEST, 0}, - {OCC_MTU_LOAD, 0}, - - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - {OCC_MTU_REQUEST, 0}, - - {-1, 0} -}; - -void -check_send_occ_req_dowork (struct context *c) -{ - if (++c->c2.occ_n_tries >= OCC_N_TRIES) - { - if (c->options.ce.remote) - /* - * No OCC_REPLY from peer after repeated attempts. - * Give up. - */ - msg (D_SHOW_OCC, - "NOTE: failed to obtain options consistency info from peer -- " - "this could occur if the remote peer is running a version of " - PACKAGE_NAME - " before 1.5-beta8 or if there is a network connectivity problem, and will not necessarily prevent " - PACKAGE_NAME - " from running (" counter_format " bytes received from peer, " counter_format - " bytes authenticated data channel traffic) -- you can disable the options consistency " - "check with --disable-occ.", - c->c2.link_read_bytes, - c->c2.link_read_bytes_auth); - event_timeout_clear (&c->c2.occ_interval); - } - else - { - c->c2.occ_op = OCC_REQUEST; - - /* - * If we don't hear back from peer, send another - * OCC_REQUEST in OCC_INTERVAL_SECONDS. - */ - event_timeout_reset (&c->c2.occ_interval); - } -} - -void -check_send_occ_load_test_dowork (struct context *c) -{ - if (CONNECTION_ESTABLISHED (c)) - { - const struct mtu_load_test *entry; - - if (!c->c2.occ_mtu_load_n_tries) - msg (M_INFO, - "NOTE: Beginning empirical MTU test -- results should be available in 3 to 4 minutes."); - - entry = &mtu_load_test_sequence[c->c2.occ_mtu_load_n_tries++]; - if (entry->op >= 0) - { - c->c2.occ_op = entry->op; - c->c2.occ_mtu_load_size = - EXPANDED_SIZE (&c->c2.frame) + entry->delta; - } - else - { - msg (M_INFO, - "NOTE: failed to empirically measure MTU (requires " PACKAGE_NAME " 1.5 or higher at other end of connection)."); - event_timeout_clear (&c->c2.occ_mtu_load_test_interval); - c->c2.occ_mtu_load_n_tries = 0; - } - } -} - -void -check_send_occ_msg_dowork (struct context *c) -{ - bool doit = false; - - c->c2.buf = c->c2.buffers->aux_buf; - ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame))); - ASSERT (buf_safe (&c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame))); - ASSERT (buf_write (&c->c2.buf, occ_magic, OCC_STRING_SIZE)); - - switch (c->c2.occ_op) - { - case OCC_REQUEST: - if (!buf_write_u8 (&c->c2.buf, OCC_REQUEST)) - break; - dmsg (D_PACKET_CONTENT, "SENT OCC_REQUEST"); - doit = true; - break; - - case OCC_REPLY: - if (!c->c2.options_string_local) - break; - if (!buf_write_u8 (&c->c2.buf, OCC_REPLY)) - break; - if (!buf_write (&c->c2.buf, c->c2.options_string_local, - strlen (c->c2.options_string_local) + 1)) - break; - dmsg (D_PACKET_CONTENT, "SENT OCC_REPLY"); - doit = true; - break; - - case OCC_MTU_REQUEST: - if (!buf_write_u8 (&c->c2.buf, OCC_MTU_REQUEST)) - break; - dmsg (D_PACKET_CONTENT, "SENT OCC_MTU_REQUEST"); - doit = true; - break; - - case OCC_MTU_REPLY: - if (!buf_write_u8 (&c->c2.buf, OCC_MTU_REPLY)) - break; - if (!buf_write_u16 (&c->c2.buf, c->c2.max_recv_size_local)) - break; - if (!buf_write_u16 (&c->c2.buf, c->c2.max_send_size_local)) - break; - dmsg (D_PACKET_CONTENT, "SENT OCC_MTU_REPLY"); - doit = true; - break; - - case OCC_MTU_LOAD_REQUEST: - if (!buf_write_u8 (&c->c2.buf, OCC_MTU_LOAD_REQUEST)) - break; - if (!buf_write_u16 (&c->c2.buf, c->c2.occ_mtu_load_size)) - break; - dmsg (D_PACKET_CONTENT, "SENT OCC_MTU_LOAD_REQUEST"); - doit = true; - break; - - case OCC_MTU_LOAD: - { - int need_to_add; - - if (!buf_write_u8 (&c->c2.buf, OCC_MTU_LOAD)) - break; - need_to_add = min_int (c->c2.occ_mtu_load_size, EXPANDED_SIZE (&c->c2.frame)) - - OCC_STRING_SIZE - - sizeof (uint8_t) - - EXTRA_FRAME (&c->c2.frame); - - while (need_to_add > 0) - { - /* - * Fill the load test packet with pseudo-random bytes. - */ - if (!buf_write_u8 (&c->c2.buf, get_random () & 0xFF)) - break; - --need_to_add; - } - dmsg (D_PACKET_CONTENT, "SENT OCC_MTU_LOAD min_int(%d-%d-%d-%d,%d) size=%d", - c->c2.occ_mtu_load_size, - OCC_STRING_SIZE, - (int) sizeof (uint8_t), - EXTRA_FRAME (&c->c2.frame), - MAX_RW_SIZE_TUN (&c->c2.frame), - BLEN (&c->c2.buf)); - doit = true; - } - break; - - case OCC_EXIT: - if (!buf_write_u8 (&c->c2.buf, OCC_EXIT)) - break; - dmsg (D_PACKET_CONTENT, "SENT OCC_EXIT"); - doit = true; - break; - } - - if (doit) - { - /* - * We will treat the packet like any other outgoing packet, - * compress, encrypt, sign, etc. - */ - encrypt_sign (c, true); - } - - c->c2.occ_op = -1; -} - -void -process_received_occ_msg (struct context *c) -{ - ASSERT (buf_advance (&c->c2.buf, OCC_STRING_SIZE)); - switch (buf_read_u8 (&c->c2.buf)) - { - case OCC_REQUEST: - dmsg (D_PACKET_CONTENT, "RECEIVED OCC_REQUEST"); - c->c2.occ_op = OCC_REPLY; - break; - - case OCC_MTU_REQUEST: - dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_REQUEST"); - c->c2.occ_op = OCC_MTU_REPLY; - break; - - case OCC_MTU_LOAD_REQUEST: - dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_LOAD_REQUEST"); - c->c2.occ_mtu_load_size = buf_read_u16 (&c->c2.buf); - if (c->c2.occ_mtu_load_size >= 0) - c->c2.occ_op = OCC_MTU_LOAD; - break; - - case OCC_REPLY: - dmsg (D_PACKET_CONTENT, "RECEIVED OCC_REPLY"); - if (c->options.occ && !TLS_MODE (c) && c->c2.options_string_remote) - { - if (!options_cmp_equal_safe ((char *) BPTR (&c->c2.buf), - c->c2.options_string_remote, - c->c2.buf.len)) - { - options_warning_safe ((char *) BPTR (&c->c2.buf), - c->c2.options_string_remote, - c->c2.buf.len); - } - } - event_timeout_clear (&c->c2.occ_interval); - break; - - case OCC_MTU_REPLY: - dmsg (D_PACKET_CONTENT, "RECEIVED OCC_MTU_REPLY"); - c->c2.max_recv_size_remote = buf_read_u16 (&c->c2.buf); - c->c2.max_send_size_remote = buf_read_u16 (&c->c2.buf); - if (c->options.mtu_test - && c->c2.max_recv_size_remote > 0 - && c->c2.max_send_size_remote > 0) - { - msg (M_INFO, "NOTE: Empirical MTU test completed [Tried,Actual] local->remote=[%d,%d] remote->local=[%d,%d]", - c->c2.max_send_size_local, - c->c2.max_recv_size_remote, - c->c2.max_send_size_remote, - c->c2.max_recv_size_local); - if (!c->options.fragment - && c->options.ce.proto == PROTO_UDPv4 - && c->c2.max_send_size_local > TUN_MTU_MIN - && (c->c2.max_recv_size_remote < c->c2.max_send_size_local - || c->c2.max_recv_size_local < c->c2.max_send_size_remote)) - msg (M_INFO, "NOTE: This connection is unable to accomodate a UDP packet size of %d. Consider using --fragment or --mssfix options as a workaround.", - c->c2.max_send_size_local); - } - event_timeout_clear (&c->c2.occ_mtu_load_test_interval); - break; - - case OCC_EXIT: - dmsg (D_PACKET_CONTENT, "RECEIVED OCC_EXIT"); - c->sig->signal_received = SIGTERM; - c->sig->signal_text = "remote-exit"; - break; - } - c->c2.buf.len = 0; /* don't pass packet on */ -} - -#else -static void dummy(void) {} -#endif |