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

📄 ssl.c

📁 一个开源的VPN原码
💻 C
📖 第 1 页 / 共 5 页
字号:
    printf ("%s\n", cipher_name);  printf ("\n");  SSL_free (ssl);  SSL_CTX_free (ctx);}/* * The OpenSSL library has a notion of preference in TLS * ciphers.  Higher preference == more secure. * Return the highest preference cipher. */voidget_highest_preference_tls_cipher (char *buf, int size){  SSL_CTX *ctx;  SSL *ssl;  const char *cipher_name;  ctx = SSL_CTX_new (TLSv1_method ());  if (!ctx)    msg (M_SSLERR, "Cannot create SSL_CTX object");  ssl = SSL_new (ctx);  if (!ssl)    msg (M_SSLERR, "Cannot create SSL object");  cipher_name = SSL_get_cipher_list (ssl, 0);  strncpynt (buf, cipher_name, size);  SSL_free (ssl);  SSL_CTX_free (ctx);}/* * Map internal constants to ascii names. */static const char *state_name (int state){  switch (state)    {    case S_UNDEF:      return "S_UNDEF";    case S_INITIAL:      return "S_INITIAL";    case S_PRE_START:      return "S_PRE_START";    case S_START:      return "S_START";    case S_SENT_KEY:      return "S_SENT_KEY";    case S_GOT_KEY:      return "S_GOT_KEY";    case S_ACTIVE:      return "S_ACTIVE";    case S_ERROR:      return "S_ERROR";    default:      return "S_???";    }}static const char *packet_opcode_name (int op){  switch (op)    {    case P_CONTROL_HARD_RESET_CLIENT_V1:      return "P_CONTROL_HARD_RESET_CLIENT_V1";    case P_CONTROL_HARD_RESET_SERVER_V1:      return "P_CONTROL_HARD_RESET_SERVER_V1";    case P_CONTROL_SOFT_RESET_V1:      return "P_CONTROL_SOFT_RESET_V1";    case P_CONTROL_V1:      return "P_CONTROL_V1";    case P_ACK_V1:      return "P_ACK_V1";    case P_DATA_V1:      return "P_DATA_V1";    default:      return "P_???";    }}static const char *session_index_name (int index){  switch (index)    {    case TM_ACTIVE:      return "TM_ACTIVE";    case TM_UNTRUSTED:      return "TM_UNTRUSTED";    case TM_LAME_DUCK:      return "TM_LAME_DUCK";    default:      return "TM_???";    }}/* * For debugging. */static const char *print_key_id (struct tls_multi *multi){  int i;  struct buffer out = alloc_buf_gc (256);  for (i = 0; i < KEY_SCAN_SIZE; ++i)    {      struct key_state *ks = multi->key_scan[i];      buf_printf (&out, " [key#%d state=%s id=%d sid=%s]", i,		  state_name (ks->state), ks->key_id,		  session_id_print (&ks->session_id_remote));    }  return out.data;}/* * OpenVPN's interface to SSL/TLS authentication, * encryption, and decryption is exclusively * through "memory BIOs". */static BIO *getbio (BIO_METHOD * type, const char *desc){  BIO *ret;  ret = BIO_new (type);  if (!ret)    msg (M_SSLERR, "Error creating %s BIO", desc);  return ret;}/* * Write to an OpenSSL BIO in non-blocking mode. */static intbio_write (BIO * bio, struct buffer *buf, const char *desc){  int i;  int ret = 0;  ASSERT (buf->len >= 0);  if (buf->len)    {      /*       * Free the L_TLS lock prior to calling BIO routines       * so that foreground thread can still call       * tls_pre_decrypt or tls_pre_encrypt,       * allowing tunnel packet forwarding to continue.       */#ifdef BIO_DEBUG      bio_debug_data ("write", bio, BPTR (buf), BLEN (buf), desc);#endif      mutex_unlock (L_TLS);      i = BIO_write (bio, BPTR (buf), BLEN (buf));      mutex_lock (L_TLS);      if (i < 0)	{	  if (BIO_should_retry (bio))	    {	      ;	    }	  else	    {	      msg (D_TLS_ERRORS | M_SSL, "TLS ERROR: BIO write %s error",		   desc);	      ret = -1;	    }	}      else if (i != buf->len)	{	  msg (D_TLS_ERRORS | M_SSL,	       "TLS ERROR: BIO write %s incomplete %d/%d", desc, i, buf->len);	  ret = -1;	}      else	{			/* successful write */	  msg (D_HANDSHAKE_VERBOSE, "BIO write %s %d bytes", desc, i);	  memset (BPTR (buf), 0, BLEN (buf)); /* erase data just written */	  buf->len = 0;	  ret = 1;	}    }  return ret;}/* * Read from an OpenSSL BIO in non-blocking mode. */static intbio_read (BIO * bio, struct buffer *buf, int maxlen, const char *desc){  int i;  int ret = 0;  ASSERT (buf->len >= 0);  if (buf->len)    {      ;    }  else    {      int len = buf_forward_capacity (buf);      if (maxlen < len)	len = maxlen;      /*       * Free the L_TLS lock prior to calling BIO routines       * so that foreground thread can still call       * tls_pre_decrypt or tls_pre_encrypt,       * allowing tunnel packet forwarding to continue.       *       * BIO_read brackets most of the serious RSA       * key negotiation number crunching.       */      mutex_unlock (L_TLS);      i = BIO_read (bio, BPTR (buf), len);      mutex_lock (L_TLS);#ifdef BIO_DEBUG      bio_debug_data ("read", bio, BPTR (buf), i, desc);#endif      if (i < 0)	{	  if (BIO_should_retry (bio))	    {	      ;	    }	  else	    {	      msg (D_TLS_ERRORS | M_SSL, "TLS_ERROR: BIO read %s error",		   desc);	      buf->len = 0;	      ret = -1;	    }	}      else if (!i)	{	  buf->len = 0;	}      else	{			/* successful read */	  msg (D_HANDSHAKE_VERBOSE, "BIO read %s %d bytes", desc, i);	  buf->len = i;	  ret = 1;	}    }  return ret;}/* * Inline functions for reading from and writing * to BIOs. */static inline intkey_state_write_plaintext (struct key_state *ks, struct buffer *buf){  return bio_write (ks->ssl_bio, buf, "tls_write_plaintext");}static inline intkey_state_write_ciphertext (struct key_state *ks, struct buffer *buf){  return bio_write (ks->ct_in, buf, "tls_write_ciphertext");}static inline intkey_state_read_plaintext (struct key_state *ks, struct buffer *buf,			  int maxlen){  return bio_read (ks->ssl_bio, buf, maxlen, "tls_read_plaintext");}static inline intkey_state_read_ciphertext (struct key_state *ks, struct buffer *buf,			   int maxlen){  return bio_read (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,		time_t current){  /*   * 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");  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 buffers */  ks->plaintext_read_buf = alloc_buf (BUF_SIZE (&session->opt->frame));  ks->plaintext_write_buf = alloc_buf (BUF_SIZE (&session->opt->frame));  ks->ack_write_buf = alloc_buf (BUF_SIZE (&session->opt->frame));  reliable_init (&ks->send_reliable, BUF_SIZE (&session->opt->frame),		 EXTRA_FRAME (&session->opt->frame));  reliable_init (&ks->rec_reliable, BUF_SIZE (&session->opt->frame),		 EXTRA_FRAME (&session->opt->frame));  reliable_set_timeout (&ks->send_reliable, session->opt->packet_timeout);}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);  reliable_free (&ks->send_reliable);  reliable_free (&ks->rec_reliable);  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 retiring key. */static voidtls_session_init (struct tls_multi *multi, struct tls_session *session){  msg (D_TLS_DEBUG, "tls_session_init: entry");  CLEAR (*session);  session->opt = &multi->opt;    while (!session_id_defined(&session->session_id))    session_id_random (&session->session_id);  session->initial_opcode = session->opt->server ?    P_CONTROL_HARD_RESET_SERVER_V1 : P_CONTROL_HARD_RESET_CLIENT_V1;  /* Initialize control channel authentication parameters */  session->tls_auth = session->opt->tls_auth;  tls_session_set_self_referential_pointers(session);  key_state_init (session, &session->key[KS_PRIMARY], time (NULL));  msg (D_TLS_DEBUG, "tls_session_init: new session object, sid=%s",       session_id_print (&session->session_id));}static voidtls_session_free (struct tls_session *session, bool clear){  int i;  for (i = 0; i < KS_SIZE; ++i)    key_state_free (&session->key[i], false);  if (clear)    CLEAR (*session);}static voidmove_session(struct tls_multi* multi, int dest, int src, bool reinit_src){  msg (D_TLS_DEBUG_LOW, "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, "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, "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 (time_t* earliest, int seconds_from_now) {  if (seconds_from_now > 0 && (seconds_from_now < *earliest || !*earliest))    *earliest = seconds_from_now;}/* * 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, time_t* wakeup, time_t current){  const struct key_state* lame = &session->key[KS_LAME_DUCK];  if (lame->state >= S_INITIAL)    {      ASSERT (lame->must_die); /* a lame duck key must always have an expiration */      if (current < lame->must_die)	{	  compute_earliest_wakeup (wakeup, lame->must_die - current);	  return false;	}      else	return true;    }  else if (lame->state == S_ERROR)    return true;  else    return false;}

⌨️ 快捷键说明

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