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

📄 ssl.c

📁 OpenVPN is a robust and highly flexible tunneling application that uses all of the encryption, authe
💻 C
📖 第 1 页 / 共 5 页
字号:
 err:  mutex_unlock_static (L_SCRIPT);  return 0;                     /* Reject connection */}intget_max_tls_verify_id (struct tls_multi* multi){  if (multi)    return multi->session[TM_ACTIVE].verify_maxlevel;  else    return 0;}const char *tls_common_name (struct tls_multi* multi, bool null){  const char *ret = NULL;  if (multi)    ret = multi->session[TM_ACTIVE].common_name;  if (ret)    return ret;  else if (null)    return NULL;  else    return "UNDEF";}/* * Print debugging information on SSL/TLS session negotiation. */static voidinfo_callback (INFO_CALLBACK_SSL_CONST SSL * s, int where, int ret){  if (where & SSL_CB_LOOP)    {      msg (D_HANDSHAKE_VERBOSE, "SSL state (%s): %s",	   where & SSL_ST_CONNECT ? "connect" :	   where & SSL_ST_ACCEPT ? "accept" :	   "undefined", SSL_state_string_long (s));    }  else if (where & SSL_CB_ALERT)    {      msg (D_HANDSHAKE_VERBOSE, "SSL alert (%s): %s: %s",	   where & SSL_CB_READ ? "read" : "write",	   SSL_alert_type_string_long (ret),	   SSL_alert_desc_string_long (ret));    }}/* * Initialize SSL context. * All files are in PEM format. */SSL_CTX *init_ssl (bool server,	  const char *ca_file,	  const char *dh_file,	  const char *cert_file,	  const char *priv_key_file,	  const char *cipher_list){  SSL_CTX *ctx;  DH *dh;  BIO *bio;  if (server)    {      ctx = SSL_CTX_new (TLSv1_server_method ());      if (ctx == NULL)	msg (M_SSLERR, "SSL_CTX_new TLSv1_server_method");      SSL_CTX_set_tmp_rsa_callback (ctx, tmp_rsa_cb);      /* Get Diffie Hellman Parameters */      if (!(bio = BIO_new_file (dh_file, "r")))	msg (M_SSLERR, "Cannot open %s for DH parameters", dh_file);      dh = PEM_read_bio_DHparams (bio, NULL, NULL, NULL);      BIO_free (bio);      if (!dh)	msg (M_SSLERR, "Cannot load DH parameters from %s", dh_file);      if (!SSL_CTX_set_tmp_dh (ctx, dh))	msg (M_SSLERR, "SSL_CTX_set_tmp_dh");      msg (D_TLS_DEBUG_LOW, "Diffie-Hellman initialized with %d bit key",	   8 * DH_size (dh));      DH_free (dh);    }  else				/* if client */    {      ctx = SSL_CTX_new (TLSv1_client_method ());      if (ctx == NULL)	msg (M_SSLERR, "SSL_CTX_new TLSv1_client_method");    }  /* Set SSL options */  SSL_CTX_set_session_cache_mode (ctx, SSL_SESS_CACHE_OFF);  SSL_CTX_set_options (ctx, SSL_OP_SINGLE_DH_USE);  /* Set callback for getting password from user to decrypt private key */  SSL_CTX_set_default_passwd_cb (ctx, pem_password_callback);  /* Load Certificate */  if (!SSL_CTX_use_certificate_file (ctx, cert_file, SSL_FILETYPE_PEM))    msg (M_SSLERR, "Cannot load certificate file %s", cert_file);  /* Load Private Key */  if (!SSL_CTX_use_PrivateKey_file (ctx, priv_key_file, SSL_FILETYPE_PEM))    msg (M_SSLERR, "Cannot load private key file %s", priv_key_file);  warn_if_group_others_accessible (priv_key_file);  /* Check Private Key */  if (!SSL_CTX_check_private_key (ctx))    msg (M_SSLERR, "Private key does not match the certificate");  /* Load CA file for verifying peer supplied certificate */  if (!SSL_CTX_load_verify_locations (ctx, ca_file, NULL))    msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_CTX_load_verify_locations)", ca_file);  /* Load names of CAs from file and use it as a client CA list */  {    STACK_OF(X509_NAME) *cert_names;    cert_names = SSL_load_client_CA_file (ca_file);    if (!cert_names)      msg (M_SSLERR, "Cannot load CA certificate file %s (SSL_load_client_CA_file)", ca_file);    SSL_CTX_set_client_CA_list (ctx, cert_names);  }  /* Enable the use of certificate chains */  if (!SSL_CTX_use_certificate_chain_file (ctx, cert_file))    msg (M_SSLERR, "Cannot load certificate chain file %s (SSL_use_certificate_chain_file)", cert_file);  /* Require peer certificate verification */  SSL_CTX_set_verify (ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,		      verify_callback);  /* Connection information callback */  SSL_CTX_set_info_callback (ctx, info_callback);  /* Allowable ciphers */  if (cipher_list)    {      if (!SSL_CTX_set_cipher_list (ctx, cipher_list))	msg (M_SSLERR, "Problem with cipher list: %s", cipher_list);    }  return ctx;}/* * Print a one line summary of SSL/TLS session handshake. */static voidprint_details (SSL * c_ssl, const char *prefix){  SSL_CIPHER *ciph;  X509 *cert;  char s1[256];  char s2[256];  s1[0] = s2[0] = 0;  ciph = SSL_get_current_cipher (c_ssl);  openvpn_snprintf (s1, sizeof (s1), "%s %s, cipher %s %s",		    prefix,		    SSL_get_version (c_ssl),		    SSL_CIPHER_get_version (ciph),		    SSL_CIPHER_get_name (ciph));  cert = SSL_get_peer_certificate (c_ssl);  if (cert != NULL)    {      EVP_PKEY *pkey = X509_get_pubkey (cert);      if (pkey != NULL)	{	  if (pkey->type == EVP_PKEY_RSA && pkey->pkey.rsa != NULL	      && pkey->pkey.rsa->n != NULL)	    {	      openvpn_snprintf (s2, sizeof (s2), ", %d bit RSA",				BN_num_bits (pkey->pkey.rsa->n));	    }	  else if (pkey->type == EVP_PKEY_DSA && pkey->pkey.dsa != NULL		   && pkey->pkey.dsa->p != NULL)	    {	      openvpn_snprintf (s2, sizeof (s2), ", %d bit DSA",				BN_num_bits (pkey->pkey.dsa->p));	    }	  EVP_PKEY_free (pkey);	}      X509_free (cert);    }  /* The SSL API does not allow us to look at temporary RSA/DH keys,   * otherwise we should print their lengths too */  msg (D_HANDSHAKE, "%s%s", s1, s2);}/* * Show the TLS ciphers that are available for us to use * in the OpenSSL library. */voidshow_available_tls_ciphers (){  SSL_CTX *ctx;  SSL *ssl;  const char *cipher_name;  int priority = 0;  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");  printf ("Available TLS Ciphers,\n");  printf ("listed in order of preference:\n\n");  while ((cipher_name = SSL_get_cipher_list (ssl, priority++)))    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_NORMAL:      return "S_NORMAL";    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_HARD_RESET_CLIENT_V2:      return "P_CONTROL_HARD_RESET_CLIENT_V2";    case P_CONTROL_HARD_RESET_SERVER_V2:      return "P_CONTROL_HARD_RESET_SERVER_V2";    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, struct gc_arena *gc){  int i;  struct buffer out = alloc_buf_gc (256, gc);  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, gc));    }  return BSTR (&out);}/* * Given a key_method, return true if op * represents the required form of hard_reset. * * If key_method = 0, return true if any * form of hard reset is used. */static boolis_hard_reset (int op, int key_method){  if (!key_method || key_method == 1)    if (op == P_CONTROL_HARD_RESET_CLIENT_V1 || op == P_CONTROL_HARD_RESET_SERVER_V1)      return true;  if (!key_method || key_method >= 2)    if (op == P_CONTROL_HARD_RESET_CLIENT_V2 || op == P_CONTROL_HARD_RESET_SERVER_V2)      return true;  return false;}/* * 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 (struct tls_multi* multi, 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 (multi->mutex);      i = BIO_write (bio, BPTR (buf), BLEN (buf));      //mutex_lock (multi->mutex);      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 (struct tls_multi* multi, 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 (multi->mutex);      i = BIO_read (bio, BPTR (buf), len);      //mutex_lock (multi->mutex);#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 tls_multi *multi, struct key_state *ks, struct buffer *buf){  return bio_write (multi, ks->ssl_bio, buf, "tls_write_plaintext");}static inline intkey_state_write_ciphertext (struct tls_multi *multi, struct key_state *ks, struct buffer *buf){  return bio_write (multi, ks->ct_in, buf, "tls_write_ciphertext");}static inline intkey_state_read_plaintext (struct tls_multi *multi, struct key_state *ks, struct buffer *buf,			  int maxlen){  return bio_read (multi, ks->ssl_bio, buf, maxlen, "tls_read_plaintext");}

⌨️ 快捷键说明

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