Skip to content

Commit 3c93d73

Browse files
committed
SSL certs location: bugfixes, check more places.
Issue #1 is a report from LEVAI Daniel that the recent certs-finding functionality is broken on OpenBSD, because of an assumption that if we can find OPENSSLDIR from openssl(1), then certs/ within that must be valid. Made a validity check for a given dir; not existing is silent, but existing and unusable triggers debug messages. It checks for being a dir and having filenames ending ".0" inside that directory. Bug-fixed stderr-handling around the search. If openssl doesn't give us a location, and none of the file candidates exist, then check a few locations for SSL_ca_path directory candidacy. Fixes #1
1 parent f82c82a commit 3c93d73

1 file changed

Lines changed: 72 additions & 9 deletions

File tree

sieve-connect.pre.pl

Lines changed: 72 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,11 @@
6262
# a server to connect to".
6363
my $DERIVE_SIEVE_SERVER = 1;
6464

65+
# Command used for generating local-side listings.
6566
my @cmd_localfs_ls = qw( ls -C );
6667

68+
# Unset this to disable probing for SSL certs and just use whatever is
69+
# set above in %ssl_options.
6770
my $SEARCH_FOR_CERTS_DIR_IF_NEEDED = 1;
6871

6972
# You can override this to a particular path; is only used to find default
@@ -1806,6 +1809,42 @@ sub tilde_expand
18061809
return ($more and wantarray) ? ($path, $tilded, $home) : $path;
18071810
}
18081811

1812+
# Given a directory, the fact of its existence doesn't mean it's usable for
1813+
# OpenSSL certs; it could have been created by an installer but never used. If
1814+
# it's usable, then there will be hash symlinks therein. Each is 8 hex chars,
1815+
# a dot and then a sequence number starting at 0, to handle hash collisions.
1816+
# So, if there are no (symlinks to) files matching *.0 then although the dir
1817+
# exists, it's unitialised cruft. If none of the symlinks are resolvable, it's
1818+
# also cruft.
1819+
#
1820+
# Theoretically, a system might try to make the dir unreadable-but-executable
1821+
# so that it becomes an oracle that can be asked if a given cert should be
1822+
# trusted. That approach of self-mistrust is not supported: if you have such a
1823+
# system, report it and we can add an option to disable the contents probe.
1824+
sub confirm_valid_sslcerts_dir
1825+
{
1826+
my $dir = shift;
1827+
die "internal error" unless defined $dir;
1828+
return 0 unless -e $dir;
1829+
unless (-d $dir) {
1830+
debug("setup: not a directory: $dir");
1831+
return 0;
1832+
}
1833+
unless (opendir(DIR, $dir)) {
1834+
debug("setup: unable to opendir($dir): $!");
1835+
return 0;
1836+
}
1837+
my @some_entries = grep /^[^.].+\.0\z/, readdir(DIR);
1838+
# while opendir failing is likely permissions, closedir
1839+
# failing is the system failing badly.
1840+
closedir(DIR) or die "closedir($dir) failed: $!\n";
1841+
foreach my $entry (@some_entries) {
1842+
return 1 if -f File::Spec->catfile($dir, $entry);
1843+
}
1844+
debug("setup: found no files named for cert-hashes, rejecting dir [$dir]");
1845+
return 0;
1846+
}
1847+
18091848
sub fixup_ssl_configuration
18101849
{
18111850
return unless $SEARCH_FOR_CERTS_DIR_IF_NEEDED;
@@ -1816,25 +1855,37 @@ sub fixup_ssl_configuration
18161855

18171856
if (defined $OPENSSL_COMMAND) {
18181857
debug "setup: Need to find SSL_ca_path, trying to ask openssl";
1819-
my $found = 0;
1858+
my $found = undef;
18201859
# protect against openssl command not existing
1821-
open (my $olderr, ">&STDERR");
1860+
open (my $olderr, ">&STDERR") or die "failed to dup(stderr): $!\n";
18221861
open(STDERR, File::Spec->devnull());
1862+
my $oops = 0;
18231863
if (open(VERSION, '-|', $OPENSSL_COMMAND, 'version', '-d')) {
1824-
open(STDERR, ">&", $olderr); close($olderr);
18251864
foreach (<VERSION>) {
18261865
next unless /^OPENSSLDIR: "(.+)"\s*$/;
1827-
$ssl_options{'SSL_ca_path'} = File::Spec->catdir($1, 'certs');
1828-
$found = 1;
1866+
$found = $1;
18291867
last;
18301868
}
18311869
close(VERSION);
1832-
debug("setup: " . ($found
1833-
? "Have set SSL_ca_path to $ssl_options{'SSL_ca_path'}"
1834-
: "Unable to get system SSL_ca_path"));
1835-
return;
1870+
} else {
1871+
$oops = 1;
18361872
}
18371873
open(STDERR, ">&", $olderr); close($olderr);
1874+
if ($oops) {
1875+
debug("setup: unable to run openssl");
1876+
} elsif (defined $found) {
1877+
my $attempt = File::Spec->catdir($found, 'certs');
1878+
if (confirm_valid_sslcerts_dir($attempt)) {
1879+
$ssl_options{'SSL_ca_path'} = $attempt;
1880+
debug("setup: Have set SSL_ca_path to $ssl_options{'SSL_ca_path'}");
1881+
} else {
1882+
debug("setup: found OPENSSLDIR but certs/ invalid");
1883+
$found = undef;
1884+
}
1885+
} else {
1886+
debug("setup: openssl did not tell us OPENSSLDIR");
1887+
}
1888+
return if defined $found;
18381889
}
18391890

18401891
debug "setup: No OpenSSL, check some common locations";
@@ -1852,6 +1903,18 @@ sub fixup_ssl_configuration
18521903
debug("setup: Have set SSL_ca_file to $ssl_options{'SSL_ca_file'}");
18531904
return;
18541905
}
1906+
my @alt_dir_locations = (
1907+
"/etc/ssl/certs", # widespread
1908+
"/etc/x509/certs",
1909+
"/system/etc/security/cacerts", # some Android
1910+
"/data/misc/keychain/cacerts-added", # some Android
1911+
);
1912+
foreach my $loc (@alt_dir_locations) {
1913+
confirm_valid_sslcerts_dir($loc) or next;
1914+
$ssl_options{'SSL_ca_path'} = $loc;
1915+
debug("setup: Have set SSL_ca_path to $ssl_options{'SSL_ca_path'}");
1916+
return;
1917+
}
18551918
}
18561919

18571920
# returns 1 "okay", 0 "definitely not available", undef "unknown"

0 commit comments

Comments
 (0)