viosslfactories.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:11k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. #include "vio_priv.h"
  14. #ifdef HAVE_OPENSSL
  15. static bool     ssl_algorithms_added    = FALSE;
  16. static bool     ssl_error_strings_loaded= FALSE;
  17. static int      verify_depth = 0;
  18. static int      verify_error = X509_V_OK;
  19. static unsigned char dh512_p[]=
  20. {
  21.   0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
  22.   0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
  23.   0xED,0x94,0xEF,0x9C,0x8A,0x44,0x03,0xED,0x57,0x46,0x50,0xD3,
  24.   0x69,0x99,0xDB,0x29,0xD7,0x76,0x27,0x6B,0xA2,0xD3,0xD4,0x12,
  25.   0xE2,0x18,0xF4,0xDD,0x1E,0x08,0x4C,0xF6,0xD8,0x00,0x3E,0x7C,
  26.   0x47,0x74,0xE8,0x33,
  27. };
  28. static unsigned char dh512_g[]={
  29.   0x02,
  30. };
  31. static DH *get_dh512(void)
  32. {
  33.   DH *dh;
  34.   if ((dh=DH_new()))
  35.   {
  36.     dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
  37.     dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
  38.     if (! dh->p || ! dh->g)
  39.     {
  40.       DH_free(dh);
  41.       dh=0;
  42.     }
  43.   }
  44.   return(dh);
  45. }
  46. static void
  47. report_errors()
  48. {
  49.   unsigned long l;
  50.   const char* file;
  51.   const char* data;
  52.   int line,flags;
  53.   DBUG_ENTER("report_errors");
  54.   while ((l=ERR_get_error_line_data(&file,&line,&data,&flags)) != 0)
  55.   {
  56. #ifndef DBUG_OFF /* Avoid warning */
  57.     char buf[200];
  58.     DBUG_PRINT("error", ("OpenSSL: %s:%s:%d:%sn", ERR_error_string(l,buf),
  59.  file,line,(flags & ERR_TXT_STRING) ? data : "")) ;
  60. #endif
  61.   }
  62.   DBUG_VOID_RETURN;
  63. }
  64. static int
  65. vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
  66. {
  67.   DBUG_ENTER("vio_set_cert_stuff");
  68.   DBUG_PRINT("enter", ("ctx=%p, cert_file=%s, key_file=%s",
  69.        ctx, cert_file, key_file));
  70.   if (cert_file != NULL)
  71.   {
  72.     if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <= 0)
  73.     {
  74.       DBUG_PRINT("error",("unable to get certificate from '%s'n",cert_file));
  75.       /* FIX stderr */
  76.       fprintf(stderr,"Error when connection to server using SSL:");
  77.       ERR_print_errors_fp(stderr);
  78.       fprintf(stderr,"Unable to get certificate from '%s'n", cert_file);
  79.       fflush(stderr);
  80.       DBUG_RETURN(0);
  81.     }
  82.     if (key_file == NULL)
  83.       key_file = cert_file;
  84.     if (SSL_CTX_use_PrivateKey_file(ctx,key_file,
  85.     SSL_FILETYPE_PEM) <= 0)
  86.     {
  87.       DBUG_PRINT("error", ("unable to get private key from '%s'n",key_file));
  88.       /* FIX stderr */
  89.       fprintf(stderr,"Error when connection to server using SSL:");
  90.       ERR_print_errors_fp(stderr);
  91.       fprintf(stderr,"Unable to get private key from '%s'n", cert_file);
  92.       fflush(stderr);      
  93.       DBUG_RETURN(0);
  94.     }
  95.     /*
  96.       If we are using DSA, we can copy the parameters from the private key
  97.       Now we know that a key and cert have been set against the SSL context
  98.     */
  99.     if (!SSL_CTX_check_private_key(ctx))
  100.     {
  101.       DBUG_PRINT("error",
  102.  ("Private key does not match the certificate public keyn"));
  103.       DBUG_RETURN(0);
  104.     }
  105.   }
  106.   DBUG_RETURN(1);
  107. }
  108. static int
  109. vio_verify_callback(int ok, X509_STORE_CTX *ctx)
  110. {
  111.   char buf[256];
  112.   X509* err_cert;
  113.   int err,depth;
  114.   DBUG_ENTER("vio_verify_callback");
  115.   DBUG_PRINT("enter", ("ok=%d, ctx=%p", ok, ctx));
  116.   err_cert=X509_STORE_CTX_get_current_cert(ctx);
  117.   err=    X509_STORE_CTX_get_error(ctx);
  118.   depth=   X509_STORE_CTX_get_error_depth(ctx);
  119.   X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf));
  120.   if (!ok)
  121.   {
  122.     DBUG_PRINT("error",("verify error: num: %d : '%s'n",err,
  123. X509_verify_cert_error_string(err)));
  124.     if (verify_depth >= depth)
  125.     {
  126.       ok=1;
  127.       verify_error=X509_V_OK;
  128.     }
  129.     else
  130.     {
  131.       verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG;
  132.     }
  133.   }
  134.   switch (ctx->error) {
  135.   case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
  136.     X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,256);
  137.     DBUG_PRINT("info",("issuer= %sn",buf));
  138.     break;
  139.   case X509_V_ERR_CERT_NOT_YET_VALID:
  140.   case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
  141.     DBUG_PRINT("error", ("notBefore"));
  142.     /*ASN1_TIME_print_fp(stderr,X509_get_notBefore(ctx->current_cert));*/
  143.     break;
  144.   case X509_V_ERR_CERT_HAS_EXPIRED:
  145.   case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
  146.     DBUG_PRINT("error", ("notAfter error"));
  147.     /*ASN1_TIME_print_fp(stderr,X509_get_notAfter(ctx->current_cert));*/
  148.     break;
  149.   }
  150.   DBUG_PRINT("exit", ("%d", ok));
  151.   DBUG_RETURN(ok);
  152. }
  153. #ifdef __NETWARE__
  154. /* NetWare SSL cleanup */
  155. void netware_ssl_cleanup()
  156. {
  157.   /* free memory from SSL_library_init() */
  158.   EVP_cleanup();
  159.   /* free global X509 method */
  160.   X509_STORE_method_cleanup();
  161.   /* free the thread_hash error table */
  162.   ERR_free_state_table();
  163. }
  164. /* NetWare SSL initialization */
  165. static void netware_ssl_init()
  166. {
  167.   /* cleanup OpenSSL library */
  168.   NXVmRegisterExitHandler(netware_ssl_cleanup, NULL);
  169. }
  170. #endif /* __NETWARE__ */
  171. /************************ VioSSLConnectorFd **********************************/
  172. /*
  173.   TODO:
  174.        Add option --verify to mysql to be able to change verification mode
  175. */
  176. struct st_VioSSLConnectorFd *
  177. new_VioSSLConnectorFd(const char* key_file,
  178.       const char* cert_file,
  179.       const char* ca_file,
  180.       const char* ca_path,
  181.       const char* cipher)
  182. {
  183.   int verify = SSL_VERIFY_NONE;
  184.   struct st_VioSSLConnectorFd* ptr;
  185.   int result;
  186.   DH *dh;
  187.   DBUG_ENTER("new_VioSSLConnectorFd");
  188.   DBUG_PRINT("enter",
  189.      ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
  190.       key_file, cert_file, ca_path, ca_file, cipher));
  191.   if (!(ptr=((struct st_VioSSLConnectorFd*)
  192.      my_malloc(sizeof(struct st_VioSSLConnectorFd),MYF(0)))))
  193.     DBUG_RETURN(0);
  194.   ptr->ssl_context= 0;
  195.   ptr->ssl_method=  0;
  196.   /* FIXME: constants! */
  197.   if (!ssl_algorithms_added)
  198.   {
  199.     DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()"));
  200.     ssl_algorithms_added = TRUE;
  201.     SSL_library_init();
  202.     OpenSSL_add_all_algorithms();
  203.   }
  204. #ifdef __NETWARE__
  205.   netware_ssl_init();
  206. #endif
  207.   if (!ssl_error_strings_loaded)
  208.   {
  209.     DBUG_PRINT("info", ("todo:SSL_load_error_strings()"));
  210.     ssl_error_strings_loaded = TRUE;
  211.     SSL_load_error_strings();
  212.   }
  213.   ptr->ssl_method = TLSv1_client_method();
  214.   ptr->ssl_context = SSL_CTX_new(ptr->ssl_method);
  215.   DBUG_PRINT("info", ("ssl_context: %p",ptr->ssl_context));
  216.   if (ptr->ssl_context == 0)
  217.   {
  218.     DBUG_PRINT("error", ("SSL_CTX_new failed"));
  219.     report_errors();
  220.     goto ctor_failure;
  221.   }
  222.   /*
  223.     SSL_CTX_set_options
  224.     SSL_CTX_set_info_callback
  225.    */
  226.   if (cipher)
  227.   {
  228.     result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher);
  229.     DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result));
  230.   }
  231.   SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback);
  232.   if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1)
  233.   {
  234.     DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
  235.     report_errors();
  236.     goto ctor_failure;
  237.   }
  238.   if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file,ca_path) == 0)
  239.   {
  240.     DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
  241.     if (SSL_CTX_set_default_verify_paths(ptr->ssl_context) == 0)
  242.     {
  243.       DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
  244.       report_errors();
  245.       goto ctor_failure;
  246.     }
  247.   } 
  248.   /* DH stuff */
  249.   dh=get_dh512();
  250.   SSL_CTX_set_tmp_dh(ptr->ssl_context,dh);
  251.   DH_free(dh);
  252.   DBUG_RETURN(ptr);
  253. ctor_failure:
  254.   DBUG_PRINT("exit", ("there was an error"));
  255.   my_free((gptr)ptr,MYF(0));
  256.   DBUG_RETURN(0);
  257. }
  258. /************************ VioSSLAcceptorFd **********************************/
  259. /*
  260.   TODO:
  261.        Add option --verify to mysqld to be able to change verification mode
  262. */
  263. struct st_VioSSLAcceptorFd*
  264. new_VioSSLAcceptorFd(const char *key_file,
  265.      const char *cert_file,
  266.      const char *ca_file,
  267.      const char *ca_path,
  268.      const char *cipher)
  269. {
  270.   int verify = (SSL_VERIFY_PEER |
  271. SSL_VERIFY_CLIENT_ONCE);
  272.   struct st_VioSSLAcceptorFd* ptr;
  273.   int result;
  274.   DH *dh;
  275.   DBUG_ENTER("new_VioSSLAcceptorFd");
  276.   DBUG_PRINT("enter",
  277.      ("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
  278.       key_file, cert_file, ca_path, ca_file, cipher));
  279.   ptr= ((struct st_VioSSLAcceptorFd*)
  280. my_malloc(sizeof(struct st_VioSSLAcceptorFd),MYF(0)));
  281.   ptr->ssl_context=0;
  282.   ptr->ssl_method=0;
  283.   /* FIXME: constants! */
  284.   ptr->session_id_context= ptr;
  285.   if (!ssl_algorithms_added)
  286.   {
  287.     DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()"));
  288.     ssl_algorithms_added = TRUE;
  289.     SSL_library_init();
  290.     OpenSSL_add_all_algorithms();
  291.   }
  292. #ifdef __NETWARE__
  293.   netware_ssl_init();
  294. #endif
  295.   if (!ssl_error_strings_loaded)
  296.   {
  297.     DBUG_PRINT("info", ("todo: SSL_load_error_strings()"));
  298.     ssl_error_strings_loaded = TRUE;
  299.     SSL_load_error_strings();
  300.   }
  301.   ptr->ssl_method=  TLSv1_server_method();
  302.   ptr->ssl_context= SSL_CTX_new(ptr->ssl_method);
  303.   if (ptr->ssl_context == 0)
  304.   {
  305.     DBUG_PRINT("error", ("SSL_CTX_new failed"));
  306.     report_errors();
  307.     goto ctor_failure;
  308.   }
  309.   if (cipher)
  310.   {
  311.     result=SSL_CTX_set_cipher_list(ptr->ssl_context, cipher);
  312.     DBUG_PRINT("info",("SSL_set_cipher_list() returned %d",result));
  313.   }
  314.   /* SSL_CTX_set_quiet_shutdown(ctx,1); */
  315.   SSL_CTX_sess_set_cache_size(ptr->ssl_context,128);
  316.   /* DH? */
  317.   SSL_CTX_set_verify(ptr->ssl_context, verify, vio_verify_callback);
  318.   SSL_CTX_set_session_id_context(ptr->ssl_context,
  319.  (const uchar*) &(ptr->session_id_context),
  320.  sizeof(ptr->session_id_context));
  321.   /*
  322.     SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(CAfile));
  323.   */
  324.   if (vio_set_cert_stuff(ptr->ssl_context, cert_file, key_file) == -1)
  325.   {
  326.     DBUG_PRINT("error", ("vio_set_cert_stuff failed"));
  327.     report_errors();
  328.     goto ctor_failure;
  329.   }
  330.   if (SSL_CTX_load_verify_locations( ptr->ssl_context, ca_file, ca_path) == 0)
  331.   {
  332.     DBUG_PRINT("warning", ("SSL_CTX_load_verify_locations failed"));
  333.     if (SSL_CTX_set_default_verify_paths(ptr->ssl_context)==0)
  334.     {
  335.       DBUG_PRINT("error", ("SSL_CTX_set_default_verify_paths failed"));
  336.       report_errors();
  337.       goto ctor_failure;
  338.     }
  339.   }
  340.   /* DH stuff */
  341.   dh=get_dh512();
  342.   SSL_CTX_set_tmp_dh(ptr->ssl_context,dh);
  343.   DH_free(dh);
  344.   DBUG_RETURN(ptr);
  345. ctor_failure:
  346.   DBUG_PRINT("exit", ("there was an error"));
  347.   my_free((gptr) ptr,MYF(0));
  348.   DBUG_RETURN(0);
  349. }
  350. #endif /* HAVE_OPENSSL */