diff --git a/clrtrust b/clrtrust index 1af319c..3e62e75 100755 --- a/clrtrust +++ b/clrtrust @@ -28,6 +28,17 @@ has_p11kit() { return 0 } +detect_c_rehash() { + if [ -z "$INTERNAL_C_REHASH" ] && command -v c_rehash >/dev/null 2>&1; then + # use c_rehash + C_REHASH_CMD=c_rehash + else + test -n "$VERBOSE" && echo "Using internal rehash" + C_REHASH_CMD=c_rehash_internal + fi + return 0 +} + # takes cert file as a single argument # returns 0 if root ca, 1 otherwise is_root_ca() { @@ -91,6 +102,31 @@ find_all_certs() { find_certs $CLR_LOCAL_TRUST_SRC/trusted } +# a c_rehash implementation for creating openssl-style CApath. this +# implementation is much simpler than openssl's one: it is designed to rehash a +# newly created store. it only takes directory to process as the argument and +# no options. it further assumes that it runs on a pristine directory where +# every file is a valid certificate, no duplicates (clrtrust ensures it prior to +# calling this function). also, it is called on a stage directory, unique to +# each clrtrust process, so no concurrent execution is assumed. +c_rehash_internal() { + local dir=$1 + if [ -z "$dir" ] || [ ! -d "$dir" ] || [ ! -w "$dir" ]; then + return 1 + fi + ( + cd "$dir" + find . -maxdepth 1 -type f | while read f; do + name=$(openssl x509 -in "$f" -noout -subject_hash 2>/dev/null) + lnno=0 + while ! ln -s "$f" "${name}.${lnno}" && ((lnno++ < 100)); do + : + done 2>/dev/null + done + ) + return 0 +} + print_verbose_error() { test -n "$VERBOSE" && 1>&2 printf "%s" "$@" && 1>&2 echo } @@ -314,7 +350,7 @@ $tmp" echo "${ca_certs}" | cut -f 1 | xargs -d '\n' cp -t $CLR_STORE_STAGE/anchors fi - if ! (cd $CLR_STORE_STAGE/anchors && c_rehash . >/dev/null 2>&1); then + if ! (cd "$CLR_STORE_STAGE/anchors" && $C_REHASH_CMD . >/dev/null 2>&1); then 1>&2 echo "Error rehashing the anchors." rm -r $CLR_STORE_STAGE return $EERR @@ -354,6 +390,7 @@ print_add_help() { Usage: ${BASENAME} add [-h|--help] ... -h | --help Prints this help message and exits + -f | --force Force addition of the certificate if possible ... List of files containing a PEM-encoded Root CA certificate(s) EOF @@ -661,7 +698,11 @@ Trust store has not been modified." print_help() { cat < [options] +Usage: ${BASENAME} [-v|--verbose] [-h|--help] [-c|--internal-rehash] [options] + + -v | --verbose Shows more details about execution + -c | --internal-rehash Forces use of internal implementation of c_rehash + -h | --help Prints this message Commands generate generates the trust store @@ -699,6 +740,11 @@ while [ $# -gt 0 ]; do print_help exit 0 ;; + ("-c"|"--internal-rehash") + INTERNAL_C_REHASH=1 + shift + continue + ;; ("generate"|"list"|"add"|"remove"|"restore"|"check") COMMAND=$1 shift @@ -709,6 +755,8 @@ while [ $# -gt 0 ]; do fi done +detect_c_rehash + case $COMMAND in ("generate"|"add"|"remove"|"restore") # must be root if writing to the default location diff --git a/test/generate-internal-rehash.bats b/test/generate-internal-rehash.bats new file mode 100755 index 0000000..35c89ad --- /dev/null +++ b/test/generate-internal-rehash.bats @@ -0,0 +1,29 @@ +#!/usr/bin/env bats +# Copyright 2017 Intel Corporation + +load test_lib + +setup() { + find_clrtrust + setup_fs + cp $CERTS/c[1-2].pem $CLR_CLEAR_TRUST_SRC/trusted + cp $CERTS/c[3-4].pem $CLR_LOCAL_TRUST_SRC/trusted +} + +@test "generate store, using internal rehash" { + $CLRTRUST -c generate + cnt=$(ls $STORE/anchors | wc -l) + [ $cnt -eq 8 ] + cnt=$(find $STORE/anchors -type l | wc -l) + [ $cnt -eq 4 ] + cnt=$($CLRTRUST list | grep ^id | wc -l) + [ $cnt -eq 4 ] + [ -f $STORE/compat/ca-roots.keystore ] + [ -f $STORE/compat/ca-roots.pem ] +} + +teardown() { + remove_fs +} + +# vim: ft=sh:sw=4:ts=4:et:tw=80:si:noai:nocin