diff --git a/easyrsa3/easyrsa b/easyrsa3/easyrsa index 5310bee..2f8be9d 100755 --- a/easyrsa3/easyrsa +++ b/easyrsa3/easyrsa @@ -44,6 +44,8 @@ Here is the list of commands available with a short syntax reminder. Use the show-cert [ cmd-opts ] show-ca [ cmd-opts ] show-crl + show-expire + show-revoke verify import-req export-p1 [ cmd-opts ] @@ -169,6 +171,16 @@ cmd_help() { show-crl Shows details of the current certificate revocation list (CRL) + Human-readable output is shown." ;; + show-expire) text=" + show-expire [ cmd-opts ] + Shows details of expiring certificates + + Human-readable output is shown." ;; + show-revoke) text=" + show-revoke [ cmd-opts ] + Shows details of revoked certificates + Human-readable output is shown." ;; verify) text=" verify @@ -1604,7 +1616,7 @@ revoke_move() { # Set certificate expire date, renew date and variables needed for fixdate cert_dates() { - if [ "$1" ]; then + if [ -e "$1" ]; then # Required for renewal # Call openssl directly, otherwise this is not debug compatible crt_not_before="$("$EASYRSA_OPENSSL" x509 -in "$1" -noout -startdate 2>&1)" \ @@ -1614,6 +1626,9 @@ cert_dates() { || die "cert_dates - crt_not_after: $crt_not_after" crt_not_after="${crt_not_after#*=}" shift + elif [ "$1" ]; then + # Required for status + crt_not_after="$1" else # Required for --fix-offset # This is a fake date to satisfy the 'if expire_date' command test @@ -2533,6 +2548,145 @@ $in_file" OpenSSL failure to process the input" } # => show_ca() +# Fixed format date +# Build a Windows date.exe compatible input field +build_ff_date_string() { + ff_date="$1" + [ "$ff_date" ] || die "ff_date: '$ff_date'" + yy="${ff_date%???????????}" + ff_date="${ff_date#"$yy"}" + mm="${ff_date%?????????}" + ff_date="${ff_date#"$mm"}" + dd="${ff_date%???????}" + ff_date="${ff_date#"$dd"}" + HH="${ff_date%?????}" + ff_date="${ff_date#"$HH"}" + MM="${ff_date%???}" + ff_date="${ff_date#"$MM"}" + SS="${ff_date%?}" + ff_date="${ff_date#"$SS"}" + TZ="$ff_date" + ff_date="${yy}-${mm}-${dd} ${HH}:${MM}:${SS}${TZ}" +} # => build_date_string() + +# SC2295: (info): Expansions inside ${..} need to be quoted separately, +# otherwise they match as patterns. (what-ever that means .. ;-) +# Unfortunately, Windows sh.exe has an absolutely ridiculous bug. +# Try this in sh.exe: t=' '; s="a${t}b${t}c"; echo "${s%%"${t}"*}" + +# Read db +# shellcheck disable=SC2295 +read_db() { + report="$1"; shift + tab_char=' ' + db_in="$EASYRSA_PKI/index.txt" + while read -r crt_stat crt_notAfter crt_record; do + + # Interpret the db/certificate record + unset -v crt_serial crt_cn crt_revokedate crt_reason + case "$crt_stat" in + V) + # Valid + crt_serial="${crt_record%%${tab_char}*}" + crt_record="${crt_record#*${tab_char}}" + crt_cn="${crt_record#*/CN=}"; crt_cn="${crt_cn%%/*}" + crt_file="$EASYRSA_PKI/issued/$crt_cn.crt" + ;; + R) + # Revoked + crt_revokedate="${crt_record%%${tab_char}*}" + crt_reason="${crt_revokedate#*,}" + [ -z "$crt_reason" ] || crt_revokedate="${crt_revokedate%,*}" + crt_record="${crt_record#*${tab_char}}" + + crt_serial="${crt_record%%${tab_char}*}" + crt_record="${crt_record#*${tab_char}}" + crt_cn="${crt_record#*/CN=}"; crt_cn="${crt_cn%%/*}" + ;; + *) die "Unexpected status: $crt_stat" + esac + + # do status report for this record + # TODO: renewed-not-revoked + case "$report" in + expire) if [ "$crt_stat" = V ]; then expire_status; fi ;; + revoke) if [ "$crt_stat" = R ]; then revoke_status; fi ;; + *) die "Unrecognised report: $report" + esac + done < "$db_in" +} # => read_db() + +# Expire status +expire_status() { + build_ff_date_string "$crt_notAfter" + + crt_file="$EASYRSA_PKI/issued/${crt_cn}.crt" + if [ -e "$crt_file" ]; then + # Use cert date + cert_dates "$crt_file" + else + # Use db translated date + cert_dates "$crt_notAfter" + fi + + if [ "$expire_date" -lt "$allow_renew_date" ]; then + # cert expires in less than grace period + printf '%s%s\n' "$crt_stat | Serial: $crt_serial | " \ + "Expires: $ff_date | CN: $crt_cn" + fi +} # => expire_status() + +# Revoke status +revoke_status() { + build_ff_date_string "$crt_revokedate" + + crt_file="$EASYRSA_PKI/revoked/certs_by_serial/$crt_serial.crt" + if [ -e "$crt_file" ]; then + # Use cert file + cert_dates "$crt_file" + else + # Use db translated date + cert_dates "$crt_notAfter" + fi + + printf '%s%s\n' "$crt_stat | Serial: $crt_serial | " \ + "Revoked: $ff_date | Reason: $crt_reason | CN: $crt_cn" +} # => revoke_status() + +# cert status reports +status() { + report="$1" + in_crt="$2" + shift 2 + + verify_ca_init + + case "$report" in + expire) + case "$in_crt" in + all) + print "Showing certificates which expire in less than $EASYRSA_CERT_RENEW days:" + print + read_db expire + ;; + *) print "Coming soon.." + esac + ;; + revoke) + case "$in_crt" in + all) + print "Showing certificates which are revoked:" + print + read_db revoke ;; + *) print "Coming soon.." + esac + ;; + *) + # TODO: renewed-not-revoked + warn "Unrecognised report: $report" + esac +} # => status() + # set_var is not known by shellcheck, therefore: # Fake declare known variables for shellcheck # Use these options without this function: @@ -3693,6 +3847,20 @@ case "$cmd" in verify) verify_cert "$@" ;; + show-expire) + if [ -z "$*" ]; then + status expire all + else + status expire "$@" + fi + ;; + show-revoke) + if [ -z "$*" ]; then + status revoke all + else + status revoke "$@" + fi + ;; upgrade) up23_manage_upgrade_23 "$@" ;;