⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 openvpn.c

📁 OpenVPN -- A Secure tunneling daemon
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *  OpenVPN -- An application to securely tunnel IP networks *             over a single UDP port, with support for SSL/TLS-based *             session authentication and key exchange, *             packet encryption, packet authentication, and *             packet compression. * *  Copyright (C) 2002-2003 James Yonan <jim@yonan.net> * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  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 */#ifdef WIN32#include "config-win32.h"#else#include "config.h"#endif#include "syshead.h"#include "common.h"#include "error.h"#include "options.h"#include "socket.h"#include "buffer.h"#include "crypto.h"#include "ssl.h"#include "misc.h"#include "lzo.h"#include "tun.h"#include "gremlin.h"#include "shaper.h"#include "thread.h"#include "interval.h"#include "fragment.h"#include "openvpn.h"#include "memdbg.h"/* * Should we become a daemon? *  level == 0 after parameters have been parsed but before any initialization *  level == 1 after initialization but before any SSL/TLS negotiation or *    tunnel data is forwarded *  first_time is true until first exit of openvpn() function * * Return true if we did it. */static boolpossibly_become_daemon (int level, const struct options* options, const bool first_time){  bool ret = false;  if (first_time && options->daemon)    {      ASSERT (!options->inetd);      if (level == DAEMONIZATION_LEVEL)	{	  if (daemon (options->cd_dir != NULL, 0) < 0)	    msg (M_ERR, "daemon() failed");	  ret = true;	}    }  return ret;}/* Handle signals */static volatile int signal_received = 0;#ifdef HAVE_SIGNAL_H/* normal signal handler, when we are in event loop */static voidsignal_handler (int signum){  signal_received = signum;  signal (signum, signal_handler);}/* temporary signal handler, before we are fully initialized */static voidsignal_handler_exit (int signum){  msg (M_FATAL | M_NOLOCK, "Signal %d received during initialization, exiting", signum);}#endif /* HAVE_SIGNAL_H *//* * For debugging, dump a packet in * nominally human-readable form. */#if defined(USE_CRYPTO) && defined(USE_SSL)#define TLS_MODE (tls_multi != NULL)#define PROTO_DUMP_FLAGS (check_debug_level (D_UDP_RW_VERBOSE) ? (PD_SHOW_DATA|PD_VERBOSE) : 0)#define PROTO_DUMP(buf) protocol_dump(buf, \				      PROTO_DUMP_FLAGS | \				      (tls_multi ? PD_TLS : 0) | \				      (options->tls_auth_file ? ks->key_type.hmac_length : 0) \				      )#else#define TLS_MODE (false)#define PROTO_DUMP(buf) format_hex (BPTR (buf), BLEN (buf), 80)#endif#ifdef USE_CRYPTO#define MD5SUM(buf, len) md5sum(buf, len)#else#define MD5SUM(buf, len) "[unavailable]"#endif#if defined(USE_PTHREAD) && defined(USE_CRYPTO)static void *test_crypto_thread (void *arg);#endif/* * Our global key schedules, packaged thusly * to facilitate --persist-key. */struct key_schedule{#ifdef USE_CRYPTO  /* which cipher, HMAC digest, and key sizes are we using? */  struct key_type   key_type;  /* pre-shared static key, read from a file */  struct key_ctx_bi static_key;#ifdef USE_SSL  /* our global SSL context */  SSL_CTX           *ssl_ctx;  /* optional authentication HMAC key for TLS control channel */  struct key_ctx_bi tls_auth_key;#endif /* USE_SSL */#else /* USE_CRYPTO */  int dummy;#endif /* USE_CRYPTO */};static voidkey_schedule_free(struct key_schedule* ks){#ifdef USE_CRYPTO  free_key_ctx_bi (&ks->static_key);#ifdef USE_SSL  if (ks->ssl_ctx)    SSL_CTX_free (ks->ssl_ctx);  free_key_ctx_bi (&ks->tls_auth_key);#endif /* USE_SSL */#endif /* USE_CRYPTO */  CLEAR (*ks);}/* * struct packet_id_persist should be empty if we are not * building with crypto. */#ifndef PACKET_ID_Hstruct packet_id_persist { int dummy; };static inline void packet_id_persist_init (struct packet_id_persist *p) {}#endif/* * Finalize MTU parameters based on command line or config file options. */static voidframe_finalize_options (struct frame *frame, const struct options *options){  frame_finalize (frame,		  options->udp_mtu_defined,		  options->udp_mtu,		  options->tun_mtu_defined,		  options->tun_mtu,#ifdef FRAGMENT_ENABLE		  options->mtu_min_defined,		  options->mtu_min,		  options->mtu_max_defined,		  options->mtu_max#else		  false,		  0,		  false,		  0#endif		  );}/* * Do the work.  Initialize and enter main event loop. * Called after command line has been parsed. * * first_time is true during our first call -- we may * be called multiple times due to SIGHUP or SIGUSR1. */static intopenvpn (const struct options *options,	 struct udp_socket_addr *udp_socket_addr,	 struct tuntap *tuntap,	 struct key_schedule *ks,	 struct packet_id_persist *pid_persist,	 bool first_time){  /*   * Initialize garbage collection level.   * When we pop the level at the end   * of the routine, everything we   * allocated with gc_malloc at our level   * or recursively lower levels will   * automatically be freed.   */  const int gc_level = gc_new_level ();  /* used by select() */  int fm;#if PASSTOS_CAPABILITY  /* used to get/set TOS. */  struct iphdr *iph;  unsigned char ptos;  bool ptos_defined = false;#endif  /* declare various buffers */  struct buffer to_tun = clear_buf ();  struct buffer to_udp = clear_buf ();  struct buffer buf = clear_buf ();  struct buffer ping_buf = clear_buf ();  struct buffer nullbuf = clear_buf ();  /* tells us to free to_udp buffer after it has been written to UDP port */  bool free_to_udp;  /* used by select() */  fd_set reads, writes;  struct udp_socket udp_socket;   /* socket used for UDP connection to remote */  struct sockaddr_in to_udp_addr; /* IP address of remote */  int max_rw_size_udp = 0;        /* max size of packet we can send to remote */  /* MTU frame parameters */  struct frame frame;#ifdef FRAGMENT_ENABLE  /* Object to handle advanced MTU negotiation and datagram fragmentation */  struct fragment_master *fragment = NULL;  struct frame frame_fragment;  struct frame frame_fragment_omit;#endif  /* Always set to current time. */  time_t current;#ifdef HAVE_GETTIMEOFDAY  /*   * Traffic shaper object.   */  struct shaper shaper;#endif  /*   * Statistics   */  counter_type tun_read_bytes = 0;  counter_type tun_write_bytes = 0;  counter_type udp_read_bytes = 0;  counter_type udp_write_bytes = 0;  /*   * Timer objects for ping and inactivity   * timeout features.   */  struct event_timeout inactivity_interval;  struct event_timeout ping_send_interval;  struct event_timeout ping_rec_interval;  /*   * This random string identifies an OpenVPN ping packet.   * It should be of sufficient length and randomness   * so as not to collide with other tunnel data.   */  static const uint8_t ping_string[] = {    0x2a, 0x18, 0x7b, 0xf3, 0x64, 0x1e, 0xb4, 0xcb,    0x07, 0xed, 0x2d, 0x0a, 0x98, 0x1f, 0xc7, 0x48  };#ifdef USE_CRYPTO  /*   * TLS-mode crypto objects.   */#ifdef USE_SSL  /* master OpenVPN SSL/TLS object */  struct tls_multi *tls_multi = NULL;  /* an options string that must match on TLS client and server */  char *data_channel_options = NULL;#ifdef USE_PTHREAD  /* object containing TLS thread state */  struct thread_parms thread_parms;  /* object sent to us by TLS thread */  struct tt_ret tt_ret;#else  /* used to optimize calls to tls_multi_process     in single-threaded mode */  struct interval tmp_int;#endif#endif  /* workspace buffers used by crypto routines */  struct buffer encrypt_buf = clear_buf ();  struct buffer decrypt_buf = clear_buf ();  /* passed to encrypt or decrypt, contains all     crypto-related command line options related     to data channel encryption/decryption */  struct crypto_options crypto_options;  /* used to keep track of data channel packet sequence numbers */  struct packet_id packet_id;  /* our residual iv from all encrypts */  uint8_t iv[EVP_MAX_IV_LENGTH];#endif  /*   * LZO compression library objects.   */#ifdef USE_LZO  struct buffer lzo_compress_buf = clear_buf ();  struct buffer lzo_decompress_buf = clear_buf ();  struct lzo_compress_workspace lzo_compwork;#endif  /*   * Buffers used to read from TUN device   * and UDP port.   */  struct buffer read_udp_buf = clear_buf ();  struct buffer read_tun_buf = clear_buf ();  /*   * IPv4 TUN device?   */  bool ipv4_tun = (!options->tun_ipv6 && is_dev_type (options->dev, options->dev_type, "tun"));  const bool ipv6_udp_transport = false; /* we don't support IPv6 UDP sockets yet */  /* workspace for get_pid_file/write_pid */  struct pid_state pid_state;  /* workspace for --user/--group */  struct user_state user_state;  struct group_state group_state;  /* temporary variable */  bool did_we_daemonize;#ifdef HAVE_SIGNAL_H  /*   * Special handling if signal arrives before   * we are properly initialized.   */  signal (SIGINT, signal_handler_exit);  signal (SIGTERM, signal_handler_exit);  signal (SIGHUP, SIG_IGN);  signal (SIGUSR1, SIG_IGN);  signal (SIGUSR2, SIG_IGN);  signal (SIGPIPE, SIG_IGN);#endif /* HAVE_SIGNAL_H */  msg (M_INFO, "%s", title_string);  CLEAR (udp_socket);  CLEAR (frame);#ifdef FRAGMENT_ENABLE  CLEAR (frame_fragment_omit);#endif  /* should we disable paging? */  if (first_time && options->mlock)    do_mlockall (true);  /*   * Initialize advanced MTU negotiation and datagram fragmentation   */#ifdef FRAGMENT_ENABLE  if (options->mtu_dynamic)    fragment = fragment_init (&frame);#endif#ifdef USE_CRYPTO  /* load a persisted packet-id for cross-session replay-protection */  if (options->packet_id_file)    packet_id_persist_load (pid_persist, options->packet_id_file);  if (!options->test_crypto)#endif    /* open the UDP socket */    udp_socket_init (&udp_socket, options->local, options->remote,		     options->local_port, options->remote_port,		     options->bind_local, options->remote_float,		     options->inetd,		     udp_socket_addr, options->ipchange,		     options->resolve_retry_seconds,		     options->mtu_discover_type);#ifdef USE_CRYPTO  /* Initialize crypto options */  CLEAR (crypto_options);  CLEAR (packet_id);  CLEAR (iv);  /* Start with a random IV and carry forward the residuals */  if (options->iv)    {      randomize_iv (iv);      crypto_options.iv = iv;    }  if (options->shared_secret_file)    {      /*       * Static Key Mode (using a pre-shared key)       */      /* Initialize packet ID tracking */      if (options->packet_id)	{	  crypto_options.packet_id = &packet_id;	  crypto_options.pid_persist = pid_persist;	  crypto_options.packet_id_long_form = true;	  packet_id_persist_load_obj (pid_persist, crypto_options.packet_id);	}      if (!key_ctx_bi_defined (&ks->static_key))	{	  struct key key;	  /* Get cipher & hash algorithms */	  init_key_type (&ks->key_type, options->ciphername,			 options->ciphername_defined, options->authname,			 options->authname_defined, options->keysize,			 options->test_crypto);	  /* Read cipher and hmac keys from shared secret file */	  read_key_file (&key, options->shared_secret_file);	  /* Fix parity for DES keys and make sure not a weak key */	  fixup_key (&key, &ks->key_type);	  if (!check_key (&key, &ks->key_type)) /* This should be a very improbable failure */	    msg (M_FATAL, "Key in %s is bad.  Try making a new key with --genkey.",		 options->shared_secret_file);	  /* Init cipher & hmac */	  init_key_ctx (&ks->static_key.encrypt, &key, &ks->key_type, DO_ENCRYPT, "Static Encrypt");	  init_key_ctx (&ks->static_key.decrypt, &key, &ks->key_type, DO_DECRYPT, "Static Decrypt");	  /* Erase the key */	  CLEAR (key);	}      else	{	  msg (M_INFO, "Re-using pre-shared static key");	}      /* Get key schedule */      crypto_options.key_ctx_bi = &ks->static_key;      /* Compute MTU parameters */      crypto_adjust_frame_parameters(&frame,				     &ks->key_type,				     options->ciphername_defined,				     options->iv,				     options->packet_id,				     true);      /* Sanity check on IV, sequence number, and cipher mode options */      check_replay_iv_consistency(&ks->key_type, options->packet_id, options->iv);      /*       * Test-crypto is a debugging tool       * that basically does a loopback test       * on the crypto subsystem.       */      if (options->test_crypto)	{#ifdef USE_PTHREAD	  if (first_time)	    {	      thread_init();	      work_thread_create(test_crypto_thread, (void*) options);	    }#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -