#!/usr/bin/bash

# SSL info

show_help() {
cat << EOF
Usage: $0 [info|infoall|subject|modulus|check] openssl_crt_key_files
Examples:
	compare 2 modulus files:
		$0 check file1 file2
	show modulus:
		$0 modulus file
	show online info from https web:
		$0 web hostname_from_URL
		$0 https://url...
	show online info from mail or other tcp based service:
		$0 mail hostname port
		$0 submission://hostname
		$0 smtps://hostname
		$0 [imaps|pop3s]://hostname
	show info (with pager):
		$0 file
	convert der to pem:
		convert filename.[crt|der] [filename.pem]
	generate private key and csr:
		csr domain.name
EOF
exit 0
}

CERT_OPTS="-certopt no_signame,no_pubkey,no_sigdump,no_extensions -ext subjectAltName"

ssl_read() {
  if [ ! -f "$1" ]; then
    echo "ERROR: File not found: $1!"
    exit 1
  fi
  if grep -q '^-----BEGIN\( .* \| \)PRIVATE KEY-----' "$1"; then
    openssl rsa -noout -in "$@"
  elif grep -q '^-----BEGIN CERTIFICATE REQUEST-----' "$1"; then
    openssl req -noout -in "$@"
  elif grep -q '^-----BEGIN X509 CRL-----' "$1"; then
    openssl crl -noout -in "$@"
  elif grep -q '^-----BEGIN' "$1"; then
    openssl x509 -noout -in "$@"
  else
    # der format
    openssl x509 -noout -inform der -in "$@"
    echo "DER format detected!"
  fi
}

ssl_read_all() {
  txt=""
  while read line; do
    if [ "${line//-----END}" != "$line" ]; then
        txt="$txt$line\n"
        printf -- "$txt" \
          | openssl x509 -noout -text $CERT_OPTS
        txt=""
    else
        txt="$txt$line\n"
    fi
  done < "$1"
}

ssl_read_tcp() {
  if [ "$2" = "submission" -o "$2" = "587" ]; then
    tls_args="-starttls smtp"
  else
    tls_args=""
  fi
  if [[ "$1" =~ ^[0-9.:]*$ ]]; then
    servername=""
  else
    servername="-servername $1"
  fi
  openssl s_client -showcerts $servername -connect "$1:$2" $tls_args \
    </dev/null 2>/dev/null \
    | ssl_read_all /dev/stdin
}

check_modulus() {
  m1="`ssl_read \"$1\" -modulus | cut -d= -f2`"
  m2="`ssl_read \"$2\" -modulus | cut -d= -f2`"
  if [ "$m1" = "$m2" ]; then
    echo "MATCH OK"
    if [ "$3" = "-d" ]; then
      echo "$m1"
      echo "$m2"
    fi
    exit 0
  else
    echo "$m1"
    echo "$m2"
    echo "NO MATCH"
    exit 1
  fi
}

ssl_convert() {
  SRC="$1"
  if [ "$2" ]; then
    TGT="$2"
  else
    TGT="${SRC%.*}.pem"
  fi
  echo "Converting $SRC -> $TGT ..."
  openssl x509 -inform der -in "$SRC" -out "$TGT"
}

ssl_csr() {
  DOMAIN="${1##\*.}"
  echo "CSR request for: $1 [$DOMAIN]"
  if [ -f "$DOMAIN.key" ]; then
    echo "Private key $DOMAIN.key already exists!"
    exit 1
  fi
  SUBJ="/CN=$1"
  openssl req -new -nodes -newkey rsa:2048 \
    -subj "$SUBJ" -keyout "$DOMAIN.key" -out "$DOMAIN.csr"
  echo
  openssl req -text -noout -sha256 -in "$DOMAIN.csr" \
    | grep 'CN *=' | sed 's/[ \t]*//g'
  echo
  cat "$DOMAIN.csr"
}

get_hostname() {
  echo "`echo $1 | awk -F[:/] '{ print $4 }'`"
}

get_proto() {
  echo "`echo $1 | cut -d: -f1`"
}

case "$1" in
  "")
	show_help
	;;
  i|info)
	shift
	for i in "$@"; do
		echo "$i:"
		ssl_read "$i" -text
	done
	;;
  ia|infoall)
	shift
	for i in "$@"; do
		echo "$i:"
		ssl_read_all "$i"
	done
	;;
  web|info_web)
	shift
	for i in "$@"; do
		echo "$i:"
		ssl_read_tcp "$i" 443
	done
	;;
  "https://"*|"http://"*)
	ssl_read_tcp "`get_hostname $1`" 443
	;;
  mail|info_mail)
	shift
	ssl_read_tcp "$@"
	;;
  "pop3s://"*|"imaps://"*|"smtps://"*|"submission://"*)
	ssl_read_tcp "`get_hostname $1`" "`get_proto $1`"
	;;
  m|mod*)
	shift
	for i in "$@"; do
		echo "$i:"
		ssl_read "$i" -modulus
	done
	;;
  check)
	shift
	check_modulus "$@"
	;;
  s|sub*)
	shift
	for i in "$@"; do
		echo "$i:"
		ssl_read "$i" -subject | sed 's/^subject *= *//i'
	done
	;;
  convert)
	shift
	ssl_convert "$@"
	;;
  csr)
	shift
	ssl_csr "$@"
	;;
  *)
	for i in "$@"; do
		ssl_read "$i" -text | less -FX
	done
	;;
esac
