Index: base/univention-ssl/debian/changelog =================================================================== --- base/univention-ssl/debian/changelog (Revision 72278) +++ base/univention-ssl/debian/changelog (Arbeitskopie) @@ -1,3 +1,10 @@ +univention-ssl (10.0.0-17ubuntu1) UNRELEASED; urgency=medium + + * Bug #41013: univention-certificate should offer a renew-option with + a transition period (-grace ) + + -- Julius Hinrichs Wed, 28 Sep 2016 16:02:00 +0200 + univention-ssl (10.0.0-17) unstable; urgency=low * Bug #41917: Fix dash local variable quoting Index: base/univention-ssl/debian/univention-ssl.cron.daily =================================================================== --- base/univention-ssl/debian/univention-ssl.cron.daily (Revision 72278) +++ base/univention-ssl/debian/univention-ssl.cron.daily (Arbeitskopie) @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Copyright 2004-2016 Univention GmbH # # http://www.univention.de/ @@ -28,6 +28,9 @@ PATH=/usr/sbin:/usr/bin:/sbin:/bin +. /usr/share/univention-ssl/make-certificates.sh +update_pending_certs + rv=0 tmp=$(mktemp) trap "rm -f '$tmp'" EXIT exec >"$tmp" 2>&1 @@ -44,7 +47,6 @@ interval=$(ucr get ssl/crl/interval) [ "${interval:-0}" -ge 1 ] || return 0 [ -f "$crl" ] && [ -n "$(find "$crl" -mtime "-$interval")" ] && return 0 - . /usr/share/univention-ssl/make-certificates.sh gencrl } check_gen_crl || rv=$? Index: base/univention-ssl/make-certificates.sh =================================================================== --- base/univention-ssl/make-certificates.sh (Revision 72278) +++ base/univention-ssl/make-certificates.sh (Arbeitskopie) @@ -43,6 +43,8 @@ : ${DEFAULT_CRL_DAYS:=10} DEFAULT_DAYS="$(/usr/sbin/univention-config-registry get ssl/default/days)" : ${DEFAULT_DAYS:=1825} +DEFAULT_GRACE="$(/usr/sbin/univention-config-registry get ssl/default/grace)" +: ${DEFAULT_GRACE:=0} DEFAULT_MD="$(/usr/sbin/univention-config-registry get ssl/default/hashfunction)" : ${DEFAULT_MD:=sha256} DEFAULT_BITS="$(/usr/sbin/univention-config-registry get ssl/default/bits)" @@ -133,6 +135,8 @@ policy = policy_match +unique_subject = no + [ policy_match ] countryName = match @@ -336,7 +340,9 @@ if ( X[i] ~ /^CN=/ ) { split ( X[i], Y, "=" ); if ( name == Y[2] ) { - seq = $4; + if ( $1 == "V" ) { + seq = seq$4" "; + } ret = ( $1 != "R" ) ? ( $1 == "V" && $2 >= now ? 0 : 3 ) : 2; } } @@ -348,8 +354,9 @@ renew_cert () { local fqdn="${1:?Missing argument: common name}" local days="${2:-$DEFAULT_DAYS}" + local grace="${3:-$DEFAULT_GRACE}" - revoke_cert "$fqdn" || [ $? -eq 2 ] || return $? + revoke_cert "$fqdn" "$grace" || [ $? -eq 2 ] || return $? ( cd "$SSLBASE" @@ -361,6 +368,7 @@ revoke_cert () { local fqdn="${1:?Missing argument: common name}" + local grace="${2:-$DEFAULT_GRACE}" local cn NUM [ ${#fqdn} -gt 64 ] && cn="${fqdn%%.*}" || cn="$fqdn" @@ -371,11 +379,65 @@ return 2 fi - openssl ca -config "${SSLBASE}/openssl.cnf" -revoke "${SSLBASE}/${CA}/certs/${NUM}.pem" -passin pass:"$PASSWD" + if [ "$grace" -eq 0 ]; then + # revoke all certificates of this fqdn + for num in "${NUM[@]}"; do + local num1=$(sed 's/\s.*$//' <<< "$num") + openssl ca -config "${SSLBASE}/openssl.cnf" -revoke "${SSLBASE}/${CA}/certs/${num1}.pem" -passin pass:"$PASSWD" + done + else + # remember all certificates of this fqdn for revocation after the grace period + pending_file="${SSLBASE}/pending.txt" + [ -f "$pending_file" ] || touch "$pending_file" + chmod 600 "$pending_file" + local pending_certs=$(cat "$pending_file") + local temp=$(mktemp) + + for num in "${NUM[@]}"; do + local num=$(sed 's/\s.*$//' <<< "$num") + local now=$(date +"%s") + local expire="$(($now + ($grace * 3600 * 24)))" + echo "$num:$expire" >>"$temp" + done + + for cert in "${pending_certs[@]}"; do + local num=$(sed 's/:.*//' <<< "$cert") + local expire=$(sed 's/.*://' <<< "$cert") + if [[ "$NUM" != *"$num"* ]]; then + echo "$num:$expire" >>"$temp" + fi + done + mv "$temp" "$pending_file" + chmod 600 "$pending_file" + fi + gencrl } +update_pending_certs () { + local pending_file="${SSLBASE}/pending.txt" + [ -f "$pending_file" ] || touch "$pending_file" + chmod 600 "$pending_file" + local pending_certs=$(cat "$pending_file") + local temp=$(mktemp) + for cert in "${pending_certs[@]}"; do + local num=$(sed 's/:.*//' <<< "$cert") + local expire=$(sed 's/.*://' <<< "$cert") + local now=$(date +"%s") + if [ "$now" -gt "$expire" ]; then + openssl ca -config "${SSLBASE}/openssl.cnf" -revoke "${SSLBASE}/${CA}/certs/${num}.pem" -passin pass:"$PASSWD" + else + echo "$num:$expire" >>"$temp" + fi + done + + mv "$temp" "$pending_file" + chmod 600 "$pending_file" + gencrl +} + + # Parameter 1: Name des Unterverzeichnisses, in dem das neue Zertifikat abgelegt werden soll # Parameter 2: Name des CN für den das Zertifikat ausgestellt wird. Index: base/univention-ssl/univention-certificate =================================================================== --- base/univention-ssl/univention-certificate (Revision 72278) +++ base/univention-ssl/univention-certificate (Arbeitskopie) @@ -50,6 +50,7 @@ echo "Options:" echo " -name " echo " -days " + echo " -grace (grace period, in days)" [ -n "$1" ] && exit 2 || exit 0 } @@ -75,6 +76,7 @@ command= name= days= +grace= while [ $# -ge 1 ] do case "$1" in @@ -86,6 +88,7 @@ dump) command="$1" ;; -name|--name) name="${2:?Missing argument to -name}" ; shift ;; -days|--days) days="${2:?Missing argument to -days}" ; shift ;; + -grace|--grace) grace="${2:?Missing argument to -grace}" ; shift ;; -h|--help|--usage|-\?) usage ;; -*) usage "Unknown option: '$1'" >&2 ;; *) usage "Unknown command: '$1'" >&2 ;; @@ -120,7 +123,7 @@ run_only master exclusive : ${days:?Missing argument -days} echo "Renew certificate: $name" - renew_cert "$name" "$days" + renew_cert "$name" "$days" "$grace" } check () { Index: test/ucs-test/tests/01_base/101_renew_certificate_with_grace_period =================================================================== --- test/ucs-test/tests/01_base/101_renew_certificate_with_grace_period (nicht existent) +++ test/ucs-test/tests/01_base/101_renew_certificate_with_grace_period (Arbeitskopie) @@ -0,0 +1,60 @@ +#!/usr/share/ucs-test/runner bash +## desc: Test if a certificate can be renewed with a grace period +## roles: [domaincontroller_master] +## exposure: dangerous +## bugs: [41013] + +. "$TESTLIBPATH/base.sh" || exit 137 +. "$TESTLIBPATH/random.sh" || exit 137 + +SSLBASE="${sslbase:-/etc/univention/ssl}" +pending_file="${SSLBASE}/pending.txt" + +test_days=1825 +test_grace=3 + +random=$(random_hostname) +test_cert_name="test_cert_$random" +while [ $(univention-certificate list | grep "$test_cert_name" | wc -l) -gt "0" ]; do + random=$(random_hostname) + test_cert_name="test_cert_$random" +done + +list0=$(univention-certificate list) +univention-certificate new -name "$test_cert_name" >/dev/null 2>&1 +[ $(univention-certificate list | grep "$test_cert_name" | wc -l) -eq "1" ] || fail_test 2 + +list1=$(univention-certificate list) +num1=$(comm -13 <(echo "$list0") <(echo "$list1") | sed 's/\t.*//') +univention-certificate renew -name "$test_cert_name" -days "$test_days" -grace "$test_grace" >/dev/null 2>&1 +[ $(univention-certificate list | grep "$test_cert_name" | wc -l) -eq "2" ] || fail_test 3 + +list2=$(univention-certificate list) +num2=$(comm -13 <(echo "$list1") <(echo "$list2") | sed 's/\t.*//') +[ "$num1" != "$num2" ] || fail_test 4 + +/etc/cron.daily/univention-ssl >/dev/null 2>&1 +[ $(univention-certificate list | grep "$test_cert_name" | wc -l) -eq "2" ] || fail_test 5 + +# change expire date to an earlier date +temp=$(mktemp) +pending_certs=$(cat "$pending_file") +for cert in "${pending_certs[@]}"; do + num=$(sed 's/:.*//' <<< "$cert") + expire=$(sed 's/.*://' <<< "$cert") + if [ "$num" == "$num1" ]; then + expire="$(($expire - ($test_grace * 3600 * 24)))" + fi + echo "$num:$expire" >>"$temp" +done +mv "$temp" "$pending_file" +chmod 600 "$pending_file" + +/etc/cron.daily/univention-ssl >/dev/null 2>&1 +[ $(univention-certificate list | grep "$test_cert_name" | wc -l) -eq "1" ] || fail_test 6 + +univention-certificate revoke -name $test_cert_name >/dev/null 2>&1 +[ $(univention-certificate list | grep "$test_cert_name" | wc -l) -eq "0" ] || fail_test 7 + +exit 0 + Eigenschaftsänderungen: test/ucs-test/tests/01_base/101_renew_certificate_with_grace_period ___________________________________________________________________ Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property