aboutsummaryrefslogtreecommitdiffstats
path: root/main/openssl
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2013-12-31 13:43:38 +0200
committerTimo Teräs <timo.teras@iki.fi>2013-12-31 13:44:51 +0200
commit94998965c2563e48e8ce172ac6b3a3db819740f8 (patch)
treea2af073e06cf5a601c6f36c055503e528cd97e77 /main/openssl
parentf9b9fff33279f090d6d32345a12f28562db3f137 (diff)
downloadaports-94998965c2563e48e8ce172ac6b3a3db819740f8.tar.bz2
aports-94998965c2563e48e8ce172ac6b3a3db819740f8.tar.xz
main/openssl: rewrite c_rehash in C for speed
fixes #2533
Diffstat (limited to 'main/openssl')
-rw-r--r--main/openssl/APKBUILD16
-rw-r--r--main/openssl/c_rehash.c235
-rw-r--r--main/openssl/c_rehash.sh157
3 files changed, 243 insertions, 165 deletions
diff --git a/main/openssl/APKBUILD b/main/openssl/APKBUILD
index ca5e5fe649..dcdb703e4b 100644
--- a/main/openssl/APKBUILD
+++ b/main/openssl/APKBUILD
@@ -1,7 +1,7 @@
# Maintainer: Timo Teras <timo.teras@iki.fi>
pkgname=openssl
pkgver=1.0.1e
-pkgrel=6
+pkgrel=7
pkgdesc="Toolkit for SSL v2/v3 and TLS v1"
url="http://openssl.org"
depends=
@@ -26,7 +26,7 @@ source="http://www.openssl.org/source/${pkgname}-${pkgver}.tar.gz
openssl-use-termios.patch
openssl-disable-rdrand-default.patch
fix-default-apps-capath.patch
- c_rehash.sh
+ c_rehash.c
"
_builddir="$srcdir"/$pkgname-$pkgver
@@ -87,14 +87,14 @@ build() {
|| return 1
make -j1 || return 1
+
+ # replace the c_rehash perl script with our C-version
+ $CC $CFLAGS -I include -L . "$srcdir"/c_rehash.c -o tools/c_rehash -lcrypto || return 1
}
package() {
cd "$_builddir"
make -j1 INSTALL_PREFIX="$pkgdir" MANDIR=/usr/share/man install
- # replace the perl script with a shell script
- rm -f "$pkgdir"/usr/bin/c_rehash
- install -m 755 "$srcdir"/c_rehash.sh "$pkgdir"/usr/bin/c_rehash || return 1
}
libcrypto() {
@@ -130,7 +130,7 @@ d1f3aaad7c36590f21355682983cd14e openssl-1.0.1-version-eglibc.patch
2681796363085d01db8a81c249cd2d7b openssl-use-termios.patch
8a251d30c977ffe8bfbf9d9b7eae1a8e openssl-disable-rdrand-default.patch
efec1bce615256961b1756e575ee1d0a fix-default-apps-capath.patch
-d0b39772b0d8bcde609b57dcf4433be8 c_rehash.sh"
+f1334f9761e14ccc71931654320653be c_rehash.c"
sha256sums="f74f15e8c8ff11aa3d5bb5f276d202ec18d7246e95f961db76054199c69c1ae3 openssl-1.0.1e.tar.gz
fe844e21b2c42da2d8e9c89350211d70c0829f45532b89b7e492bfde589ee7ed fix-manpages.patch
82863c2fed659a7186c7f3905a1853b8bd8060350ad101ce159fa7e7d2ba27e8 openssl-bb-basename.patch
@@ -143,7 +143,7 @@ cbb2493ec9157e78035e9cc02be17655996ee9cd0a71b79507fc19f3862f452b 0003-engines-e
05266a671143cf17367dee8d409ad6d0857201392c99731d7ebb8f8cdcdc32f7 openssl-use-termios.patch
c215b03f9328b8dfb81e3fa90bdf0332d6b649688944ff79fe60be62131ccb60 openssl-disable-rdrand-default.patch
1e11d6b8cdcdd6957c69d33ab670c5918fc96c12fdb9b76b4287cb8f69c3545d fix-default-apps-capath.patch
-c99cf6efd66c7515a2a627b4bcf9b08f237401a5e514f12ed300b33c466450ff c_rehash.sh"
+1e8a060228221b4746822caf6139261fc1fbf0c9939f1181a9a7bec7ee855490 c_rehash.c"
sha512sums="c76857e439431b2ef6f2aa123997e53f82b9c3c964d4d765d7cc6c0c20b37a21adf578f9b759b2b65ae3925454c432a01b7de0cd320ece7181dc292e00d3244e openssl-1.0.1e.tar.gz
880411d56da49946d24328445728367e0bf13b0fd47954971514bee8cd5613a038ad8aeaf68da2c92f4634deb022febd7b3e37f9bbfc5d2c9c8b3b5ffd971407 fix-manpages.patch
6c4f4b0c1b606b3e5a8175618c4398923392f9c25ad8d3f5b65b0424fe51e104c4f456d2da590d9f572382225ab320278e88db1585790092450cad60a02819a5 openssl-bb-basename.patch
@@ -156,4 +156,4 @@ b019320869d215014ad46e0b29aa239e31243571c4d45256b3ce6449a67fdc106a381c1cf3abd55d
22261ad902ad4826db889fa0e6196b57d6cb389c1707f5827ba48a4630097e590979257f16f4a36fe611199fa33ba32d5f412c8b93beb84001865c2501b288da openssl-use-termios.patch
2af7a40d023e4a09c14712661056a45c572416d5bbee8d90caf5d9d44854ffa86b1d3a0bebf78156ec5da2e71ae91724c007c3d0a8de5f025b3947fd0add287d openssl-disable-rdrand-default.patch
f2e737146a473d55b99f27457718ca299a02a0c74009026a30c3d1347c575bc264962b5708995e02ef7d68521b8366ccea7320523efb87b1ab2632d73fec5658 fix-default-apps-capath.patch
-ad4dde3ad0abee7645b1ab3111242f045cc381e4381a19dd0c624059697cb0f6486f8463da6dfb22f11d9b2882a1872fef8a1fd1709b0981847d0a6d2c8741a3 c_rehash.sh"
+cb2a1240d8d615ea20f0aeb00149f422d934edd0d4a149badf2b8f11ab375cd208a34430f7616971785560d81659ebf81cc7ffe1cdb2ac43650c0005ecbc6aa0 c_rehash.c"
diff --git a/main/openssl/c_rehash.c b/main/openssl/c_rehash.c
new file mode 100644
index 0000000000..a46ec4533c
--- /dev/null
+++ b/main/openssl/c_rehash.c
@@ -0,0 +1,235 @@
+/* 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 <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;
+}
diff --git a/main/openssl/c_rehash.sh b/main/openssl/c_rehash.sh
deleted file mode 100644
index 9840132d22..0000000000
--- a/main/openssl/c_rehash.sh
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/bin/sh
-#
-# Ben Secrest <blsecres@gmail.com>
-#
-# sh c_rehash script, scan all files in a directory
-# and add symbolic links to their hash values.
-#
-# based on the c_rehash perl script distributed with openssl
-#
-# LICENSE: See OpenSSL license
-# ^^acceptable?^^
-#
-
-# default certificate location
-DIR=/etc/openssl
-
-#
-# use openssl to fingerprint a file
-# arguments:
-# 1. the filename to fingerprint
-# 2. the method to use (x509, crl)
-# returns:
-# none
-# assumptions:
-# user will capture output from last stage of pipeline
-#
-fingerprint()
-{
- ${SSL_CMD} ${2} -fingerprint -noout -in ${1} | sed -e 's/^.*=//' -e 's/://g'
-}
-
-
-#
-# link_hash - create links to certificate files
-# arguments:
-# 1. the filename to create a link for
-# 2. the type of certificate being linked (x509, crl)
-# returns:
-# 0 on success, 1 otherwise
-#
-link_hash()
-{
- local HASH=$( ${SSL_CMD} ${2} -hash -noout -in ${1} )
- local SUFFIX=0
- local LINKFILE=''
- local TAG=''
-
- if [ ${2} = "crl" ]
- then
- TAG='r'
- fi
-
- LINKFILE=${HASH}.${TAG}${SUFFIX}
-
- if [ -f ${LINKFILE} ]
- then
- local FINGERPRINT=$( fingerprint ${1} ${2} )
-
- while [ -f ${LINKFILE} ]
- do
- if [ ${FINGERPRINT} = $( fingerprint ${LINKFILE} ${2} ) ]
- then
- echo "WARNING: Skipping duplicate file ${1}" >&2
- return 1
- fi
-
- SUFFIX=$(( ${SUFFIX} + 1 ))
- LINKFILE=${HASH}.${TAG}${SUFFIX}
- done
- fi
-
- echo "${1} => ${LINKFILE}"
-
- # assume any system with a POSIX shell will either support symlinks or
- # do something to handle this gracefully
- ln -s ${1} ${LINKFILE}
-
- return 0
-}
-
-
-# hash_dir create hash links in a given directory
-hash_dir()
-{
- echo "Doing ${1}"
-
- cd ${1}
-
- ls -1 * 2>/dev/null | grep -E '^[[:xdigit:]]{8}\.r?[[:digit:]]+$' | while read FILE
- do
- [ -h "${FILE}" ] && rm "${FILE}"
- done
-
- ls -1 *.pem 2>/dev/null | while read FILE
- do
- local TYPE_STR=
-
- if grep -q '^-----BEGIN X509 CRL-----' ${FILE}; then
- TYPE_STR="crl"
- elif grep -q -E '^-----BEGIN (X509 |TRUSTED )?CERTIFICATE-----' ${FILE}; then
- TYPE_STR="x509"
- else
- echo "WARNING: ${FILE} does not contain a certificate or CRL: skipping" >&2
- continue
- fi
-
- link_hash ${FILE} ${TYPE_STR}
- done
-}
-
-
-# choose the name of an ssl application
-if [ -n "${OPENSSL}" ]
-then
- SSL_CMD=$(which ${OPENSSL} 2>/dev/null)
-else
- SSL_CMD=/usr/bin/openssl
- OPENSSL=${SSL_CMD}
- export OPENSSL
-fi
-
-# fix paths
-PATH=${PATH}:${DIR}/bin
-export PATH
-
-# confirm existance/executability of ssl command
-if ! [ -x ${SSL_CMD} ]
-then
- echo "${0}: rehashing skipped ('openssl' program not available)" >&2
- exit 0
-fi
-
-# determine which directories to process
-old_IFS=$IFS
-if [ ${#} -gt 0 ]
-then
- IFS=':'
- DIRLIST=${*}
-elif [ -n "${SSL_CERT_DIR}" ]
-then
- DIRLIST=$SSL_CERT_DIR
-else
- DIRLIST=${DIR}/certs
-fi
-
-IFS=':'
-
-# process directories
-for CERT_DIR in ${DIRLIST}
-do
- if [ -d ${CERT_DIR} -a -w ${CERT_DIR} ]
- then
- IFS=$old_IFS
- hash_dir ${CERT_DIR}
- IFS=':'
- fi
-done