· 6 years ago · Jan 15, 2020, 10:58 AM
1#!/bin/bash
2
3usage()
4{
5cat <<EOF
6Usage: $(basename $0) [options]
7
8This shell script is a simple wrapper around the openssl binary. It uses
9s_client to get certificate information from remote hosts, or x509 for local
10certificate files. It can parse out some of the openssl output or just dump all
11of it as text.
12
13Options:
14
15 --all-info Print all output, including boring things like Modulus and
16 Exponent.
17
18 --alt Print Subject Alternative Names. These will be typically be
19 additional hostnames that the certificate is valid for.
20
21 --cn Print commonName from Subject. This is typically the host for
22 which the certificate was issued.
23
24 --debug Print additional info that might be helpful when debugging this
25 script.
26
27 --end Print certificate expiration date. For additional functionality
28 related to certificate expiration, take a look at this script:
29 "http://prefetch.net/code/ssl-cert-check".
30
31 --dates Print start and end dates of when the certificate is valid.
32
33 --end_days Print days untill certifiactes expires.
34
35 --file Use a local certificate file for input.
36
37 --help Print this help message.
38
39 --host Fetch the certificate from this remote host.
40
41 --name Specify a specific domain name (Virtual Host) along with the
42 request. This value will be used as the '-servername' in the
43 s_client command. This is for TLS SNI (Server Name Indication).
44
45 --issuer Print the certificate issuer.
46
47 --most-info Print almost everything. Skip boring things like Modulus and
48 Exponent.
49
50 --option Pass any openssl option through to openssl to get its raw
51 output.
52
53 --port Use this port when conneting to remote host. If ommitted, port
54 defaults to 443.
55
56 --subject Print the certificate Subject -- typically address and org name.
57
58 --thumbprint Prints certificate thumbprint.
59
60Examples:
61
62 1. Print a list of all hostnames that the certificate used by amazon.com
63 is valid for.
64
65 $(basename $0) --host amazon.com --alt
66 DNS:uedata.amazon.com
67 DNS:amazon.com
68 DNS:amzn.com
69 DNS:www.amzn.com
70 DNS:www.amazon.com
71
72 2. Print issuer of certificate used by smtp.gmail.com. Fetch certficate info
73 over port 465.
74
75 $(basename $0) --host smtp.gmail.com --port 465 --issuer
76 issuer=
77 countryName = US
78 organizationName = Google Inc
79 commonName = Google Internet Authority G2
80
81 3. Print valid dates for the certificate, using a local file as the source of
82 certificate data. Dates are formatted using the date command and display
83 time in your local timezone instead of GMT.
84
85 $(basename $0) --file /path/to/file.crt --dates
86 valid from: 2014-02-04 16:00:00 PST
87 valid till: 2017-02-04 15:59:59 PST
88
89
90 4. Print certificate serial number. This script doesn't have a special option
91 to parse out the serial number, so will use the generic --option flag to
92 pass '-serial' through to openssl.
93
94 $(basename $0) --host gmail.com --option -serial
95 serial=4BF004B4DDC9C2F8
96
97EOF
98}
99
100if ! [ -x "$(type -P openssl)" ]; then
101 echo "ERROR: script requires openssl"
102 echo "For Debian and friends, get it with 'apt-get install openssl'"
103 exit 1
104fi
105
106while [ "$1" ]; do
107 case "$1" in
108 --file)
109 shift
110 crt="$1"
111 source="local"
112 ;;
113 --host)
114 shift
115 host="$1"
116 source="remote"
117 ;;
118 --port)
119 shift
120 port="$1"
121 ;;
122 --name)
123 shift
124 servername="-servername $1"
125 ;;
126 --all-info)
127 opt="-text"
128 ;;
129 --alt)
130 FormatOutput() {
131 grep -A1 "Subject Alternative Name:" | tail -n1 |
132 tr -d ' ' | tr ',' '\n'
133 }
134 ;;
135 --cn)
136 opt="-subject -nameopt multiline"
137 FormatOutput() {
138 awk '/commonName/ {print$NF}'
139 }
140 ;;
141 --dates)
142 opt="-dates"
143 FormatOutput() {
144 dates=$(cat -)
145 start=$(grep Before <<<"$dates" | cut -d= -f2-)
146 end=$(grep After <<<"$dates" | cut -d= -f2-)
147 echo valid from: $(date -d "$start" '+%F %T %Z')
148 echo valid till: $(date -d "$end" '+%F %T %Z')
149 }
150 ;;
151 --end)
152 opt="-enddate"
153 FormatOutput() {
154 read end
155 end=$(cut -d= -f2- <<<"$end")
156 date -d "$end" '+%F %T %Z'
157 }
158 ;;
159 --end_days)
160 opt="-enddate"
161 FormatOutput() {
162 read end
163 end=$(cut -d= -f2- <<<"$end")
164# date -d "$end" '+%s'
165# date +'%s'
166# echo $(( $(date -d "$end" '+%s') - $(date +'%s') ))
167 echo $(( ( $(date -d "$end" '+%s') - $(date +'%s') )/(60*60*24) ))
168 }
169 ;;
170 --issuer)
171 opt="-issuer -nameopt multiline"
172 ;;
173 --most-info)
174 opt="-text -certopt no_header,no_version,no_serial,no_signame,no_pubkey,no_sigdump,no_aux"
175 ;;
176 --option)
177 shift
178 opt="$1"
179 ;;
180 --subject)
181 opt="-subject -nameopt multiline"
182 ;;
183 --help)
184 usage
185 exit 0
186 ;;
187 --test)
188 FormatOutput() {
189 if grep -q "unable to load certificate"; then echo "false"; else echo "true"; fi
190 }
191 ;;
192 --thumbprint)
193 opt="-fingerprint"
194 FormatOutput() {
195 awk -F"=" '{print$2}' | sed s/://g
196 }
197 ;;
198 --debug)
199 DEBUG="yes"
200 ;;
201 *)
202 echo "$(basename $0): invalid option $1" >&2
203 echo "see --help for usage"
204 exit 1
205 ;;
206 esac
207 shift
208done
209
210CheckLocalCert()
211{
212 openssl x509 -in $crt -noout $opt
213}
214
215CheckRemoteCert()
216{
217 echo |
218 openssl s_client $servername -connect $host:$port $options 2>/dev/null |
219 openssl x509 -noout $opt 2>&1
220}
221
222if [ -z "$(type -t FormatOutput)" ]; then
223 FormatOutput() { cat; }
224fi
225
226if [ -z "$opt" ]; then
227 opt="-text -certopt no_header,no_version,no_serial,no_signame,no_pubkey,no_sigdump,no_aux"
228fi
229
230if [ -z "$source" ]; then
231 echo "ERROR: missing certificate source."
232 echo "Provide one via '--file' or '--host' arguments."
233 echo "See '--help' for examples."
234 exit 1
235fi
236
237if [ "$source" == "local" ]; then
238 [ -n "$DEBUG" ] && echo "DEBUG: certificate source is local file"
239 if [ -z "$crt" ]; then
240 echo "ERROR: missing certificate file"
241 exit 1
242 fi
243 [ -n "$DEBUG" ] && echo
244 CheckLocalCert | FormatOutput
245fi
246
247if [ "$source" == "remote" ]; then
248 [ -n "$DEBUG" ] && echo "DEBUG: certificate source is remote host"
249 if [ -z "$host" ]; then
250 echo "ERROR: missing remote host value."
251 echo "Provide one via '--host' argument"
252 exit 1
253 fi
254 if [ -z "$port" ]; then
255 [ -n "$DEBUG" ] && echo "DEBUG: defaulting to 443 for port."
256 port="443"
257 fi
258 if [ "$port" -eq "465" ] || [ "$port" -eq "25" ] || [ "$port" -eq "587" ]; then
259 [ -n "$DEBUG" ] && echo "DEBUG: Presuming that $port is a smtp port, adding starttls."
260 options="-starttls smtp"
261 fi
262
263 [ -n "$DEBUG" ] && echo
264 CheckRemoteCert | FormatOutput
265fi