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

📄 ssl.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 5 页
字号:
static inline intkey_state_read_ciphertext (struct tls_multi *multi, struct key_state *ks, struct buffer *buf,			   int maxlen){  return bio_read (multi, ks->ct_out, buf, maxlen, "tls_read_ciphertext");}/* * Initialize a key_state.  Each key_state corresponds to * a specific SSL/TLS session. */static voidkey_state_init (struct tls_session *session, struct key_state *ks){  update_time ();  /*   * Build TLS object that reads/writes ciphertext   * to/from memory BIOs.   */  CLEAR (*ks);  ks->ssl = SSL_new (session->opt->ssl_ctx);  if (!ks->ssl)    msg (M_SSLERR, "SSL_new failed");  /* put session * in ssl object so we can access it     from verify callback*/  SSL_set_ex_data (ks->ssl, mydata_index, session);  ks->ssl_bio = getbio (BIO_f_ssl (), "ssl_bio");  ks->ct_in = getbio (BIO_s_mem (), "ct_in");  ks->ct_out = getbio (BIO_s_mem (), "ct_out");#ifdef BIO_DEBUG  bio_debug_oc ("open ssl_bio", ks->ssl_bio);  bio_debug_oc ("open ct_in", ks->ct_in);  bio_debug_oc ("open ct_out", ks->ct_out);#endif  if (session->opt->server)    SSL_set_accept_state (ks->ssl);  else    SSL_set_connect_state (ks->ssl);  SSL_set_bio (ks->ssl, ks->ct_in, ks->ct_out);  BIO_set_ssl (ks->ssl_bio, ks->ssl, BIO_NOCLOSE);  /* Set control-channel initiation mode */  ks->initial_opcode = session->initial_opcode;  session->initial_opcode = P_CONTROL_SOFT_RESET_V1;  ks->state = S_INITIAL;  ks->key_id = session->key_id;  /*   * key_id increments to KEY_ID_MASK then recycles back to 1.   * This way you know that if key_id is 0, it is the first key.   */  ++session->key_id;  session->key_id &= P_KEY_ID_MASK;  if (!session->key_id)    session->key_id = 1;  /* allocate key source material object */  ALLOC_OBJ_CLEAR (ks->key_src, struct key_source2);  /* allocate reliability objects */  ALLOC_OBJ_CLEAR (ks->send_reliable, struct reliable);  ALLOC_OBJ_CLEAR (ks->rec_reliable, struct reliable);  ALLOC_OBJ_CLEAR (ks->rec_ack, struct reliable_ack);  /* allocate buffers */  ks->plaintext_read_buf = alloc_buf (PLAINTEXT_BUFFER_SIZE);  ks->plaintext_write_buf = alloc_buf (PLAINTEXT_BUFFER_SIZE);  ks->ack_write_buf = alloc_buf (BUF_SIZE (&session->opt->frame));  reliable_init (ks->send_reliable, BUF_SIZE (&session->opt->frame),		 FRAME_HEADROOM (&session->opt->frame), TLS_RELIABLE_N_SEND_BUFFERS);  reliable_init (ks->rec_reliable, BUF_SIZE (&session->opt->frame),		 FRAME_HEADROOM (&session->opt->frame), TLS_RELIABLE_N_REC_BUFFERS);  reliable_set_timeout (ks->send_reliable, session->opt->packet_timeout);  /* init packet ID tracker */  packet_id_init (&ks->packet_id,		  session->opt->replay_window,		  session->opt->replay_time);}static voidkey_state_free (struct key_state *ks, bool clear){  ks->state = S_UNDEF;  if (ks->ssl) {#ifdef BIO_DEBUG    bio_debug_oc ("close ssl_bio", ks->ssl_bio);    bio_debug_oc ("close ct_in", ks->ct_in);    bio_debug_oc ("close ct_out", ks->ct_out);#endif    BIO_free_all(ks->ssl_bio);    SSL_free (ks->ssl);  }  free_key_ctx_bi (&ks->key);  free_buf (&ks->plaintext_read_buf);  free_buf (&ks->plaintext_write_buf);  free_buf (&ks->ack_write_buf);  if (ks->send_reliable)    {      reliable_free (ks->send_reliable);      free (ks->send_reliable);    }  if (ks->rec_reliable)    {      reliable_free (ks->rec_reliable);      free (ks->rec_reliable);    }  if (ks->rec_ack)    free (ks->rec_ack);  if (ks->key_src)    free (ks->key_src);  packet_id_free (&ks->packet_id);  if (clear)    CLEAR (*ks);}/* * Must be called if we move a tls_session in memory. */static inline void tls_session_set_self_referential_pointers (struct tls_session* session) {  session->tls_auth.packet_id = &session->tls_auth_pid;}/* * Initialize a TLS session.  A TLS session normally has 2 key_state objects, * one for the current key, and one for the lame duck (i.e. retiring) key. */static voidtls_session_init (struct tls_multi *multi, struct tls_session *session){  struct gc_arena gc = gc_new ();  msg (D_TLS_DEBUG, "TLS: tls_session_init: entry");  CLEAR (*session);  /* Set options data to point to parent's option structure */  session->opt = &multi->opt;    /* Randomize session # if it is 0 */  while (!session_id_defined(&session->session_id))    session_id_random (&session->session_id);  /* Are we a TLS server or client? */  ASSERT (session->opt->key_method >= 1);  if (session->opt->key_method == 1)    {      session->initial_opcode = session->opt->server ?	P_CONTROL_HARD_RESET_SERVER_V1 : P_CONTROL_HARD_RESET_CLIENT_V1;    }  else /* session->opt->key_method >= 2 */    {      session->initial_opcode = session->opt->server ?	P_CONTROL_HARD_RESET_SERVER_V2 : P_CONTROL_HARD_RESET_CLIENT_V2;    }  /* Initialize control channel authentication parameters */  session->tls_auth = session->opt->tls_auth;  /* Set session internal pointers (also called if session object is moved in memory) */  tls_session_set_self_referential_pointers (session);  /* initialize packet ID replay window for --tls-auth */  packet_id_init (session->tls_auth.packet_id,		  session->opt->replay_window,		  session->opt->replay_time);  /* load most recent packet-id to replay protect on --tls-auth */  packet_id_persist_load_obj (session->tls_auth.pid_persist, session->tls_auth.packet_id);  key_state_init (session, &session->key[KS_PRIMARY]);  msg (D_TLS_DEBUG, "TLS: tls_session_init: new session object, sid=%s",       session_id_print (&session->session_id, &gc));  gc_free (&gc);}static voidtls_session_free (struct tls_session *session, bool clear){  int i;  if (session->tls_auth.packet_id)    packet_id_free (session->tls_auth.packet_id);  for (i = 0; i < KS_SIZE; ++i)    key_state_free (&session->key[i], false);  if (session->common_name)    free (session->common_name);  if (clear)    CLEAR (*session);}static voidmove_session (struct tls_multi* multi, int dest, int src, bool reinit_src){  msg (D_TLS_DEBUG_LOW, "TLS: move_session: dest=%s src=%s reinit_src=%d",       session_index_name(dest),       session_index_name(src),       reinit_src);  ASSERT (src != dest);  ASSERT (src >= 0 && src < TM_SIZE);  ASSERT (dest >= 0 && dest < TM_SIZE);  tls_session_free (&multi->session[dest], false);  multi->session[dest] = multi->session[src];  tls_session_set_self_referential_pointers (&multi->session[dest]);  if (reinit_src)    tls_session_init (multi, &multi->session[src]);  else    CLEAR (multi->session[src]);  msg (D_TLS_DEBUG, "TLS: move_session: exit");}static voidreset_session (struct tls_multi *multi, struct tls_session *session){  tls_session_free (session, false);  tls_session_init (multi, session);}#if 0/* * Transmit a TLS reset on our untrusted channel. */static voidinitiate_untrusted_session (struct tls_multi *multi, struct sockaddr_in *to){  struct tls_session *session = &multi->session[TM_UNTRUSTED];  struct key_state *ks = &session->key[KS_PRIMARY];  reset_session (multi, session);  ks->remote_addr = *to;  msg (D_TLS_DEBUG_LOW, "TLS: initiate_untrusted_session: addr=%s", print_sockaddr (to));}#endif/* * Used to determine in how many seconds we should be * called again. */static inline voidcompute_earliest_wakeup (interval_t *earliest, interval_t seconds_from_now) {  if (seconds_from_now < *earliest)    *earliest = seconds_from_now;  if (*earliest < 0)    *earliest = 0;}/* * Return true if "lame duck" or retiring key has expired and can * no longer be used. */static inline boollame_duck_must_die (const struct tls_session* session, interval_t *wakeup){  const struct key_state* lame = &session->key[KS_LAME_DUCK];  if (lame->state >= S_INITIAL)    {      const time_t local_now = now;      ASSERT (lame->must_die); /* a lame duck key must always have an expiration */      if (local_now < lame->must_die)	{	  compute_earliest_wakeup (wakeup, lame->must_die - local_now);	  return false;	}      else	return true;    }  else if (lame->state == S_ERROR)    return true;  else    return false;}/* * A tls_multi object fully encapsulates OpenVPN's TLS state. * See ssl.h for more comments. */struct tls_multi *tls_multi_init (struct tls_options *tls_options){  struct tls_multi *ret;  ALLOC_OBJ_CLEAR (ret, struct tls_multi);  /* get command line derived options */  ret->opt = *tls_options;  /* set up pointer to HMAC object for TLS packet authentication */  ret->opt.tls_auth.key_ctx_bi = &ret->opt.tls_auth_key;  /* set up list of keys to be scanned by data channel encrypt and decrypt routines */  ASSERT (SIZE (ret->key_scan) == 3);  ret->key_scan[0] = &ret->session[TM_ACTIVE].key[KS_PRIMARY];  ret->key_scan[1] = &ret->session[TM_ACTIVE].key[KS_LAME_DUCK];  ret->key_scan[2] = &ret->session[TM_LAME_DUCK].key[KS_LAME_DUCK];  return ret;}/* * Finalize our computation of frame sizes. */voidtls_multi_init_finalize (struct tls_multi* multi, const struct frame* frame){  tls_init_control_channel_frame_parameters (frame, &multi->opt.frame);    /* initialize the active and untrusted sessions */  tls_session_init (multi, &multi->session[TM_ACTIVE]);  if (!multi->opt.single_session)    tls_session_init (multi, &multi->session[TM_UNTRUSTED]);}/* * Initialize and finalize a standalone tls-auth verification object. */struct tls_auth_standalone *tls_auth_standalone_init (struct tls_options *tls_options,			  struct gc_arena *gc){  struct tls_auth_standalone *tas;  ALLOC_OBJ_CLEAR_GC (tas, struct tls_auth_standalone, gc);  /* set up pointer to HMAC object for TLS packet authentication */  tas->tls_auth_key = tls_options->tls_auth_key;  tas->tls_auth_options.key_ctx_bi = &tas->tls_auth_key;  tas->tls_auth_options.packet_id_long_form = true;  /* get initial frame parms, still need to finalize */  tas->frame = tls_options->frame;  return tas;}voidtls_auth_standalone_finalize (struct tls_auth_standalone *tas,			      const struct frame *frame){  tls_init_control_channel_frame_parameters (frame, &tas->frame);}/* * Set local and remote option compatibility strings. * Used to verify compatibility of local and remote option * sets. */voidtls_multi_init_set_options (struct tls_multi* multi,			   const char *local,			   const char *remote){  /* initialize options string */  multi->opt.local_options = local;  multi->opt.remote_options = remote;}voidtls_multi_free (struct tls_multi *multi, bool clear){  int i;  ASSERT (multi);  for (i = 0; i < TM_SIZE; ++i)    tls_session_free (&multi->session[i], false);  if (clear)    CLEAR (*multi);  free(multi);}/* * Move a packet authentication HMAC + related fields to or from the front * of the buffer so it can be processed by encrypt/decrypt. *//* * Dependent on hmac size, opcode size, and session_id size. * Will assert if too small. */#define SWAP_BUF_SIZE 256static boolswap_hmac (struct buffer *buf, const struct crypto_options *co, bool incoming){  struct key_ctx *ctx;  ASSERT (co);  ctx = (incoming ? &co->key_ctx_bi->decrypt : &co->key_ctx_bi->encrypt);  ASSERT (ctx->hmac);  {    /* hmac + packet_id (8 bytes) */    const int hmac_size = HMAC_size (ctx->hmac) + packet_id_size (true);    /* opcode + session_id */    const int osid_size = 1 + SID_SIZE;    int e1, e2;    uint8_t *b = BPTR (buf);    uint8_t buf1[SWAP_BUF_SIZE];    uint8_t buf2[SWAP_BUF_SIZE];    if (incoming)      {	e1 = osid_size;	e2 = hmac_size;      }    else      {	e1 = hmac_size;	e2 = osid_size;      }    ASSERT (e1 <= SWAP_BUF_SIZE && e2 <= SWAP_BUF_SIZE);    if (buf->len >= e1 + e2)      {	memcpy (buf1, b, e1);	memcpy (buf2, b + e1, e2);	memcpy (b, buf2, e2);	memcpy (b + e2, buf1, e1);	return true;      }    else      return false;  }}#undef SWAP_BUF_SIZE/* * Write a control channel authentication record. */static voidwrite_control_auth (struct tls_session *session,		    struct key_state *ks,		    struct buffer *buf,		    struct sockaddr_in *to_link_addr,		    int opcode,		    int max_ack,		    bool prepend_ack){  uint8_t *header;  struct buffer null = clear_buf ();  ASSERT (addr_defined (&ks->remote_addr));  ASSERT (reliable_ack_write	  (ks->rec_ack, buf, &ks->session_id_remote, max_ack, prepend_ack));  ASSERT (session_id_write_prepend (&session->session_id, buf));  ASSERT (header = buf_prepend (buf, 1));  *header = ks->key_id | (opcode << P_OPCODE_SHIFT);  if (session->tls_auth.key_ctx_bi->encrypt.hmac)    {      /* no encryption, only write hmac */      openvpn_encrypt (buf, null, &session->tls_auth, NULL);      ASSERT (swap_hmac (buf, &session->tls_auth, false));    }  *to_link_addr = ks->remote_addr;}/* * Read a control channel authentication record. */static boolread_control_auth (struct buffer *buf,		   const struct crypto_options *co,		   const struct sockaddr_in *from){  struct gc_arena gc = gc_new ();  if (co->key_ctx_bi->decrypt.hmac)    {      struct buffer null = clear_buf ();      /* move the hmac record to the front of the packet */      if (!swap_hmac (buf, co, true))	{	  msg (D_TLS_ERRORS,	       "TLS Error: cannot locate HMAC in incoming packet from %s",	       print_sockaddr (from, &gc));	  gc_free (&gc);	  return false;	}      /* authenticate only (no decrypt) and remove the hmac record         from the head of the buffer */      openvpn_decrypt (buf, null, co, NULL);

⌨️ 快捷键说明

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