diff --git a/srcpkgs/libressl/files/c_rehash b/srcpkgs/libressl/files/c_rehash deleted file mode 100755 index d77b0eb15b6..00000000000 --- a/srcpkgs/libressl/files/c_rehash +++ /dev/null @@ -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() { - 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 . 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 ; # 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 .r - -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; -} - diff --git a/srcpkgs/libressl/files/c_rehash.c b/srcpkgs/libressl/files/c_rehash.c new file mode 100644 index 00000000000..a669529d295 --- /dev/null +++ b/srcpkgs/libressl/files/c_rehash.c @@ -0,0 +1,236 @@ +/* c_rehash.c - C implementation based on the Perl and shell versions + * + * Copyright (c) 2013 Timo Teräs + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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; +} diff --git a/srcpkgs/libressl/template b/srcpkgs/libressl/template index 67c3f4ba8ae..ab6ead69a7f 100644 --- a/srcpkgs/libressl/template +++ b/srcpkgs/libressl/template @@ -11,6 +11,9 @@ homepage="http://www.libressl.org/" distfiles="http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${pkgname}-${version}.tar.gz" checksum=fb5ada41a75b31c8dd9ff013daca57b253047ad14e43f65d8b41879b7b8e3c17 +post_build() { + $CC -Wall $CFLAGS -Iinclude -Lcrypto/.libs $LDFLAGS ${FILESDIR}/c_rehash.c -o ${wrksrc}/c_rehash -lcrypto +} post_install() { vlicense COPYING mv ${DESTDIR}/usr/share/man/man1/{passwd.1,libressl-passwd.1} @@ -30,15 +33,13 @@ libressl-devel_package() { } libressl-openssl_package() { short_desc+=" - utilities" - # required by c_rehash - depends="perl" - provides="openssl-${version}_${revision} openssl-crehash-${version}_${revision}" - replaces="libressl<2.0.1_2 openssl>=0 openssl-crehash>=0" + provides="openssl-${version}_${revision}" + replaces="libressl<2.0.1_2 openssl>=0" conf_files="/etc/ssl/openssl.cnf" pkg_install() { vinstall ${FILESDIR}/openssl.cnf 644 etc/ssl vmove usr/bin vmove usr/share/man/man1 - vbin ${FILESDIR}/c_rehash + vbin ${wrksrc}/c_rehash } }