openfire-docker-compose/federation/scripts/revocation.sh

176 lines
5.4 KiB
Bash
Executable File

#!/bin/bash
# Configuration
CERT_DIR="./_data/certs"
INDEX_FILE="${CERT_DIR}/ca/intermediate-ca/index.txt"
CA_CERT="${CERT_DIR}/ca/intermediate-ca/intermediate.crt"
CA_KEY="${CERT_DIR}/ca/intermediate-ca/private/intermediate.key"
# Default revocation reason
REASON="unspecified"
FOUND_CERT=false
ACTION="revoke" # Default action
# Usage information
usage() {
echo "Usage: $0 [--server servername] [--cert certificate_file] [--reason reason_code] [--unrevoke]"
echo "Revokes or unrevokes an SSL certificate and updates the OCSP database"
echo ""
echo "Options:"
echo " --server Server name (e.g., xmpp1)"
echo " --cert Path to the certificate to revoke (alternative to --server)"
echo " --reason Reason for revocation (optional):"
echo " unspecified (default)"
echo " keyCompromise"
echo " CACompromise"
echo " affiliationChanged"
echo " superseded"
echo " cessationOfOperation"
echo " certificateHold"
echo " --unrevoke Removes the revocation status of the certificate"
exit 1
}
# Parse command line options
while [[ $# -gt 0 ]]; do
case $1 in
--server)
SERVER_NAME="$2"
if [[ ! "$SERVER_NAME" =~ ^xmpp[0-9]+$ ]]; then
echo "Error: Server name must be in format 'xmpp<number>' (e.g., xmpp1)"
usage
fi
CERTIFICATE="${CERT_DIR}/${SERVER_NAME}.crt"
shift 2
;;
--cert)
CERTIFICATE="$2"
shift 2
;;
--reason)
case "$2" in
unspecified|keyCompromise|CACompromise|affiliationChanged|superseded|cessationOfOperation|certificateHold)
REASON="$2"
;;
*)
echo "Error: Invalid reason. See usage for valid reasons."
usage
;;
esac
shift 2
;;
--unrevoke)
ACTION="unrevoke"
shift
;;
-h|--help)
usage
;;
*)
echo "Error: Unknown option $1"
usage
;;
esac
done
# Validate input and files
if [ -z "$CERTIFICATE" ]; then
echo "Error: Either --server or --cert must be specified"
usage
fi
for file in "$CERTIFICATE" "$INDEX_FILE" "$CA_CERT" "$CA_KEY"; do
if [ ! -f "$file" ]; then
echo "Error: Required file not found: $file"
exit 1
fi
done
# Create backup
INDEX_BACKUP="${INDEX_FILE}.$(date +%Y%m%d%H%M%S).bak"
cp "$INDEX_FILE" "$INDEX_BACKUP"
# Get certificate serial number
SERIAL=$(openssl x509 -in "$CERTIFICATE" -noout -serial | cut -d'=' -f2)
# Create new index file
> "$INDEX_FILE.new"
# Read and process each line
while read -r line; do
# Split the line into fields
status=$(echo "$line" | cut -f1)
expiry=$(echo "$line" | cut -f2)
revocation=$(echo "$line" | cut -f3)
serial=$(echo "$line" | cut -f4)
filename=$(echo "$line" | cut -f5)
subject=$(echo "$line" | cut -f6)
if [ "$serial" = "$SERIAL" ]; then
if [ "$ACTION" = "revoke" ]; then
if [ "$status" = "R" ]; then
echo "Error: Certificate is already revoked"
rm "$INDEX_FILE.new"
rm "$INDEX_BACKUP"
exit 1
fi
# Create revoked entry
REVOKE_DATE=$(date -u +%y%m%d%H%M%SZ)
printf 'R\t%s\t%s,%s\t%s\t%s\t%s\n' \
"$expiry" \
"$REVOKE_DATE" \
"$REASON" \
"$serial" \
"$filename" \
"$subject" >> "$INDEX_FILE.new"
else # unrevoke
if [ "$status" != "R" ]; then
echo "Error: Certificate is not revoked"
rm "$INDEX_FILE.new"
rm "$INDEX_BACKUP"
exit 1
fi
# Convert back to valid entry
printf 'V\t%s\t\t%s\t%s\t%s\n' \
"$expiry" \
"$serial" \
"$filename" \
"$subject" >> "$INDEX_FILE.new"
fi
FOUND_CERT=true
else
# Not our certificate - keep original line
echo "$line" >> "$INDEX_FILE.new"
fi
done < "$INDEX_FILE"
if [ "$FOUND_CERT" = false ]; then
echo "Error: Certificate not found in database"
echo "Looking for serial: $SERIAL"
rm "$INDEX_FILE.new"
exit 1
fi
if mv "$INDEX_FILE.new" "$INDEX_FILE"; then
if [ "$ACTION" = "revoke" ]; then
echo "Certificate successfully revoked"
echo "Reason: $REASON"
else
echo "Certificate successfully unrevoked"
fi
echo -e "\nTo verify the current status:"
echo "openssl ocsp -url http://ocsp.localhost.example:8888 \\"
echo " -issuer ${CERT_DIR}/ca/intermediate-ca/intermediate.crt \\"
echo " -CAfile ${CERT_DIR}/$(basename "$CERTIFICATE" .crt)_chain.pem \\"
echo " -cert ${CERTIFICATE} \\"
echo " -text"
echo -e "\nNote: The first OCSP status check may return the previous status."
echo " Run the check again if this happens - subsequent checks will show the current status."
# Clean up backup file on success
rm "$INDEX_BACKUP"
else
echo "Error: Failed to ${ACTION} certificate"
echo "Restoring database backup..."
cp "$INDEX_BACKUP" "$INDEX_FILE"
exit 1
fi