From 727379743e6b30687c0aea2e47f02657cb3ea623 Mon Sep 17 00:00:00 2001 From: Tomas Jelinek Date: Tue, 8 Mar 2016 15:20:42 +0100 Subject: [PATCH] add config settings for SSL options and ciphers --- pcsd/pcsd.conf | 9 +++++++++ pcsd/ssl.rb | 46 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/pcsd/pcsd.conf b/pcsd/pcsd.conf index 5ac8bc76b..e63603c73 100644 --- a/pcsd/pcsd.conf +++ b/pcsd/pcsd.conf @@ -5,5 +5,14 @@ PCSD_DEBUG=false DISABLE_GUI=false # Set web UI sesions lifetime SESSION_LIFETIME=3600 + +# SSL settings +# set SSL options delimited by ',' character +# list of valid options can be obtained by running +# ruby -e 'require "openssl"; puts OpenSSL::SSL.constants.grep /^OP_/' +#PCSD_SSL_OPTIONS='OP_NO_SSLv2,OP_NO_SSLv3,OP_NO_TLSv1,OP_NO_TLSv1_1' +# set SSL ciphers +#PCSD_SSL_CIPHERS='DEFAULT:!RC4:!3DES:@STRENGTH!' + # Do not change RACK_ENV=production diff --git a/pcsd/ssl.rb b/pcsd/ssl.rb index 2858574c2..38dd25bd3 100644 --- a/pcsd/ssl.rb +++ b/pcsd/ssl.rb @@ -26,6 +26,46 @@ def generate_cert_key_pair(server_name) return crt, key end +def get_ssl_options() + default_options = ( + OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 | + OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1 + ) + if ENV['PCSD_SSL_OPTIONS'] + options = 0 + ENV['PCSD_SSL_OPTIONS'].split(',').each { |op| + op_cleaned = op.strip() + begin + if not op_cleaned.start_with?('OP_') + raise NameError.new('options must start with OP_') + end + op_constant = OpenSSL::SSL.const_get(op_cleaned) + options |= op_constant + rescue NameError => e + $logger.error( + "SSL configuration error '#{e}', unknown SSL option '#{op}'" + ) + exit + rescue => e + $logger.error("SSL configuration error '#{e}'") + exit + end + } + return options + end + return default_options +end + +def run_server(server, webrick_options) + ciphers = 'DEFAULT:!RC4:!3DES:@STRENGTH!' + ciphers = ENV['PCSD_SSL_CIPHERS'] if ENV['PCSD_SSL_CIPHERS'] + # no need to validate ciphers, ssl context will validate them for us + + server.run(Sinatra::Application, webrick_options) { |server_instance| + server_instance.ssl_context.ciphers = ciphers + } +end + if not File.exists?(CRT_FILE) or not File.exists?(KEY_FILE) crt, key = generate_cert_key_pair(server_name) File.open(CRT_FILE, 'w',0700) {|f| f.write(crt)} @@ -55,7 +95,7 @@ def generate_cert_key_pair(server_name) :SSLCertificate => OpenSSL::X509::Certificate.new(crt), :SSLPrivateKey => OpenSSL::PKey::RSA.new(key), :SSLCertName => [[ "CN", server_name ]], - :SSLOptions => OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3, + :SSLOptions => get_ssl_options(), } server = ::Rack::Handler::WEBrick @@ -79,9 +119,9 @@ def generate_cert_key_pair(server_name) require 'pcsd' begin - server.run(Sinatra::Application, webrick_options) + run_server(server, webrick_options) rescue Errno::EAFNOSUPPORT webrick_options[:BindAddress] = '0.0.0.0' webrick_options[:Host] = '0.0.0.0' - server.run(Sinatra::Application, webrick_options) + run_server(server, webrick_options) end