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