• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

SSLConfig.cc

Go to the documentation of this file.
00001 /** @file
00002 
00003   A brief file description
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 
00024 /*************************** -*- Mod: C++ -*- ******************************
00025   SSLConfig.cc
00026    Created On      : 07/20/2000
00027 
00028    Description:
00029    SSL Configurations
00030  ****************************************************************************/
00031 
00032 #include "libts.h"
00033 #include "I_Layout.h"
00034 
00035 #include <string.h>
00036 #include "P_Net.h"
00037 #include "P_SSLConfig.h"
00038 #include "P_SSLUtils.h"
00039 #include "P_SSLCertLookup.h"
00040 #include <records/I_RecHttp.h>
00041 
00042 int SSLConfig::configid = 0;
00043 int SSLCertificateConfig::configid = 0;
00044 int SSLConfigParams::ssl_maxrecord = 0;
00045 bool SSLConfigParams::ssl_allow_client_renegotiation = false;
00046 bool SSLConfigParams::ssl_ocsp_enabled = false;
00047 int SSLConfigParams::ssl_ocsp_cache_timeout = 3600;
00048 int SSLConfigParams::ssl_ocsp_request_timeout = 10;
00049 int SSLConfigParams::ssl_ocsp_update_period = 60;
00050 init_ssl_ctx_func SSLConfigParams::init_ssl_ctx_cb = NULL;
00051 
00052 static ConfigUpdateHandler<SSLCertificateConfig> * sslCertUpdate;
00053 
00054 SSLConfigParams::SSLConfigParams()
00055 {
00056   serverCertPathOnly =
00057     serverCertChainFilename =
00058     configFilePath =
00059     serverCACertFilename =
00060     serverCACertPath =
00061     clientCertPath =
00062     clientKeyPath =
00063     clientCACertFilename =
00064     clientCACertPath =
00065     cipherSuite =
00066     client_cipherSuite =
00067     serverKeyPathOnly = NULL;
00068 
00069   clientCertLevel = client_verify_depth = verify_depth = clientVerify = 0;
00070 
00071   ssl_ctx_options = 0;
00072   ssl_client_ctx_protocols = 0;
00073   ssl_session_cache = SSL_SESSION_CACHE_MODE_SERVER;
00074   ssl_session_cache_size = 1024*20;
00075   ssl_session_cache_timeout = 0;
00076 }
00077 
00078 SSLConfigParams::~SSLConfigParams()
00079 {
00080   cleanup();
00081 }
00082 
00083 void
00084 SSLConfigParams::cleanup()
00085 {
00086   ats_free_null(serverCertChainFilename);
00087   ats_free_null(serverCACertFilename);
00088   ats_free_null(serverCACertPath);
00089   ats_free_null(clientCertPath);
00090   ats_free_null(clientKeyPath);
00091   ats_free_null(clientCACertFilename);
00092   ats_free_null(clientCACertPath);
00093   ats_free_null(configFilePath);
00094   ats_free_null(serverCertPathOnly);
00095   ats_free_null(serverKeyPathOnly);
00096   ats_free_null(cipherSuite);
00097   ats_free_null(client_cipherSuite);
00098 
00099   clientCertLevel = client_verify_depth = verify_depth = clientVerify = 0;
00100 }
00101 
00102 /**  set_paths_helper
00103 
00104  If path is *not* absolute, consider it relative to PREFIX
00105  if it's empty, just take SYSCONFDIR, otherwise we can take it as-is
00106  if final_path is NULL, it will not be updated.
00107 
00108  XXX: Add handling for Windows?
00109  */
00110 static void
00111 set_paths_helper(const char *path, const char *filename, char **final_path, char **final_filename)
00112 {
00113   if (final_path) {
00114     if (path && path[0] != '/') {
00115       *final_path = Layout::get()->relative_to(Layout::get()->prefix, path);
00116     } else if (!path || path[0] == '\0'){
00117       *final_path = ats_strdup(Layout::get()->sysconfdir);
00118     } else {
00119       *final_path = ats_strdup(path);
00120     }
00121   }
00122 
00123   if (final_filename) {
00124     *final_filename = filename ? Layout::get()->relative_to(path, filename) : NULL;
00125   }
00126 
00127 }
00128 
00129 void
00130 SSLConfigParams::initialize()
00131 {
00132   char *serverCertRelativePath = NULL;
00133   char *ssl_server_private_key_path = NULL;
00134   char *CACertRelativePath = NULL;
00135   char *ssl_client_cert_filename = NULL;
00136   char *ssl_client_cert_path = NULL;
00137   char *ssl_client_private_key_filename = NULL;
00138   char *ssl_client_private_key_path = NULL;
00139   char *clientCACertRelativePath = NULL;
00140   char *multicert_config_file = NULL;
00141   char *ssl_server_ca_cert_filename = NULL;
00142   char *ssl_client_ca_cert_filename = NULL;
00143 
00144   cleanup();
00145 
00146   //+++++++++++++++++++++++++ Server part +++++++++++++++++++++++++++++++++
00147   verify_depth = 7;
00148 
00149   REC_ReadConfigInt32(clientCertLevel, "proxy.config.ssl.client.certification_level");
00150   REC_ReadConfigStringAlloc(cipherSuite, "proxy.config.ssl.server.cipher_suite");
00151   REC_ReadConfigStringAlloc(client_cipherSuite, "proxy.config.ssl.client.cipher_suite");
00152 
00153   int options;
00154   int client_ssl_options;
00155   REC_ReadConfigInteger(options, "proxy.config.ssl.SSLv2");
00156   if (!options)
00157     ssl_ctx_options |= SSL_OP_NO_SSLv2;
00158   REC_ReadConfigInteger(options, "proxy.config.ssl.SSLv3");
00159   if (!options)
00160     ssl_ctx_options |= SSL_OP_NO_SSLv3;
00161   REC_ReadConfigInteger(options, "proxy.config.ssl.TLSv1");
00162   if (!options)
00163     ssl_ctx_options |= SSL_OP_NO_TLSv1;
00164 
00165   REC_ReadConfigInteger(client_ssl_options, "proxy.config.ssl.client.SSLv2");
00166   if (!client_ssl_options)
00167     ssl_client_ctx_protocols |= SSL_OP_NO_SSLv2;
00168   REC_ReadConfigInteger(client_ssl_options, "proxy.config.ssl.client.SSLv3");
00169   if (!client_ssl_options)
00170     ssl_client_ctx_protocols |= SSL_OP_NO_SSLv3;
00171   REC_ReadConfigInteger(client_ssl_options, "proxy.config.ssl.client.TLSv1");
00172   if (!client_ssl_options)
00173     ssl_client_ctx_protocols |= SSL_OP_NO_TLSv1;
00174 
00175   // These are not available in all versions of OpenSSL (e.g. CentOS6). Also see http://s.apache.org/TS-2355.
00176 #ifdef SSL_OP_NO_TLSv1_1
00177   REC_ReadConfigInteger(options, "proxy.config.ssl.TLSv1_1");
00178   if (!options)
00179     ssl_ctx_options |= SSL_OP_NO_TLSv1_1;
00180 
00181   REC_ReadConfigInteger(client_ssl_options, "proxy.config.ssl.client.TLSv1_1");
00182   if (!client_ssl_options)
00183     ssl_client_ctx_protocols |= SSL_OP_NO_TLSv1_1;
00184 #endif
00185 #ifdef SSL_OP_NO_TLSv1_2
00186   REC_ReadConfigInteger(options, "proxy.config.ssl.TLSv1_2");
00187   if (!options)
00188     ssl_ctx_options |= SSL_OP_NO_TLSv1_2;
00189 
00190   REC_ReadConfigInteger(client_ssl_options, "proxy.config.ssl.client.TLSv1_2");
00191   if (!client_ssl_options)
00192     ssl_client_ctx_protocols |= SSL_OP_NO_TLSv1_2;
00193 #endif
00194 
00195 #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE
00196   REC_ReadConfigInteger(options, "proxy.config.ssl.server.honor_cipher_order");
00197   if (options)
00198     ssl_ctx_options |= SSL_OP_CIPHER_SERVER_PREFERENCE;
00199 #endif
00200 
00201   REC_ReadConfigInteger(options, "proxy.config.ssl.compression");
00202   if (!options) {
00203 #ifdef SSL_OP_NO_COMPRESSION
00204     /* OpenSSL >= 1.0 only */
00205     ssl_ctx_options |= SSL_OP_NO_COMPRESSION;
00206 #elif OPENSSL_VERSION_NUMBER >= 0x00908000L
00207     sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
00208 #endif
00209   }
00210 
00211   // Enable ephemeral DH parameters for the case where we use a cipher with DH forward security.
00212 #ifdef SSL_OP_SINGLE_DH_USE
00213   ssl_ctx_options |= SSL_OP_SINGLE_DH_USE;
00214 #endif
00215 
00216 #ifdef SSL_OP_SINGLE_ECDH_USE
00217   ssl_ctx_options |= SSL_OP_SINGLE_ECDH_USE;
00218 #endif
00219 
00220   // Enable all SSL compatibility workarounds.
00221   ssl_ctx_options |= SSL_OP_ALL;
00222 
00223   // According to OpenSSL source, applications must enable this if they support the Server Name extension. Since
00224   // we do, then we ought to enable this. Httpd also enables this unconditionally.
00225 #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
00226   ssl_ctx_options |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
00227 #endif
00228 
00229   REC_ReadConfigStringAlloc(serverCertChainFilename, "proxy.config.ssl.server.cert_chain.filename");
00230   REC_ReadConfigStringAlloc(serverCertRelativePath, "proxy.config.ssl.server.cert.path");
00231   set_paths_helper(serverCertRelativePath, NULL, &serverCertPathOnly, NULL);
00232   ats_free(serverCertRelativePath);
00233 
00234   REC_ReadConfigStringAlloc(multicert_config_file, "proxy.config.ssl.server.multicert.filename");
00235   set_paths_helper(Layout::get()->sysconfdir, multicert_config_file, NULL, &configFilePath);
00236   ats_free(multicert_config_file);
00237 
00238   REC_ReadConfigStringAlloc(ssl_server_private_key_path, "proxy.config.ssl.server.private_key.path");
00239   set_paths_helper(ssl_server_private_key_path, NULL, &serverKeyPathOnly, NULL);
00240   ats_free(ssl_server_private_key_path);
00241 
00242   REC_ReadConfigStringAlloc(ssl_server_ca_cert_filename, "proxy.config.ssl.CA.cert.filename");
00243   REC_ReadConfigStringAlloc(CACertRelativePath, "proxy.config.ssl.CA.cert.path");
00244   set_paths_helper(CACertRelativePath, ssl_server_ca_cert_filename, &serverCACertPath, &serverCACertFilename);
00245   ats_free(ssl_server_ca_cert_filename);
00246   ats_free(CACertRelativePath);
00247 
00248   // SSL session cache configurations
00249   REC_ReadConfigInteger(ssl_session_cache, "proxy.config.ssl.session_cache");
00250   REC_ReadConfigInteger(ssl_session_cache_size, "proxy.config.ssl.session_cache.size");
00251   REC_ReadConfigInteger(ssl_session_cache_timeout, "proxy.config.ssl.session_cache.timeout");
00252 
00253   // SSL record size
00254   REC_EstablishStaticConfigInt32(ssl_maxrecord, "proxy.config.ssl.max_record_size");
00255 
00256   // SSL OCSP Stapling configurations
00257   REC_ReadConfigInt32(ssl_ocsp_enabled, "proxy.config.ssl.ocsp.enabled");
00258   REC_EstablishStaticConfigInt32(ssl_ocsp_cache_timeout, "proxy.config.ssl.ocsp.cache_timeout");
00259   REC_EstablishStaticConfigInt32(ssl_ocsp_request_timeout, "proxy.config.ssl.ocsp.request_timeout");
00260   REC_EstablishStaticConfigInt32(ssl_ocsp_update_period, "proxy.config.ssl.ocsp.update_period");
00261 
00262   // ++++++++++++++++++++++++ Client part ++++++++++++++++++++
00263   client_verify_depth = 7;
00264   REC_ReadConfigInt32(clientVerify, "proxy.config.ssl.client.verify.server");
00265 
00266   ssl_client_cert_filename = NULL;
00267   ssl_client_cert_path = NULL;
00268   REC_ReadConfigStringAlloc(ssl_client_cert_filename, "proxy.config.ssl.client.cert.filename");
00269   REC_ReadConfigStringAlloc(ssl_client_cert_path, "proxy.config.ssl.client.cert.path");
00270   set_paths_helper(ssl_client_cert_path, ssl_client_cert_filename, NULL, &clientCertPath);
00271   ats_free_null(ssl_client_cert_filename);
00272   ats_free_null(ssl_client_cert_path);
00273 
00274   REC_ReadConfigStringAlloc(ssl_client_private_key_filename, "proxy.config.ssl.client.private_key.filename");
00275   REC_ReadConfigStringAlloc(ssl_client_private_key_path, "proxy.config.ssl.client.private_key.path");
00276   set_paths_helper(ssl_client_private_key_path, ssl_client_private_key_filename, NULL, &clientKeyPath);
00277   ats_free_null(ssl_client_private_key_filename);
00278   ats_free_null(ssl_client_private_key_path);
00279 
00280   REC_ReadConfigStringAlloc(ssl_client_ca_cert_filename, "proxy.config.ssl.client.CA.cert.filename");
00281   REC_ReadConfigStringAlloc(clientCACertRelativePath, "proxy.config.ssl.client.CA.cert.path");
00282   set_paths_helper(clientCACertRelativePath, ssl_client_ca_cert_filename, &clientCACertPath, &clientCACertFilename);
00283   ats_free(clientCACertRelativePath);
00284   ats_free(ssl_client_ca_cert_filename);
00285 
00286   REC_ReadConfigInt32(ssl_allow_client_renegotiation, "proxy.config.ssl.allow_client_renegotiation");
00287 }
00288 
00289 void
00290 SSLConfig::startup()
00291 {
00292   reconfigure();
00293 }
00294 
00295 void
00296 SSLConfig::reconfigure()
00297 {
00298   SSLConfigParams *params;
00299   params = new SSLConfigParams;
00300   params->initialize();         // re-read configuration
00301   configid = configProcessor.set(configid, params);
00302 }
00303 
00304 SSLConfigParams *
00305 SSLConfig::acquire()
00306 {
00307   return ((SSLConfigParams *) configProcessor.get(configid));
00308 }
00309 
00310 void
00311 SSLConfig::release(SSLConfigParams * params)
00312 {
00313   configProcessor.release(configid, params);
00314 }
00315 
00316 void
00317 SSLCertificateConfig::startup()
00318 {
00319   sslCertUpdate = new ConfigUpdateHandler<SSLCertificateConfig>();
00320   sslCertUpdate->attach("proxy.config.ssl.server.multicert.filename");
00321   sslCertUpdate->attach("proxy.config.ssl.server.cert.path");
00322   sslCertUpdate->attach("proxy.config.ssl.server.private_key.path");
00323   sslCertUpdate->attach("proxy.config.ssl.server.cert_chain.filename");
00324 
00325   reconfigure();
00326 }
00327 
00328 void
00329 SSLCertificateConfig::reconfigure()
00330 {
00331   SSLConfig::scoped_config params;
00332   SSLCertLookup * lookup = new SSLCertLookup();
00333 
00334   // Test SSL certificate loading startup. With large numbers of certificates, reloading can take time, so delay
00335   // twice the healthcheck period to simulate a loading a large certificate set.
00336   if (is_action_tag_set("test.multicert.delay")) {
00337     const int secs = 60;
00338     Debug("ssl", "delaying certificate reload by %dsecs", secs);
00339     ink_hrtime_sleep(HRTIME_SECONDS(secs));
00340   }
00341 
00342   if (SSLParseCertificateConfiguration(params, lookup)) {
00343     configid = configProcessor.set(configid, lookup);
00344   } else {
00345     delete lookup;
00346   }
00347 }
00348 
00349 SSLCertLookup *
00350 SSLCertificateConfig::acquire()
00351 {
00352   return (SSLCertLookup *)configProcessor.get(configid);
00353 }
00354 
00355 void
00356 SSLCertificateConfig::release(SSLCertLookup * lookup)
00357 {
00358   configProcessor.release(configid, lookup);
00359 }
00360 

Generated by  doxygen 1.7.1