12

I needed my script to email admin if there is a problem, and the company only uses Gmail. Following a few posts instructions I was able to set up mailx using a .mailrc file. there was first the error of nss-config-dir I solved that by copying some .db files from a firefox directory. to ./certs and aiming to it in mailrc. A mail was sent.

However, the error above came up. By some miracle, there was a Google certificate in the .db. It showed up with this command:

~]$ certutil -L -d certs

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

GeoTrust SSL CA                                              ,,
VeriSign Class 3 Secure Server CA - G3                       ,,
Microsoft Internet Authority                                 ,,
VeriSign Class 3 Extended Validation SSL CA                  ,,
Akamai Subordinate CA 3                                      ,,
MSIT Machine Auth CA 2                                       ,,
Google Internet Authority                                    ,,

Most likely, it can be ignored, because the mail worked anyway. Finally, after pulling some hair and many googles, I found out how to rid myself of the annoyance.

First, export the existing certificate to a ASSCII file:

~]$ certutil -L -n 'Google Internet Authority'  -d certs -a > google.cert.asc

Now re-import that file, and mark it as a trusted for SSL certificates, ala:

~]$ certutil -A -t "C,," -n 'Google Internet Authority'  -d certs -i google.cert.asc

After this, listing shows it trusted:

~]$ certutil -L -d certs

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI
...
Google Internet Authority                                    C,,

And mailx sends out with no hitch.

~]$ /bin/mailx -A gmail -s "Whadda ya no" [email protected]
ho ho ho
EOT
~]$

I hope it is helpful to someone looking to be done with the error.

Also, I am curious about somethings.

How could I get this certificate, if it were not in the mozilla database by chance? Is there for instance, something like this?

    ~]$ certutil -A -t "C,," \
                 -n 'gmail.com'  \
                 -d certs \
                 -i 'http://google.com/cert/this...'

4 Answers 4

13

Well it is not the one liner I wanted, but this is how to fetch and import a certificate from scratch:

# Create a certificate directory
~]$ mkdir certs

# Create a new database in the certs dir
~]$ certutil -N -d certs 

# Need now a chain certificate - May 18, 2015
~]$ wget https://www.geotrust.com/resources/root_certificates/certificates/GeoTrust_Global_CA.cer

# Need now a chain certificate part 2 - May 18, 2015
~]$ mv GeoTrust_Global_CA.cer certs/

# Fetch the certificate from Gmail, saving in the text file GMAILCERT
# Added the CA opion - May 18, 2015
~]$ echo -n | openssl s_client -connect smtp.gmail.com:465 -CAfile certs/GeoTrust_Global_CA.cer | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > GMAILCERT

# Import the new cert file into the new database in the new dir
~]$ certutil -A -n "Google Internet Authority" -t "C,," -d certs -i GMAILCERT 

# Double Check
~]$ certutil -L -d certs

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

Google Internet Authority                                    C,,  

Yaa! and thanks to the answer on this ticket

3
  • 1
    I'm getting an error again, "Error in certificate: Peer's certificate issuer is not recognized.". The gmail certificate I had ingested had expired, looks like the new one is a chained certificate. openssl s_client -showcerts -connect smtp.gmail.com:465 </dev/null to view them all.
    – spazm
    May 11, 2015 at 0:46
  • 1
    Updated the answer with a step to download the issuers cer file.
    – ndasusers
    May 19, 2015 at 0:28
  • Thanks to this ticket
    – ndasusers
    May 19, 2015 at 0:34
9

This post needs to be updated again. I was having trouble with my mailx install on my CentOS 7 box. Mail would send but I was still receiving the "Error in certified: Peer's certificate issuer is not recognized." error.

I found the solution here, had to translate it though.

Here is a quick way to do it:

# Create a certificate directory
mkdir ~/.certs

# Create a new database in the certs dir (dont forget to enter your pass phrase!)
certutil -N -d ~/.certs 

# Create three files for the cert chain
touch ~/.certs/google ~/.certs/geotrust ~/.certs/equifax

# Copy the cert chain for smtp.google.com:465 over to my_certs file (don't forget the -showcerts option, CTRL + C to end this command)
openssl s_client -showcerts -connect smtp.gmail.com:465 > ~/.certs/my_certs

Now copy each certificate including the --BEGIN CERTIFICATE-- and --END CERTIFICATE-- and paste them into their respective files you created earlier (google, geotrust, equifax) and now save those files.

# Open your my_certs file you made earlier and copy the google cert (usually the first one)
nano ~/.certs/my_certs

# Open your google file, paste the google cert that you just copied, and save and close
nano ~/.certs/google

# Open your my_certs file you made earlier and copy the geotrust cert (usually the second one)
nano ~/.certs/my_certs

# Open your geotrust file, paste the geotrust cert that you just copied, and save and close
nano ~/.certs/geotrust

# Open your my_certs file you made earlier and copy the equifax cert (usually the third one)
nano ~/.certs/my_certs

# Open your equifax file, paste the equifax cert that you just copied, and save and close
nano ~/.certs/equifax

Now we have to import each of these certs into the db.

# Import the google cert into the db
certutil -A -n "Google Internet Authority" -t "TC,," -d ~/.certs -i ~/.certs/google

# Import the geotrust cert into the db
certutil -A -n "GeoTrust Global CA" -t "TC,," -d ~/.certs -i ~/.certs/geotrust

# Import the equifax cert into the db
certutil -A -n "Equifax Secure Certificate Authority" -t "TCP,," -d ~/.certs -i ~/.certs/equifax

# Double check to make sure everything imported correctly into the db
certutil -L -d ~/.certs

Example output:

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

Google Internet Authority                                    CT,,
GeoTrust Global CA                                           CT,,
Equifax Secure Certificate Authority                         CT,,

Clean up time (optional)

# Remove all unnecessary files since the db has the certs :)
rm -rf ~/.certs/google ~/.certs/geotrust ~/.certs/equifax ~/.certs/my_certs

# Now run a test to make sure mailx is sending correctly now (don't forget to change [email protected] to the email address you'd like to send to)
echo "Your message" | mail -s "Message Subject" [email protected]

That should be it, you shouldn't receive the "Error in certified: Peer's certificate issuer is not recognized." error any more!

Notes:

You might have noticed that I changed the dir from /certs to ~/.certs. mailx runs as root so I just made these changes as root/. "~/" means HOME directory put it all together ~/.certs means /root/.certs/. I'm sure you knew that but hey just in case you never know who might be reading this!

Just in case you need this, here is the configuration options I added to the bottom of /etc/mail.rc

# /etc/mail.rc options added to the bottom
set smtp-use-starttls
set smtp-auth=login
set smtp=smtp://smtp.gmail.com:587
set from="[email protected](Web01 Server)"
set [email protected]
set smtp-auth-password=your.pass
set ssl-verify=ignore
set nss-config-dir=/root/.certs

Make sure to change your.from.user, your.smtp.user, and your.pass to their respective variables.

7
  • Thanks opterons this worked like charm, I don't know why @ndasusers did not work. Dec 14, 2015 at 12:33
  • Anybody know how to solve the issue when the email servers are load balanced and run as a cluster? e.g. Office 365 The cert will intermittently get an error because the server at the end of the connection changes from connection to connection.
    – Brad
    Nov 15, 2017 at 20:17
  • This is out of date again: -showcerts gives two certificates, not 3. The second one is a GlobalSign one. Still, this procedure is the only one that works, so +1: use -showcerts, find all the certificates in it (currently 2), and individually import them into the database.
    – EML
    May 17, 2018 at 17:50
  • ...and run openssl as echo -n | openssl, ot it hangs waiting for input
    – EML
    May 17, 2018 at 17:53
  • @EML+ or openssl s_client </dev/null. Yes, as of 2017 Google (including gmail) switched from GIA2 under GeoTrust/Equifax to GIA3 under GlobalSign. But there is no need to store all the certs of the chain. And if any criminal or impostor (like a nosy government) impersonates gmail, this method not only trusts them but does so permanently -- other users might be temporarily fooled by an illegitimately issued cert but when it is revoked they stop trusting it whereas with this method you continue to give all your email to evildoers. Aug 24, 2019 at 9:07
1

@pyr0ball, just updated little changes in your script and thanks for sharing nice approach :)

#!/bin/bash
certdirectory="/root/.certs"
fail() {
    ec=$?
    [ "${ec}" == "0" ] && ec=1
    echo -e "FAILED[code=$ec]: $@"
    exit $ec
}

cleanup() {
  rm /tmp/allgcert* || warn "Cleanup of files errored"
  rm /tmp/gcert* || warn "Cleanup of files errored"
}

failclean() {
  cleanup
  fail "$@"
}

numcerts=$(echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | grep -c "i:")
mkdir -p $certdirectory || fail "Unable to create certificates directory"
echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/allgcert || failclean "Unable to pull certs from smtp.gmail.com"
awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/{if(/-----BEGIN CERTIFICATE-----/){a++}; out="/tmp/gcert"a".crt"; print > out}' /tmp/allgcert
echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | grep i: | sed -e 's,.*=,,' > /tmp/allgcertnames || failclean "Unable to output parsed names for certificates"

for i in $(seq 1 $numcerts) ; do
  certutil -A -n "$(sed -n ${i}p /tmp/allgcertnames)" -t "TC,," -d $certdirectory -i /tmp/gcert${i}.crt || failclean "Unable to import certificates to database"
done

cleanup
1
  • Why grep i: instead of grep s:? Why do you use the issuer's name? If you use the issuer's name, you will get two same names, since sometimes the root CA is issued by itself. So that the intermediate cert and the root cert have the same name, which is the root CA name. @Vadiraj k.s @pyr0ball
    – Nick Dong
    Jun 21, 2023 at 4:43
0

I created a little script, based on the replies in this thread, that will automatically pull, parse, and install the current gmail smtp certs. It should be able to handle it if the number of certs changes again.

Here's a pastebin with syntax highlighting as well

#!/bin/bash

# This script pulls ssl certs for using gmail smtp. Adapted from the following config explaination:
# https://serverfault.com/questions/498588/smtp-gmail-com-from-bash-gives-error-in-certificate-peers-certificate-issuer

certdirectory="/home/user/.certs"

# Functions

fail() {
    ec=$?
    [ "${ec}" == "0" ] && ec=1
    echo -e "FAILED[code=$ec]: $@"
    exit $ec
}

warn(){
echo -e "WARNING $@"
}

cleanup() {
  rm allgcert* || warn "Cleanup of files errored"
  rm gcert* || warn "Cleanup of files errored"
}

failclean() {
  cleanup
  fail "$@"
}

# Count number of certs currently being used (can change from time to time)
numcerts=$(echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | grep -c "i:")

# Create the certs directory if it does not exist
mkdir -p $certdirectory || fail "Unable to create certificates directory"

# Pull certs to a local file for parsing
echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > allgcert || failclean "Unable to pull certs from smtp.gmail.com"

# Parses certs output based on the number of certs, and outputs to individual files
if (($numcerts > 1)) ; then
  # Pulls the first cert out as it needs one extra line
  sed '1,27!d' allgcert > gcert1
  # For subsequent certs, it multiplies the cert number by the number of lines in the file where it should exist
  for i in $(seq 2 $numcerts) ; do
    sed "$((2 + (((($i - 1)) * 26))))"','"$((1 + (($i * 26))))"'!d' allgcert > gcert${i}
  done
fi

# Parses out certificate issuer names for installation
echo -n | openssl s_client -showcerts -connect smtp.gmail.com:465 | grep i: | sed -e 's,.*=,,' > allgcertnames || failclean "Unable to output parsed names for certificates"

for i in $(seq 1 $numcerts) ; do
  certutil -A -n "$(sed -n ${i}p allgcertnames)" -t "TC,," -d $certdirectory -i gcert${i} || failclean "Unable to import certificates to database"
done

cleanup
2
  • 1
    As above this is the wrong thing to do, but if you want to do it one line of awk is sufficient: openssl s_client </dev/null -showcerts -connect ... | awk '/^ i:/{n=substr($0,7)} /-BEGIN/,/-END/{print>"t"} /-END/{close("t"); system("certutil -A -n \"" n "\" -t TC,, -i t -d certdir || echo failed; rm t")}' Aug 24, 2019 at 9:16
  • Ah I didn't see your comment before building that script. Thanks! Edit: after re-reading your one-liner, I don't see any practical difference between my script and that one. I'm assuming you've just given me basically the one-liner version of my script. Is there a recommended "right way" to do this that won't have the issue of permanent trust?
    – pyr0ball
    Aug 26, 2019 at 20:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .