libressl: use the C c_rehash tool written by Timo Teras via Alpine.
Thanks to Timo Teras for doing the hard work!
This commit is contained in:
parent
14eac4987a
commit
04251ee7fe
|
@ -1,180 +0,0 @@
|
||||||
#!/usr/bin/perl
|
|
||||||
|
|
||||||
|
|
||||||
# Perl c_rehash script, scan all files in a directory
|
|
||||||
# and add symbolic links to their hash values.
|
|
||||||
|
|
||||||
my $openssl;
|
|
||||||
|
|
||||||
my $dir = "/etc/ssl";
|
|
||||||
my $prefix = "/usr";
|
|
||||||
|
|
||||||
if(defined $ENV{OPENSSL}) {
|
|
||||||
$openssl = $ENV{OPENSSL};
|
|
||||||
} else {
|
|
||||||
$openssl = "openssl";
|
|
||||||
$ENV{OPENSSL} = $openssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $pwd;
|
|
||||||
eval "require Cwd";
|
|
||||||
if (defined(&Cwd::getcwd)) {
|
|
||||||
$pwd=Cwd::getcwd();
|
|
||||||
} else {
|
|
||||||
$pwd=`pwd`; chomp($pwd);
|
|
||||||
}
|
|
||||||
my $path_delim = ($pwd =~ /^[a-z]\:/i) ? ';' : ':'; # DOS/Win32 or Unix delimiter?
|
|
||||||
|
|
||||||
$ENV{PATH} = "$prefix/bin" . ($ENV{PATH} ? $path_delim . $ENV{PATH} : ""); # prefix our path
|
|
||||||
|
|
||||||
if(! -x $openssl) {
|
|
||||||
my $found = 0;
|
|
||||||
foreach (split /$path_delim/, $ENV{PATH}) {
|
|
||||||
if(-x "$_/$openssl") {
|
|
||||||
$found = 1;
|
|
||||||
$openssl = "$_/$openssl";
|
|
||||||
last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if($found == 0) {
|
|
||||||
print STDERR "c_rehash: rehashing skipped ('openssl' program not available)\n";
|
|
||||||
exit 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(@ARGV) {
|
|
||||||
@dirlist = @ARGV;
|
|
||||||
} elsif($ENV{SSL_CERT_DIR}) {
|
|
||||||
@dirlist = split /$path_delim/, $ENV{SSL_CERT_DIR};
|
|
||||||
} else {
|
|
||||||
$dirlist[0] = "$dir/certs";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-d $dirlist[0]) {
|
|
||||||
chdir $dirlist[0];
|
|
||||||
$openssl="$pwd/$openssl" if (!-x $openssl);
|
|
||||||
chdir $pwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (@dirlist) {
|
|
||||||
if(-d $_ and -w $_) {
|
|
||||||
hash_dir($_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub hash_dir {
|
|
||||||
my %hashlist;
|
|
||||||
print "Doing $_[0]\n";
|
|
||||||
chdir $_[0];
|
|
||||||
opendir(DIR, ".");
|
|
||||||
my @flist = readdir(DIR);
|
|
||||||
# Delete any existing symbolic links
|
|
||||||
foreach (grep {/^[\da-f]+\.r{0,1}\d+$/} @flist) {
|
|
||||||
if(-l $_) {
|
|
||||||
unlink $_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir DIR;
|
|
||||||
FILE: foreach $fname (grep {/\.pem$/} @flist) {
|
|
||||||
# Check to see if certificates and/or CRLs present.
|
|
||||||
my ($cert, $crl) = check_file($fname);
|
|
||||||
if(!$cert && !$crl) {
|
|
||||||
print STDERR "WARNING: $fname does not contain a certificate or CRL: skipping\n";
|
|
||||||
next;
|
|
||||||
}
|
|
||||||
link_hash_cert($fname) if($cert);
|
|
||||||
link_hash_crl($fname) if($crl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub check_file {
|
|
||||||
my ($is_cert, $is_crl) = (0,0);
|
|
||||||
my $fname = $_[0];
|
|
||||||
open IN, $fname;
|
|
||||||
while(<IN>) {
|
|
||||||
if(/^-----BEGIN (.*)-----/) {
|
|
||||||
my $hdr = $1;
|
|
||||||
if($hdr =~ /^(X509 |TRUSTED |)CERTIFICATE$/) {
|
|
||||||
$is_cert = 1;
|
|
||||||
last if($is_crl);
|
|
||||||
} elsif($hdr eq "X509 CRL") {
|
|
||||||
$is_crl = 1;
|
|
||||||
last if($is_cert);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close IN;
|
|
||||||
return ($is_cert, $is_crl);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Link a certificate to its subject name hash value, each hash is of
|
|
||||||
# the form <hash>.<n> where n is an integer. If the hash value already exists
|
|
||||||
# then we need to up the value of n, unless its a duplicate in which
|
|
||||||
# case we skip the link. We check for duplicates by comparing the
|
|
||||||
# certificate fingerprints
|
|
||||||
|
|
||||||
sub link_hash_cert {
|
|
||||||
my $fname = $_[0];
|
|
||||||
$fname =~ s/'/'\\''/g;
|
|
||||||
my ($hash, $fprint) = `"$openssl" x509 -hash -fingerprint -noout -in "$fname"`;
|
|
||||||
chomp $hash;
|
|
||||||
chomp $fprint;
|
|
||||||
$fprint =~ s/^.*=//;
|
|
||||||
$fprint =~ tr/://d;
|
|
||||||
my $suffix = 0;
|
|
||||||
# Search for an unused hash filename
|
|
||||||
while(exists $hashlist{"$hash.$suffix"}) {
|
|
||||||
# Hash matches: if fingerprint matches its a duplicate cert
|
|
||||||
if($hashlist{"$hash.$suffix"} eq $fprint) {
|
|
||||||
print STDERR "WARNING: Skipping duplicate certificate $fname\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$suffix++;
|
|
||||||
}
|
|
||||||
$hash .= ".$suffix";
|
|
||||||
print "$fname => $hash\n";
|
|
||||||
$symlink_exists=eval {symlink("",""); 1};
|
|
||||||
if ($symlink_exists) {
|
|
||||||
symlink $fname, $hash;
|
|
||||||
} else {
|
|
||||||
open IN,"<$fname" or die "can't open $fname for read";
|
|
||||||
open OUT,">$hash" or die "can't open $hash for write";
|
|
||||||
print OUT <IN>; # does the job for small text files
|
|
||||||
close OUT;
|
|
||||||
close IN;
|
|
||||||
}
|
|
||||||
$hashlist{$hash} = $fprint;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Same as above except for a CRL. CRL links are of the form <hash>.r<n>
|
|
||||||
|
|
||||||
sub link_hash_crl {
|
|
||||||
my $fname = $_[0];
|
|
||||||
$fname =~ s/'/'\\''/g;
|
|
||||||
my ($hash, $fprint) = `"$openssl" crl -hash -fingerprint -noout -in '$fname'`;
|
|
||||||
chomp $hash;
|
|
||||||
chomp $fprint;
|
|
||||||
$fprint =~ s/^.*=//;
|
|
||||||
$fprint =~ tr/://d;
|
|
||||||
my $suffix = 0;
|
|
||||||
# Search for an unused hash filename
|
|
||||||
while(exists $hashlist{"$hash.r$suffix"}) {
|
|
||||||
# Hash matches: if fingerprint matches its a duplicate cert
|
|
||||||
if($hashlist{"$hash.r$suffix"} eq $fprint) {
|
|
||||||
print STDERR "WARNING: Skipping duplicate CRL $fname\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$suffix++;
|
|
||||||
}
|
|
||||||
$hash .= ".r$suffix";
|
|
||||||
print "$fname => $hash\n";
|
|
||||||
$symlink_exists=eval {symlink("",""); 1};
|
|
||||||
if ($symlink_exists) {
|
|
||||||
symlink $fname, $hash;
|
|
||||||
} else {
|
|
||||||
system ("cp", $fname, $hash);
|
|
||||||
}
|
|
||||||
$hashlist{$hash} = $fprint;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,236 @@
|
||||||
|
/* c_rehash.c - C implementation based on the Perl and shell versions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Timo Teräs <timo.teras@iki.fi>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is licensed under the MIT License.
|
||||||
|
* Full license available at: http://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _POSIX_C_SOURCE 200809L
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
|
||||||
|
#define countof(x) (sizeof(x) / sizeof(x[0]))
|
||||||
|
|
||||||
|
struct hash_info {
|
||||||
|
struct hash_info *next;
|
||||||
|
int type;
|
||||||
|
unsigned long hash;
|
||||||
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Type {
|
||||||
|
TYPE_CERT = 0,
|
||||||
|
TYPE_CRL,
|
||||||
|
MAX_TYPES,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EVP_MD *evpmd;
|
||||||
|
static int evpmdsize;
|
||||||
|
static const char *prefixes[MAX_TYPES] = { "", "r" };
|
||||||
|
static struct hash_info *hash_table[257];
|
||||||
|
|
||||||
|
static int get_link_id(int type, unsigned long hash, unsigned char *digest)
|
||||||
|
{
|
||||||
|
unsigned int bucket = hash % countof(hash_table);
|
||||||
|
struct hash_info *hi;
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (hi = hash_table[bucket]; hi; hi = hi->next) {
|
||||||
|
if (hi->type != type || hi->hash != hash)
|
||||||
|
continue;
|
||||||
|
if (memcmp(digest, hi->digest, evpmdsize) == 0)
|
||||||
|
return -1;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
hi = malloc(sizeof(*hi));
|
||||||
|
hi->next = hash_table[bucket];
|
||||||
|
hi->type = type;
|
||||||
|
hi->hash = hash;
|
||||||
|
memcpy(hi->digest, digest, evpmdsize);
|
||||||
|
hash_table[bucket] = hi;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int link_file(int dirfd, const char *filename, int type, unsigned long hash, unsigned char *digest)
|
||||||
|
{
|
||||||
|
char linkfn[32];
|
||||||
|
int id;
|
||||||
|
|
||||||
|
id = get_link_id(type, hash, digest);
|
||||||
|
if (id < 0) {
|
||||||
|
fprintf(stderr, "WARNING: Skipping duplicate certificate in file %s\n",
|
||||||
|
filename);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(linkfn, sizeof(linkfn),
|
||||||
|
"%08lx.%s%d", hash, prefixes[type], id);
|
||||||
|
fprintf(stdout, "%s => %s\n", linkfn, filename);
|
||||||
|
if (symlinkat(filename, dirfd, linkfn) < 0)
|
||||||
|
perror(linkfn);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BIO *BIO_openat(int dirfd, const char *filename)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
BIO *bio;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
fd = openat(dirfd, filename, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror(filename);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fp = fdopen(fd, "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
bio = BIO_new_fp(fp, BIO_CLOSE);
|
||||||
|
if (!bio) {
|
||||||
|
fclose(fp);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return bio;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hash_file(int dirfd, const char *filename)
|
||||||
|
{
|
||||||
|
STACK_OF(X509_INFO) *inf;
|
||||||
|
X509_INFO *x;
|
||||||
|
BIO *b;
|
||||||
|
int i, count = 0;
|
||||||
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||||
|
|
||||||
|
b = BIO_openat(dirfd, filename);
|
||||||
|
if (!b)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
inf = PEM_X509_INFO_read_bio(b, NULL, NULL, NULL);
|
||||||
|
BIO_free(b);
|
||||||
|
if (!inf)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for(i = 0; i < sk_X509_INFO_num(inf); i++) {
|
||||||
|
x = sk_X509_INFO_value(inf, i);
|
||||||
|
if (x->x509) {
|
||||||
|
X509_digest(x->x509, evpmd, digest, NULL);
|
||||||
|
link_file(dirfd, filename, TYPE_CERT,
|
||||||
|
X509_subject_name_hash(x->x509), digest);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
if (x->crl) {
|
||||||
|
X509_CRL_digest(x->crl, evpmd, digest, NULL);
|
||||||
|
link_file(dirfd, filename, TYPE_CRL,
|
||||||
|
X509_NAME_hash(X509_CRL_get_issuer(x->crl)),
|
||||||
|
digest);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sk_X509_INFO_pop_free(inf, X509_INFO_free);
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"WARNING: %s does not contain a certificate or CRL: skipping\n",
|
||||||
|
filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_hash_filename(const char *fn)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
if (!isxdigit(fn[i]))
|
||||||
|
return 0;
|
||||||
|
if (fn[i++] != '.')
|
||||||
|
return 0;
|
||||||
|
if (fn[i] == 'r') i++;
|
||||||
|
for (; fn[i] != 0; i++)
|
||||||
|
if (!isdigit(fn[i]))
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hash_dir(const char *dirname)
|
||||||
|
{
|
||||||
|
struct dirent *de;
|
||||||
|
struct stat st;
|
||||||
|
int dirfd;
|
||||||
|
DIR *d;
|
||||||
|
|
||||||
|
fprintf(stdout, "Doing %s\n", dirname);
|
||||||
|
dirfd = open(dirname, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (dirfd < 0) {
|
||||||
|
perror(dirname);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
d = opendir(dirname);
|
||||||
|
if (!d) {
|
||||||
|
close(dirfd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
while ((de = readdir(d)) != NULL) {
|
||||||
|
if (fstatat(dirfd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0)
|
||||||
|
continue;
|
||||||
|
if (!S_ISLNK(st.st_mode))
|
||||||
|
continue;
|
||||||
|
if (!is_hash_filename(de->d_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (unlinkat(dirfd, de->d_name, 0) < 0)
|
||||||
|
perror(de->d_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
rewinddir(d);
|
||||||
|
while ((de = readdir(d)) != NULL) {
|
||||||
|
if (fnmatch("*.pem", de->d_name, FNM_NOESCAPE) == 0)
|
||||||
|
hash_file(dirfd, de->d_name);
|
||||||
|
}
|
||||||
|
closedir(d);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
const char *env;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
evpmd = EVP_sha1();
|
||||||
|
evpmdsize = EVP_MD_size(evpmd);
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
for (i = 1; i < argc; i++)
|
||||||
|
hash_dir(argv[i]);
|
||||||
|
} else if ((env = getenv("SSL_CERT_DIR")) != NULL) {
|
||||||
|
char *e, *m;
|
||||||
|
m = strdup(env);
|
||||||
|
for (e = strtok(m, ":"); e != NULL; e = strtok(NULL, ":"))
|
||||||
|
hash_dir(e);
|
||||||
|
free(m);
|
||||||
|
} else {
|
||||||
|
hash_dir("/etc/ssl/certs");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -11,6 +11,9 @@ homepage="http://www.libressl.org/"
|
||||||
distfiles="http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${pkgname}-${version}.tar.gz"
|
distfiles="http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${pkgname}-${version}.tar.gz"
|
||||||
checksum=fb5ada41a75b31c8dd9ff013daca57b253047ad14e43f65d8b41879b7b8e3c17
|
checksum=fb5ada41a75b31c8dd9ff013daca57b253047ad14e43f65d8b41879b7b8e3c17
|
||||||
|
|
||||||
|
post_build() {
|
||||||
|
$CC -Wall $CFLAGS -Iinclude -Lcrypto/.libs $LDFLAGS ${FILESDIR}/c_rehash.c -o ${wrksrc}/c_rehash -lcrypto
|
||||||
|
}
|
||||||
post_install() {
|
post_install() {
|
||||||
vlicense COPYING
|
vlicense COPYING
|
||||||
mv ${DESTDIR}/usr/share/man/man1/{passwd.1,libressl-passwd.1}
|
mv ${DESTDIR}/usr/share/man/man1/{passwd.1,libressl-passwd.1}
|
||||||
|
@ -30,15 +33,13 @@ libressl-devel_package() {
|
||||||
}
|
}
|
||||||
libressl-openssl_package() {
|
libressl-openssl_package() {
|
||||||
short_desc+=" - utilities"
|
short_desc+=" - utilities"
|
||||||
# required by c_rehash
|
provides="openssl-${version}_${revision}"
|
||||||
depends="perl"
|
replaces="libressl<2.0.1_2 openssl>=0"
|
||||||
provides="openssl-${version}_${revision} openssl-crehash-${version}_${revision}"
|
|
||||||
replaces="libressl<2.0.1_2 openssl>=0 openssl-crehash>=0"
|
|
||||||
conf_files="/etc/ssl/openssl.cnf"
|
conf_files="/etc/ssl/openssl.cnf"
|
||||||
pkg_install() {
|
pkg_install() {
|
||||||
vinstall ${FILESDIR}/openssl.cnf 644 etc/ssl
|
vinstall ${FILESDIR}/openssl.cnf 644 etc/ssl
|
||||||
vmove usr/bin
|
vmove usr/bin
|
||||||
vmove usr/share/man/man1
|
vmove usr/share/man/man1
|
||||||
vbin ${FILESDIR}/c_rehash
|
vbin ${wrksrc}/c_rehash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue