1 ยท View the Full Certificate Chain

The -showcerts flag makes s_client print every certificate the server sends โ€” not just the leaf. Pipe through openssl x509 to decode human-readable fields.

BASH
# Dump every cert the server sends, plus handshake info
echo | openssl s_client -showcerts -connect google.com:443 -servername google.com 2>/dev/null
BASH
# Just the subject, issuer, and expiry of the leaf cert
echo | openssl s_client -connect google.com:443 2>/dev/null \
  | openssl x509 -noout -subject -issuer -dates
BASH
# Full decoded text of the leaf cert (verbose)
echo | openssl s_client -connect google.com:443 2>/dev/null \
  | openssl x509 -noout -text
Note: The echo | prefix sends an empty string to close stdin immediately after the handshake, so the command doesn't hang waiting for input.
2 ยท Save the CA Certificates to a File

With -showcerts, the output contains all certs separated by -----BEGIN/END CERTIFICATE----- markers. Cert #1 is always the leaf โ€” everything after is CA chain. Use awk to skip the first block.

BASH โ€” skip the leaf cert, save the rest
echo | openssl s_client -showcerts -connect google.com:443 2>/dev/null \
  | awk '
    BEGIN { n=0; p=0 }
    /-----BEGIN CERTIFICATE-----/ { n++; if (n>1) p=1 }
    p { print }
    /-----END CERTIFICATE-----/   { p=0 }
  ' > google.com-ca.pem

# Verify it saved correctly
openssl x509 -in google.com-ca.pem -noout -subject -issuer
BASH โ€” split into one file per cert
echo | openssl s_client -showcerts -connect google.com:443 2>/dev/null \
  | awk '
    BEGIN { n=0 }
    /-----BEGIN CERTIFICATE-----/ { n++; file="cert-"n".pem" }
    { print > file }
  '

# cert-1.pem = leaf, cert-2.pem = first CA, cert-3.pem = second CAโ€ฆ
openssl x509 -in cert-2.pem -noout -subject -issuer
Tip: If the server sends only one certificate (misconfigured), the awk filter above will produce an empty file. That's your signal that the server is leaf-only and you need to fetch the CA separately.
3 ยท Inspect a Saved Certificate
BASH
# Subject, issuer, validity window
openssl x509 -in ca.pem -noout -subject -issuer -dates

# SHA-256 fingerprint
openssl x509 -in ca.pem -noout -fingerprint -sha256

# Is it a CA cert? (look for CA:TRUE)
openssl x509 -in ca.pem -noout -text | grep -A2 "Basic Constraints"

# Subject Alternative Names (SANs)
openssl x509 -in ca.pem -noout -text | grep -A1 "Subject Alternative"

# Check if cert expires within 30 days (exit 1 if so)
openssl x509 -in ca.pem -checkend 2592000 || echo "Expires within 30 days!"
4 ยท Fetch the Root CA via AIA

When a server sends only the leaf cert (or you need the root CA which servers never send), the AIA (Authority Information Access) extension in the leaf cert contains a URL pointing to the issuing CA's certificate. It's almost always in DER format, so you need to convert it.

BASH โ€” one-liner: extract AIA URL โ†’ download โ†’ convert โ†’ inspect
# Step 1: get the AIA CA Issuers URL from the leaf cert
AIA_URL=$(echo | openssl s_client -connect google.com:443 2>/dev/null \
  | openssl x509 -noout -text \
  | grep "CA Issuers" \
  | grep -oP 'http://[^ ]+')

echo "AIA URL: $AIA_URL"

# Step 2: download (usually DER format)
curl -sL "$AIA_URL" -o issuer.der

# Step 3: convert DER โ†’ PEM
openssl x509 -inform DER -in issuer.der -out issuer.pem

# Step 4: inspect
openssl x509 -in issuer.pem -noout -subject -issuer -dates
BASH โ€” compact version for scripting
HOST=google.com; PORT=443
curl -sL $(echo | openssl s_client -connect $HOST:$PORT 2>/dev/null \
  | openssl x509 -noout -text | grep "CA Issuers" | grep -oP 'http://[^ ]+') \
  | openssl x509 -inform DER -out $HOST-root-ca.pem
5 ยท Format Conversion

TLS certificates exist in several formats. PEM is base64 text (the -----BEGIN CERTIFICATE----- format). DER is the raw binary equivalent. PKCS#7 bundles multiple certs. Most tools produce or consume PEM.

BASH
# DER โ†’ PEM
openssl x509 -inform DER -in cert.der -out cert.pem

# PEM โ†’ DER
openssl x509 -outform DER -in cert.pem -out cert.der

# PKCS#7 (.p7b) โ†’ PEM (expand all certs in the bundle)
openssl pkcs7 -print_certs -in bundle.p7b -out bundle.pem

# Concatenate multiple PEM certs into one chain file
cat intermediate.pem root.pem > ca-chain.pem

# Count PEM blocks in a file
grep -c "BEGIN CERTIFICATE" ca-chain.pem
6 ยท Verify a Certificate Against a CA

After you've saved the CA cert, you can verify that a server's leaf cert was actually signed by it. This is the core of TLS trust.

BASH
# Save just the leaf cert
echo | openssl s_client -connect google.com:443 2>/dev/null \
  | openssl x509 > leaf.pem

# Verify leaf against your saved CA chain
openssl verify -CAfile google.com-ca.pem leaf.pem
# โ†’ leaf.pem: OK

# Verify a live server's cert matches a saved CA (full handshake check)
openssl s_client -connect google.com:443 -CAfile google.com-ca.pem -verify_return_error 2>&1 \
  | grep "Verify return"
# โ†’ Verify return code: 0 (ok)
7 ยท Useful s_client Flags
BASH
# Custom port (e.g. LDAPS, SMTPS, internal service)
echo | openssl s_client -connect internal.corp:8443 -servername internal.corp 2>/dev/null

# Skip cert verification (self-signed / private CA)
echo | openssl s_client -connect internal.corp:443 -verify_quiet -noverify 2>/dev/null

# Show full chain with -showcerts; -no_ign_eof keeps connection open briefly
echo | openssl s_client -showcerts -connect example.com:443

# Force TLSv1.2 or TLSv1.3
echo | openssl s_client -tls1_2 -connect example.com:443 2>/dev/null
echo | openssl s_client -tls1_3 -connect example.com:443 2>/dev/null

# Check negotiated cipher suite
echo | openssl s_client -connect example.com:443 2>/dev/null | grep "Cipher\|Protocol"

# STARTTLS (SMTP, IMAP, etc.)
echo | openssl s_client -connect mail.example.com:587 -starttls smtp 2>/dev/null
8 ยท OpenSSL vs tls-ca-fetch
Task openssl tls-ca-fetch
View chain openssl s_client -showcerts โ€ฆ tls-ca-fetch hostname
Save CA cert(s) s_client + awk pipeline automatic
Identify leaf vs CA manual grep for CA:TRUE automatic
AIA root fetch manual grep + curl + openssl convert -fetch-root flag
Private / self-signed -noverify flag -insecure flag
Format conversion full control PEM only
Verify cert against CA openssl verify not supported
STARTTLS (SMTP/IMAP) -starttls flag not supported
Dependencies openssl + awk + curl (usually pre-installed) none โ€” single binary
Windows needs WSL or Git Bash .exe available
Scriptability composable with shell tools structured output
Bottom line: Use openssl when you need full control, format conversion, or STARTTLS. Use tls-ca-fetch when you just want the CA cert file in one command with no pipeline gymnastics โ€” especially on Windows or in environments where shell pipelines are awkward.