"Fossies" - the Fresh Open Source Software Archive

Member "mariadb-connector-c-3.0.8-src/libmariadb/ma_tls.c" (18 Dec 2018, 5787 Bytes) of package /linux/misc/mariadb-connector-c-3.0.8-src.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "ma_tls.c": 3.0.5-src_vs_3.0.6-src.

    1 /************************************************************************************
    2   Copyright (C) 2014 MariaDB Corporation AB
    3 
    4   This library is free software; you can redistribute it and/or
    5   modify it under the terms of the GNU Library General Public
    6   License as published by the Free Software Foundation; either
    7   version 2 of the License, or (at your option) any later version.
    8 
    9   This library is distributed in the hope that it will be useful,
   10   but WITHOUT ANY WARRANTY; without even the implied warranty of
   11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   12   Library General Public License for more details.
   13 
   14   You should have received a copy of the GNU Library General Public
   15   License along with this library; if not see <http://www.gnu.org/licenses>
   16   or write to the Free Software Foundation, Inc.,
   17   51 Franklin St., Fifth Floor, Boston, MA 02110, USA
   18 
   19  *************************************************************************************/
   20 
   21 /*
   22  * this is the abstraction layer for communication via SSL.
   23  * The following SSL libraries/variants are currently supported:
   24  * - openssl
   25  * - gnutls
   26  * - schannel (windows only)
   27  * 
   28  * Different SSL variants are implemented as plugins
   29  * On Windows schannel is implemented as (standard)
   30  * built-in plugin.
   31  */
   32 
   33 #ifdef HAVE_TLS
   34 
   35 #include <ma_global.h>
   36 #include <ma_sys.h>
   37 #include <ma_common.h>
   38 #include <string.h>
   39 #include <errmsg.h>
   40 #include <ma_pvio.h>
   41 #include <ma_tls.h>
   42 #include <mysql/client_plugin.h>
   43 #include <mariadb/ma_io.h>
   44 
   45 #ifdef HAVE_NONBLOCK
   46 #include <mariadb_async.h>
   47 #include <ma_context.h>
   48 #endif
   49 
   50 /* Errors should be handled via pvio callback function */
   51 my_bool ma_tls_initialized= FALSE;
   52 unsigned int mariadb_deinitialize_ssl= 1;
   53 
   54 const char *tls_protocol_version[]=
   55   {"SSLv3", "TLSv1.0", "TLSv1.1", "TLSv1.2", "TLSv1.3", "Unknown"};
   56 
   57 MARIADB_TLS *ma_pvio_tls_init(MYSQL *mysql)
   58 {
   59   MARIADB_TLS *ctls= NULL;
   60 
   61   if (!ma_tls_initialized)
   62     ma_tls_start(mysql->net.last_error, MYSQL_ERRMSG_SIZE);
   63 
   64   if (!(ctls= (MARIADB_TLS *)calloc(1, sizeof(MARIADB_TLS))))
   65   {
   66     return NULL;
   67   }
   68 
   69   /* register error routine and methods */
   70   ctls->pvio= mysql->net.pvio;
   71   if (!(ctls->ssl= ma_tls_init(mysql)))
   72   {
   73     free(ctls);
   74     ctls= NULL;
   75   }
   76   return ctls;
   77 }
   78 
   79 my_bool ma_pvio_tls_connect(MARIADB_TLS *ctls)
   80 {
   81   my_bool rc;
   82   
   83   if ((rc= ma_tls_connect(ctls)))
   84     ma_tls_close(ctls);
   85   return rc;
   86 }
   87 
   88 ssize_t ma_pvio_tls_read(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
   89 {
   90   return ma_tls_read(ctls, buffer, length);
   91 }
   92 
   93 ssize_t ma_pvio_tls_write(MARIADB_TLS *ctls, const uchar* buffer, size_t length)
   94 {
   95   return ma_tls_write(ctls, buffer, length);
   96 }
   97 
   98 my_bool ma_pvio_tls_close(MARIADB_TLS *ctls)
   99 {
  100   return ma_tls_close(ctls);
  101 }
  102 
  103 int ma_pvio_tls_verify_server_cert(MARIADB_TLS *ctls)
  104 {
  105   return ma_tls_verify_server_cert(ctls);
  106 }
  107 
  108 const char *ma_pvio_tls_cipher(MARIADB_TLS *ctls)
  109 {
  110   return ma_tls_get_cipher(ctls);
  111 }
  112 
  113 void ma_pvio_tls_end()
  114 {
  115   ma_tls_end();
  116 }
  117 
  118 int ma_pvio_tls_get_protocol_version_id(MARIADB_TLS *ctls)
  119 {
  120   return ma_tls_get_protocol_version(ctls);
  121 }
  122 
  123 const char *ma_pvio_tls_get_protocol_version(MARIADB_TLS *ctls)
  124 {
  125   int version;
  126 
  127   version= ma_tls_get_protocol_version(ctls);
  128   if (version < 0 || version > PROTOCOL_MAX)
  129     return tls_protocol_version[PROTOCOL_UNKNOWN];
  130   return tls_protocol_version[version];
  131 }
  132 
  133 static signed char ma_hex2int(char c)
  134 {
  135   if (c >= '0' && c <= '9')
  136     return c - '0';
  137   if (c >= 'A' && c <= 'F')
  138     return 10 + c - 'A';
  139   if (c >= 'a' && c <= 'f')
  140     return 10 + c - 'a';
  141   return -1;
  142 }
  143 
  144 static my_bool ma_pvio_tls_compare_fp(const char *cert_fp,
  145                                      unsigned int cert_fp_len,
  146                                      const char *fp, unsigned int fp_len)
  147 {
  148   char *p= (char *)fp,
  149        *c;
  150 
  151   /* check length */
  152   if (cert_fp_len != 20)
  153     return 1;
  154 
  155   /* We support two formats:
  156      2 digits hex numbers, separated by colons (length=59)
  157      20 * 2 digits hex numbers without separators (length = 40)
  158   */
  159   if (fp_len != (strchr(fp, ':') ? 59 : 40))
  160     return 1;
  161 
  162   for(c= (char *)cert_fp; c < cert_fp + cert_fp_len; c++)
  163   {
  164     signed char d1, d2;
  165     if (*p == ':')
  166       p++;
  167     if (p - fp > (int)fp_len -1)
  168       return 1;
  169     if ((d1 = ma_hex2int(*p)) == - 1 ||
  170         (d2 = ma_hex2int(*(p+1))) == -1 ||
  171         (char)(d1 * 16 + d2) != *c)
  172       return 1;
  173     p+= 2;
  174   }
  175   return 0;
  176 }
  177 
  178 my_bool ma_pvio_tls_check_fp(MARIADB_TLS *ctls, const char *fp, const char *fp_list)
  179 {
  180   unsigned int cert_fp_len= 64;
  181   char *cert_fp= NULL;
  182   my_bool rc=1;
  183   MYSQL *mysql= ctls->pvio->mysql;
  184 
  185   cert_fp= (char *)malloc(cert_fp_len);
  186 
  187   if ((cert_fp_len= ma_tls_get_finger_print(ctls, cert_fp, cert_fp_len)) < 1)
  188     goto end;
  189   if (fp)
  190     rc= ma_pvio_tls_compare_fp(cert_fp, cert_fp_len, fp, (unsigned int)strlen(fp));
  191   else if (fp_list)
  192   {
  193     MA_FILE *fp;
  194     char buff[255];
  195 
  196     if (!(fp = ma_open(fp_list, "r", mysql)))
  197       goto end;
  198 
  199     while (ma_gets(buff, sizeof(buff)-1, fp))
  200     {
  201       /* remove trailing new line character */
  202       char *pos= strchr(buff, '\r');
  203       if (!pos)
  204         pos= strchr(buff, '\n');
  205       if (pos)
  206         *pos= '\0';
  207         
  208       if (!ma_pvio_tls_compare_fp(cert_fp, cert_fp_len, buff, (unsigned int)strlen(buff)))
  209       {
  210         /* finger print is valid: close file and exit */
  211         ma_close(fp);
  212         rc= 0;
  213         goto end;
  214       }
  215     }
  216 
  217     /* No finger print matched - close file and return error */
  218     ma_close(fp);
  219   }
  220 
  221 end:
  222   if (cert_fp)
  223     free(cert_fp);
  224   if (rc)
  225   {
  226     my_set_error(mysql, CR_SSL_CONNECTION_ERROR, SQLSTATE_UNKNOWN,
  227                          ER(CR_SSL_CONNECTION_ERROR), 
  228                          "Fingerprint verification of server certificate failed");
  229   }
  230   return rc;
  231 }
  232 #endif /* HAVE_TLS */