From acf455911cd0b97e247bcd06e365a3fea0ba208c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Thu, 8 Dec 2016 13:49:11 +0100
Subject: [PATCH] Default SSL_ca_file to system-wide store
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This patch provides a default value for a file with CA certificates.
Similar idea was implemented in upstream version 1.968.
This patch also decouples default values for CA and client
certificates. This allows to specify SSL_cert_file and SSL_key_file
while not specifying SSL_ca_path and SSL_ca_file to still use
default values for them.
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
lib/IO/Socket/SSL.pm | 65 +++++++++++++++++++++++++++++++++++-----------------
1 file changed, 44 insertions(+), 21 deletions(-)
diff --git a/lib/IO/Socket/SSL.pm b/lib/IO/Socket/SSL.pm
index 4720606..2ea454b 100644
--- a/lib/IO/Socket/SSL.pm
+++ b/lib/IO/Socket/SSL.pm
@@ -326,7 +326,7 @@ sub configure_SSL {
"*******************************************************************\n".
" Using the default of SSL_verify_mode of SSL_VERIFY_NONE for client\n".
" is deprecated! Please set SSL_verify_mode to SSL_VERIFY_PEER\n".
- " together with SSL_ca_file|SSL_ca_path for verification.\n".
+ " possibly with SSL_ca_file|SSL_ca_path for verification.\n".
" If you really don't want to verify the certificate and keep the\n".
" connection open to Man-In-The-Middle attacks please set\n".
" SSL_verify_mode explicitly to SSL_VERIFY_NONE in your application.\n".
@@ -339,24 +339,54 @@ sub configure_SSL {
%$arg_hash = ( %default_args, %$arg_hash );
# use default path to certs and ca unless another one was given
- # don't mix default path with user specified path, either we use all
- # or no defaults
+ # don't mix default paths with user specified paths for CA or client
+ # certificates, either we use all from the grup or no defaults
{
- my $use_default = 1;
- for (qw( SSL_cert SSL_cert_file SSL_key SSL_key_file SSL_ca_file SSL_ca_path )) {
+ my $use_default_ca = 1;
+ my $dont_use_system_ca_file = (exists $arg_hash->{SSL_ca_file} and
+ not defined($arg_hash->{SSL_ca_file}));
+ for (qw( SSL_ca_file SSL_ca_path )) {
next if ! defined $arg_hash->{$_};
# some apps set keys '' to signal that it is not set, replace with undef
if ( $arg_hash->{$_} eq '' ) {
$arg_hash->{$_} = undef;
next;
}
- $use_default = 0;
+ $use_default_ca = 0;
}
- if ( $use_default ) {
+ my $use_default_client = 1;
+ for (qw( SSL_cert SSL_cert_file SSL_key SSL_key_file )) {
+ next if ! defined $arg_hash->{$_};
+ # some apps set keys '' to signal that it is not set, replace with undef
+ if ( $arg_hash->{$_} eq '' ) {
+ $arg_hash->{$_} = undef;
+ next;
+ }
+ $use_default_client = 0;
+ }
+ if ( $use_default_ca ) {
my %ca =
-f 'certs/my-ca.pem' ? ( SSL_ca_file => 'certs/my-ca.pem' ) :
-d 'ca/' ? ( SSL_ca_path => 'ca/' ) :
();
+ if (! %ca and !$dont_use_system_ca_file) {
+ require Mozilla::CA;
+ %ca = ( SSL_ca_file => Mozilla::CA::SSL_ca_file() );
+ }
+ %$arg_hash = ( %$arg_hash, %ca );
+ } else {
+ if ( defined( my $f = $arg_hash->{SSL_ca_file} )) {
+ die "SSL_ca_file $f does not exist" if ! -f $f;
+ die "SSL_ca_file $f is not accessable" if ! -r _;
+ }
+ if ( defined( my $d = $arg_hash->{SSL_ca_path} )) {
+ die "only SSL_ca_path or SSL_ca_file should be given"
+ if defined $arg_hash->{SSL_ca_file};
+ die "SSL_ca_path $d does not exist" if ! -d $d;
+ die "SSL_ca_path $d is not accessable" if ! -r _;
+ }
+ }
+ if ( $use_default_client ) {
my %certs = $is_server ? (
SSL_key_file => 'certs/server-key.pem',
SSL_cert_file => 'certs/server-cert.pem',
@@ -364,7 +394,7 @@ sub configure_SSL {
SSL_key_file => 'certs/client-key.pem',
SSL_cert_file => 'certs/client-cert.pem',
);
- %$arg_hash = ( %$arg_hash, %ca, %certs );
+ %$arg_hash = ( %$arg_hash, %certs );
} else {
for(qw(SSL_cert_file SSL_key_file)) {
defined( my $file = $arg_hash->{$_} ) or next;
@@ -373,16 +403,6 @@ sub configure_SSL {
die "$_ $f is not accessable" if ! -r _;
}
}
- if ( defined( my $f = $arg_hash->{SSL_ca_file} )) {
- die "SSL_ca_file $f does not exist" if ! -f $f;
- die "SSL_ca_file $f is not accessable" if ! -r _;
- }
- if ( defined( my $d = $arg_hash->{SSL_ca_path} )) {
- die "only SSL_ca_path or SSL_ca_file should be given"
- if defined $arg_hash->{SSL_ca_file};
- die "SSL_ca_path $d does not exist" if ! -d $d;
- die "SSL_ca_path $d is not accessable" if ! -r _;
- }
}
}
@@ -1937,8 +1957,11 @@ IO::Socket::SSL -- SSL sockets with IO::Socket interface
# certificate verification
SSL_verify_mode => SSL_VERIFY_PEER,
+
+ # location of CA store
+ # need only be given if default store should not be used
SSL_ca_path => '/etc/ssl/certs', # typical CA path on Linux
- # on OpenBSD instead: SSL_ca_file => '/etc/ssl/cert.pem'
+ SSL_ca_file => '/etc/ssl/cert.pem', # typical CA file on BSD
# easy hostname verification
SSL_verifycn_name => 'foo.bar', # defaults to PeerHost
@@ -2210,9 +2233,9 @@ password required to decrypt your private key.
=item SSL_ca_file
If you want to verify that the peer certificate has been signed by a reputable
-certificate authority, then you should use this option to locate the file
+certificate authority, then you can use this option to locate the file
containing the certificateZ<>(s) of the reputable certificate authorities if it is
-not already in the file F<certs/my-ca.pem>.
+not already in the file F<certs/my-ca.pem> or in a system-wide certificate authority certificates store.
If you definitely want no SSL_ca_file used you should set it to undef.
=item SSL_ca_path
--
2.7.4