?? openvpn.c
字號:
frame_finalize_options (&frame, options); test_crypto (&crypto_options, &frame); key_schedule_free (ks); signal_received = 0;#ifdef USE_PTHREAD if (first_time) work_thread_join ();#endif goto done; } }#ifdef USE_SSL else if (options->tls_server || options->tls_client) { /* * TLS-based dynamic key exchange mode */ struct tls_options to; bool packet_id_long_form; ASSERT (!options->test_crypto); /* Make sure we are either a TLS client or server but not both */ ASSERT (options->tls_server == !options->tls_client); /* Let user specify a script to verify the incoming certificate */ tls_set_verify_command (options->tls_verify); if (!ks->ssl_ctx) { /* * Initialize the OpenSSL library's global * SSL context. */ ks->ssl_ctx = init_ssl (options->tls_server, options->ca_file, options->dh_file, options->cert_file, options->priv_key_file, options->cipher_list); /* Get cipher & hash algorithms */ init_key_type (&ks->key_type, options->ciphername, options->ciphername_defined, options->authname, options->authname_defined, options->keysize, true); /* TLS handshake authentication (--tls-auth) */ if (options->tls_auth_file) get_tls_handshake_key (&ks->key_type, &ks->tls_auth_key, options->tls_auth_file); } else { msg (M_INFO, "Re-using SSL/TLS context"); } /* Sanity check on IV, sequence number, and cipher mode options */ check_replay_iv_consistency(&ks->key_type, options->packet_id, options->iv); /* In short form, unique datagram identifier is 32 bits, in long form 64 bits */ packet_id_long_form = cfb_ofb_mode (&ks->key_type); /* Compute MTU parameters */ crypto_adjust_frame_parameters(&frame, &ks->key_type, options->ciphername_defined, options->iv, options->packet_id, packet_id_long_form); tls_adjust_frame_parameters(&frame); /* Set all command-line TLS-related options */ CLEAR (to); to.ssl_ctx = ks->ssl_ctx; to.key_type = ks->key_type; to.server = options->tls_server; to.options = data_channel_options = options_string (options); to.packet_id = options->packet_id; to.packet_id_long_form = packet_id_long_form; to.transition_window = options->transition_window; to.handshake_window = options->handshake_window; to.packet_timeout = options->tls_timeout; to.renegotiate_bytes = options->renegotiate_bytes; to.renegotiate_packets = options->renegotiate_packets; to.renegotiate_seconds = options->renegotiate_seconds; to.single_session = options->single_session; to.disable_occ = options->disable_occ; /* TLS handshake authentication (--tls-auth) */ if (options->tls_auth_file) { to.tls_auth_key = ks->tls_auth_key; to.tls_auth.pid_persist = pid_persist; to.tls_auth.packet_id_long_form = true; crypto_adjust_frame_parameters(&to.frame, &ks->key_type, false, false, true, true); } /* * Initialize OpenVPN's master TLS-mode object. */ tls_multi = tls_multi_init (&to, &udp_socket); }#endif else { /* * No encryption or authentication. */ ASSERT (!options->test_crypto); free_key_ctx_bi (&ks->static_key); crypto_options.key_ctx_bi = &ks->static_key; msg (M_WARN, "******* WARNING *******: all encryption and authentication features disabled -- all data will be tunnelled as cleartext"); }#else /* USE_CRYPTO */ msg (M_WARN, "******* WARNING *******: OpenVPN built without OpenSSL -- encryption and authentication features disabled -- all data will be tunnelled as cleartext");#endif /* USE_CRYPTO */#ifdef USE_LZO /* * Initialize LZO compression library. */ if (options->comp_lzo) { lzo_compress_init (&lzo_compwork, options->comp_lzo_adaptive); lzo_adjust_frame_parameters (&frame);#ifdef FRAGMENT_ENABLE lzo_adjust_frame_parameters (&frame_fragment_omit); /* omit LZO frame delta from final frame_fragment */#endif }#endif /* * Adjust frame size based on the --tun-mtu-extra parameter. */ tun_adjust_frame_parameters (&frame, options->tun_mtu_extra); /* * Fill in the blanks in the frame parameters structure, * make sure values are rational, etc. */ frame_finalize_options (&frame, options); /* * Set frame parameter for fragment code. This is necessary because * the fragmentation code deals with payloads which have already been * passed through the compression code. */#ifdef FRAGMENT_ENABLE frame_fragment = frame; frame_subtract_extra (&frame_fragment, &frame_fragment_omit); frame_dynamic_finalize (&frame_fragment);#endif max_rw_size_udp = MAX_RW_SIZE_UDP (&frame); frame_print (&frame, D_MTU_INFO, "Data Channel MTU parms");#ifdef FRAGMENT_ENABLE if (fragment) frame_print (&frame_fragment, D_FRAG_DEBUG, "Fragmentation MTU parms");#endif#if defined(USE_CRYPTO) && defined(USE_SSL) if (tls_multi) { int size; tls_multi_init_finalize (tls_multi, &frame); size = MAX_RW_SIZE_UDP (&tls_multi->opt.frame); if (size > max_rw_size_udp) max_rw_size_udp = size; frame_print (&tls_multi->opt.frame, D_MTU_INFO, "Control Channel MTU parms"); }#endif /* * Now that we know all frame parameters, initialize * our buffers. */ read_udp_buf = alloc_buf (BUF_SIZE (&frame)); read_tun_buf = alloc_buf (BUF_SIZE (&frame));#ifdef USE_CRYPTO encrypt_buf = alloc_buf (BUF_SIZE (&frame)); decrypt_buf = alloc_buf (BUF_SIZE (&frame));#endif#ifdef USE_LZO if (options->comp_lzo) { lzo_compress_buf = alloc_buf (BUF_SIZE (&frame)); lzo_decompress_buf = alloc_buf (BUF_SIZE (&frame)); }#endif#ifdef FRAGMENT_ENABLE /* fragmenting code has buffers to initialize once frame parameters are known */ if (fragment) fragment_frame_init (fragment, &frame_fragment, (options->mtu_icmp && ipv4_tun));#endif if (!tuntap_defined (tuntap)) { /* do ifconfig */ if (ifconfig_order() == IFCONFIG_BEFORE_TUN_OPEN) do_ifconfig (options->dev, options->dev_type, options->ifconfig_local, options->ifconfig_remote, TUN_MTU_SIZE (&frame)); /* open the tun device */ open_tun (options->dev, options->dev_type, options->dev_node, options->tun_ipv6, tuntap); /* do ifconfig */ if (ifconfig_order() == IFCONFIG_AFTER_TUN_OPEN) do_ifconfig (tuntap->actual, options->dev_type, options->ifconfig_local, options->ifconfig_remote, TUN_MTU_SIZE (&frame)); /* run the up script */ run_script (options->up_script, tuntap->actual, TUN_MTU_SIZE (&frame), max_rw_size_udp, options->ifconfig_local, options->ifconfig_remote); } else { msg (M_INFO, "Preserving previous TUN/TAP instance: %s", tuntap->actual); }#ifdef HAVE_GETTIMEOFDAY /* initialize traffic shaper (i.e. transmit bandwidth limiter) */ if (options->shaper) { shaper_init (&shaper, options->shaper); shaper_msg (&shaper); }#endif if (first_time) { /* get user and/or group that we want to setuid/setgid to */ get_group (options->groupname, &group_state); get_user (options->username, &user_state); /* get --writepid file descriptor */ get_pid_file (options->writepid, &pid_state); /* chroot if requested */ do_chroot (options->chroot_dir); } /* become a daemon if --daemon */ did_we_daemonize = possibly_become_daemon (1, options, first_time);#ifdef HAVE_SIGNAL_H /* catch signals */ signal (SIGINT, signal_handler); signal (SIGTERM, signal_handler); signal (SIGHUP, signal_handler); signal (SIGUSR1, signal_handler); signal (SIGUSR2, signal_handler);#endif /* HAVE_SIGNAL_H */ if (first_time) { /* should we disable paging? */ if (options->mlock && did_we_daemonize) do_mlockall (true); /* call again in case we daemonized */ /* set user and/or group that we want to setuid/setgid to */ set_group (&group_state); set_user (&user_state); /* save process ID in a file */ write_pid (&pid_state); /* initialize threading if pthread configure option enabled */ thread_init(); } /* start the TLS thread */#if defined(USE_CRYPTO) && defined(USE_SSL) && defined(USE_PTHREAD) if (tls_multi) tls_thread_create (&thread_parms, tls_multi, &udp_socket, options->nice_work, options->mlock);#endif /* change scheduling priority if requested */ if (first_time) set_nice (options->nice); /* * MAIN EVENT LOOP * * Pipe UDP -> tun and tun -> UDP using nonblocked i/o. * * If tls_multi is defined, multiplex a TLS * control channel over the UDP connection which * will be used for secure key exchange with our peer. * */ /* calculate max file handle + 1 for select */ fm = udp_socket.sd; if (tuntap->fd > fm) fm = tuntap->fd; current = time (NULL); /* initialize inactivity timeout */ if (options->inactivity_timeout) event_timeout_init (&inactivity_interval, current, options->inactivity_timeout); /* initialize pings */ if (options->ping_send_timeout) { ping_buf = alloc_buf (BUF_SIZE (&frame)); event_timeout_init (&ping_send_interval, 0, options->ping_send_timeout); } if (options->ping_rec_timeout) event_timeout_init (&ping_rec_interval, current, options->ping_rec_timeout);#if defined(USE_CRYPTO) && defined(USE_SSL)#ifdef USE_PTHREAD if (tls_multi && TLS_THREAD_SOCKET (&thread_parms) > fm) fm = TLS_THREAD_SOCKET (&thread_parms);#else /* initialize tmp_int optimization that limits the number of times we call tls_multi_process in the main event loop */ interval_init (&tmp_int, TLS_MULTI_HORIZON, TLS_MULTI_REFRESH);#endif#endif /* select() needs this */ ++fm; /* this flag is true for buffers coming from the TLS background thread */ free_to_udp = false; while (true) { int stat = 0; struct timeval *tv = NULL; struct timeval timeval; /* initialize select() timeout */ timeval.tv_sec = 0; timeval.tv_usec = 0;#ifdef USE_CRYPTO /* flush current packet-id to file once per 60 seconds if --replay-persist was specified */ packet_id_persist_flush (pid_persist, current, 60);#endif#if defined(USE_CRYPTO) && defined(USE_SSL) && !defined(USE_PTHREAD) /* * In TLS mode, let TLS level respond to any control-channel packets which were * received, or prepare any packets for transmission. * * tmp_int is purely an optimization that allows us to call tls_multi_process * less frequently when there's not much traffic on the control-channel. * */ if (tls_multi) { interval_t wakeup = 0; if (interval_test (&tmp_int, current)) { if (tls_multi_process (tls_multi, &to_udp, &to_udp_addr, &udp_socket, &wakeup, current)) interval_action (&tmp_int, current); interval_future_trigger (&tmp_int, wakeup, current); free_to_udp = false; } interval_schedule_wakeup (&tmp_int, current, &wakeup); if (wakeup) { timeval.tv_sec = wakeup; timeval.tv_usec = 0; tv = &timeval; } }#endif current = time (NULL); /* * Should we exit due to inactivity timeout? */ if (options->inactivity_timeout) { if (event_timeout_trigger (&inactivity_interval, current)) { msg (M_INFO, "Inactivity timeout (--inactive), exiting"); signal_received = 0; break; } event_timeout_wakeup (&inactivity_interval, current, &timeval); tv = &timeval; } /* * Should we exit or restart due to ping (or other authenticated packet) * not received in n seconds? */ if (options->ping_rec_timeout && (!options->ping_timer_remote || addr_defined (&udp_socket_addr->actual))) { if (event_timeout_trigger (&ping_rec_interval, current)) { switch (options->ping_rec_timeout_action) { case PING_EXIT: msg (M_INFO, "Inactivity timeout (--ping-exit), exiting"); signal_received = 0; break; case PING_RESTART: msg (M_INFO, "Inactivity timeout (--ping-restart), restarting"); signal_received = SIGUSR1; break; default: ASSERT (0); } break; } event_timeout_wakeup (&ping_rec_interval, current, &timeval); tv = &timeval; }#ifdef FRAGMENT_ENABLE /* * Should we deliver a datagram fragment to remote? */ if (fragment) { /* OS MTU Hint? */ if (udp_socket.mtu_changed && ipv4_tun) { frame_adjust_path_mtu (&frame_fragment, udp_socket.mtu, ipv6_udp_transport); udp_socket.mtu_changed = false; } if (!to_udp.len && fragment_outgoing_defined (fragment) && fragment_ready_to_send (fragment, &buf, &frame_fragment)) {#ifdef USE_CRYPTO#ifdef USE_SSL /* * If TLS mode, get the key we will use to encrypt * the packet. */ mutex_lock (L_TLS); if (tls_multi) tls_pre_encrypt (tls_multi, &buf, &crypto_options);#endif /* * Encrypt the packet and write an optional * HMAC authentication record. */ openvpn_encrypt (&buf, encrypt_buf, &crypto_options, &frame, current);#endif /* * Get the address we will be sending the packet to. */ udp_socket_get_outgoing_addr (&buf, &udp_socket, &to_udp_addr);#ifdef USE_CRYPTO#ifdef USE_SSL /* * In TLS mode, prepend the appropriate one-byte opcode * to the packet which identifies it as a data channel * packet and gives the low-permutation version of * the key-id to the recipient so it knows which * decrypt key to use. */ if (tls_multi) tls_post_encrypt (tls_multi, &buf); mutex_unlock (L_TLS);#endif#endif to_udp = buf; free_to_udp = false; } if (!to_tun.len && fragment_icmp (fragment, &buf)) { to_tun = buf; } fragment_housekeeping (fragment, &frame_fragment, current, &timeval); tv = &timeval; }#endif /* FRAGMENT_ENABLE */ /* * Should we ping the remote? */ if (options->ping_send_timeout) { if (!to_udp.len) { if (event_timeout_trigger (&ping_send_interval, current)) { buf = ping_buf; ASSERT (buf_init (&buf, EXTRA_FRAME (&frame))); ASSERT (buf_safe (&buf, MAX_RW_SIZE_TUN (&frame)));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -