summaryrefslogtreecommitdiff
path: root/cert-info
diff options
context:
space:
mode:
authorPeter Wu <lekensteyn@gmail.com>2013-04-23 18:59:15 +0200
committerPeter Wu <lekensteyn@gmail.com>2013-04-23 18:59:15 +0200
commitaf38cb02a9ca95b20056bc92e73fe72a45d1f523 (patch)
tree41628cac3a02d2c4dcf4ff6ecbb1fb8c5378db20 /cert-info
downloadscripts-af38cb02a9ca95b20056bc92e73fe72a45d1f523.tar.gz
Initial checkin.
Diffstat (limited to 'cert-info')
-rwxr-xr-xcert-info128
1 files changed, 128 insertions, 0 deletions
diff --git a/cert-info b/cert-info
new file mode 100755
index 0000000..b4aa9b1
--- /dev/null
+++ b/cert-info
@@ -0,0 +1,128 @@
+#!/bin/bash
+# see also Docs/ssl-infos/tools/
+# i= &&tail -n+$((i*5000)) /tmp/top-1m.csv | head -5000 |~/scripts/cert-info csv $i
+# killall -v cert-info -s 0
+usage() {
+ [ -z "$1" ] || echo "$1" >&2
+ echo "Usage: $0 [options] hostname[:port] [hostname[:port]].." >&2
+ echo " $0 csv out-dir <file [options]" >&2
+ echo "options (may be interleaved between hosts):"
+ awk '/^parse_arg\(/{p=1}
+ /}/{if(p)exit}
+ /#/{if(p){sub(/\).*# */,"\t");print}}' "$0"
+ echo "csv file from http://s3.amazonaws.com/alexa-static/top-1m.csv.zip"
+ exit 1
+}
+
+auto_less() {
+ [ ! -t 1 ] || { "$0" "$@" | less; exit $?; }
+}
+
+main() {
+if [ "$1" = "csv" ]; then
+ [ $# -ge 2 ] || usage "Missing outdir"
+ outdir="${2:-.}/"
+ mkdir -p "$outdir"
+ tmp=$(mktemp); trap "rm -f $tmp" EXIT
+ shift 2
+ for arg; do parse_arg "$arg" || usage "Unrecognized option $arg"; done
+ i=0
+ while IFS=,; read -r no host; do
+ # strip path if any
+ host="${host%%/*}"
+ [ -n "$host" ] || continue
+ outfile="$outdir$host.txt"
+ if [ -e "$outfile" ]; then
+ echo "Skipping existing $outfile"
+ else
+ printf "%5d %s %6d %s\n" $((++i)) "$(date -R)" "$no" "$host"
+ get_cert "$host" 443 | parse_cert > "$tmp" 2>&1
+ mv "$tmp" "$outfile"
+ #[ -s "$outfile" ] || echo "# no cert for $host"
+ fi
+ done
+elif [ ! -t 0 ]; then
+ auto_less "$@"
+ for arg; do
+ parse_arg "$arg" || :
+ done
+ parse_cert
+elif [ $# -gt 0 ]; then
+ auto_less "$@"
+ for arg; do
+ ! parse_arg "$arg" || continue
+ host="${arg%%:*}"
+ port="${arg##*:}"
+ [ "$port" != "$arg" -a -n "$port" ] || port=443
+ echo "# === $host:$port ==="
+ get_cert "$host" "$port" | parse_cert
+ done
+else
+ usage
+fi
+}
+
+get_cert() {
+ local host="$1" port="$2"
+ if ! nc -z -w 2 "$host" "$port"; then
+ echo "# conn timeout for $host:$port!" >&2
+ return 1
+ fi
+ </dev/null 2>/dev/null \
+ timeout 5 openssl s_client -connect "$host:$port" -showcerts
+}
+
+parse_arg() {
+ case "$1" in
+ -) depth_1=1 ;; # less certificates [def]
+ +) depth_1=0 ;; # more certificates
+ -=) cert_only=1 ;; # less output (just raw cert)
+ +=) cert_only=0 ;; # more output (verbose details) [def]
+ -cert) include_cert=0 ;; # hide raw cert (-noout)
+ +cert) include_cert=1 ;; # include raw cert [def]
+ *) return 1 ;;
+ esac
+}
+parse_arg -
+parse_arg +=
+parse_arg +cert
+
+parse_cert() {
+ infocmd="openssl x509 -text -nameopt sep_comma_plus_space"
+ [ $include_cert -eq 1 ] || infocmd="$infocmd -noout"
+ awk -vOneOnly="$depth_1" -vCertOnly="$cert_only" \
+ -vinfocmd="$infocmd" '
+BEGIN {
+ sep="# ";
+ for (i=0; i<77; i++) {
+ sep=sep"-";
+ }
+}
+/^-----BEGIN CERTIFICATE-----$/ {
+ in_cert=1;
+}
+{
+ if (in_cert) {
+ cert = cert $0 "\n";
+ }
+}
+/^-----END CERTIFICATE-----$/ {
+ in_cert = 0;
+}
+{
+ if (!in_cert && cert) {
+ if (CertOnly) {
+ print cert;
+ } else {
+ print cert | infocmd;
+ close(infocmd);
+ print sep;
+ }
+ cert="";
+ if (OneOnly) exit;
+ }
+}
+'
+}
+
+main "$@"