
Why sign your email directly on the MTA (here we will talk about Postfix MTA) ? I don’t find a simple webmail client for my email server that include a S/MIME and/or PGP functionality to sign/encrypt outgoing messages.
So I found and change a little bit a script that get the outgoing message on the MTA and sign them with OpenSSL. The steps are:
– A running Postfix server
– Create the user account that will run the signing script and lock the account to prevent logging in:
useradd -M pfsigner
usermod -L pfsigner
– Create the folder /var/spool/signing. This folder will be used to store temporary message header and content
– chmod 700 /var/spool/signing
– chown pfsigner:pfsigner /var/spool/signing
– Edit your /etc/postfix/master.cf . We will add a new TCP port for the smtpd. This port will be used on your mail/webmail client SMTP configuration. Add these lines:
2525 inet n - - - - smtpd -o content_filter=sign:dummy sign unix - n n - 10 pipe flags=Rq user=pfsigner null_sender= argv=/usr/local/bin/sign.sh -f ${sender} -- ${recipient}
– request your certificate using the procedure here and export the certificate+private key to a pfx file
– convert your pfx file to pem (use your email name in the pem filename as shown below). If your email is youremail@yourdomain.com, use the following command:
openssl pkcs12 -in yourcert.pfx -out youremail@yourdomain.com.pem -nodes
– create the folder certs
mkdir -p /usr/local/src/smtp-signer/certs
– copy the certificate to the certs folder created above
– create the script file /usr/local/bin/sign.sh :
#!/bin/sh # SMTP Signer - POSIX Shell Implementation (using sed) USERNAME="pfsigner" SIGN_DIR="/var/spool/sign" CERT_DIR="/usr/local/src/smtp-signer/certs" SENDMAIL="/usr/sbin/sendmail -G -i" OPENSSL="/usr/bin/openssl" CERT_FILE="${CERT_DIR}/$2.pem" E_TEMPFAIL=75 cd ${SIGN_DIR} || { printf "${SIGN_DIR} does not exist" exit ${E_TEMPFAIL} } # TRAP DEFINITION # Number SIG Meaning # 0 0 On exit from shell # 1 SIGHUP Clean tidyup # 2 SIGINT Interrupt # 3 SIGQUIT Quit # 6 SIGABRT Abort # 9 SIGKILL Die Now (cannot be trap'ped) # 14 SIGALRM Alarm Clock # 15 SIGTERM Terminate trap "rm -f in.$$ body.$$ body2.$$ header1.$$ header2.$$ header.$$ signed.$$" 0 1 2 3 15 # Get the outgoing message : header and body cat >in.$$ # get the header and store it in the file header.$$ sed '/^$/q' <in.$$ >header1.$$ sed '$d' <header1.$$ >header.$$ # find the line that begin with Content-type in the header text CONTENT_TYPE=`sed -n '/Content-Type:/p' <header1.$$` printf "\n" >body.$$ sed '1,/^$/ d' <in.$$ >>body.$$ # You can uncomment the following both lines if you want to troubleshoot and see the content of the header and message body in the log file user.log # logger -f header.$$ # logger -f body.$$ # If a certificate exist and the email is not already signed, sign it with openssl if [[ -f "${CERT_FILE}" ]] && [[ $CONTENT_TYPE != *"signed"* ]]; then # Sign mail and relay MSG="Signed mail from $2" CONTENT_TYPE_BODY=`sed -n '/Content-Type/,+1p' header.$$` printf "${CONTENT_TYPE_BODY}\n" > body2.$$ cat body.$$ >>body2.$$ sed '/Content-Type/,+1 d' <header.$$ >header2.$$ # Sign the message body with OpenSSL ${OPENSSL} smime -sign -signer ${CERT_FILE} -in body2.$$ -out signed.$$ sed '/Content-Type/,+1 d' <header.$$ >header2.$$ # Concaetnante header and the signed message and send it using sendmail tool cat header2.$$ signed.$$ | ${SENDMAIL} "$@" else # Relay without signing MSG="Unsigned mail from $2 because message already signed" cat in.$$ | ${SENDMAIL} "$@" fi STATUS=$? if [ "${STATUS}" -eq 0 ]; then LOG_LEVEL="notice" else LOG_LEVEL="err" fi logger -p "mail.${LOG_LEVEL}" -t "sign.sh" "${MSG}" exit ${STATUS}
You can now configure your favorite email client and do not forget to specify port TCP 2525 for the SMTP settings to send your signed emails.
My Powershell script categories
- Active Directory
- Cluster
- Database
- Exchange
- Files and folders
- Hardware
- Network
- Operating System
- PKI
- SCCM
- Service and process
- Tips
- VMWare
Thanks for the excellent script.
Only bug I found: when you add a .JPG to the email (attached file), the signed message doesn’t validate anymore . For example, Outlook 2007 complains about “corrupted message”, or something like this.
regards, JS
Thank you for your comment. I will try to solve this issue. I will keep you informed.
Nico
I have tested successfully that case :
– I send message from webmail client (Rainloop) configured on my custom postfix. Image attached
– I receive successfully the message + attachment on outlook (version 2016 for me)
Probably a problem with the method you have chosen to send your message with attachment…
Hi Nicolas
(en fait, tu parles francais ? )
Merci d’avoir pris du temps pour ce problème. L’envoi des messages avec fichiers attachés fonctionne correctement, et je reçois aussi le message ainsi que le fichier joint, mais il y a un problème au niveau de la signature. Outlook 2007 m’indique que le message a été altéré, et donc le chiffrement ne correspond pas.
J’utilise ton script sur mon postfix personnel, webmail roundcube. La méthode d’attachement du fichier est standard.
Peut-etre que Outlook 2007 est bugué au niveau de la vérification de la signature, et que le bug a été résolu sous 2016 ? Ca me semble très improbable, car d’autres messages signés avec attachement sont correctement validés.
Il n’y a pas de probleme avec l’en-tete ? Je peux t’envoyer les fichiers temporaires (body, header, header1… ) qui sont créés, si besoin
Merci, Julien
Thanks for the excellent script.
Only bug I found: when you add a .JPG to the email (attached file), the signed message doesn’t validate anymore . For example, Outlook 2007 complains about “corrupted message”, or something like this.
regards, JS
Thank you for your comment. I will try to solve this issue. I will keep you informed.
Nico
I have tested successfully that case :
– I send message from webmail client (Rainloop) configured on my custom postfix. Image attached
– I receive successfully the message + attachment on outlook (version 2016 for me)
Probably a problem with the method you have chosen to send your message with attachment…
Hi Nicolas
(en fait, tu parles francais ? )
Merci d’avoir pris du temps pour ce problème. L’envoi des messages avec fichiers attachés fonctionne correctement, et je reçois aussi le message ainsi que le fichier joint, mais il y a un problème au niveau de la signature. Outlook 2007 m’indique que le message a été altéré, et donc le chiffrement ne correspond pas.
J’utilise ton script sur mon postfix personnel, webmail roundcube. La méthode d’attachement du fichier est standard.
Peut-etre que Outlook 2007 est bugué au niveau de la vérification de la signature, et que le bug a été résolu sous 2016 ? Ca me semble très improbable, car d’autres messages signés avec attachement sont correctement validés.
Il n’y a pas de probleme avec l’en-tete ? Je peux t’envoyer les fichiers temporaires (body, header, header1… ) qui sont créés, si besoin
Merci, Julien
Hi,
I can confirm that your script is working correctly with rainloop, but it’s not the case with roundcube.
Regards, Julien
Hello Julien,
Oui je parle bien francais
Thank you for your feedback… I don’t have a lot of time to test the script with Roundcube… but I will keep you informed when it will be done !
Nico
Hi,
I can confirm that your script is working correctly with rainloop, but it’s not the case with roundcube.
Regards, Julien
1) Your sign.sh has wrong SIGN_DIR? Is it /var/spool/signing?
2). Maybe private key and certificate should not combine together and with different file permissions:
PRIV_KEY_FILE=”${CERT_DIR}/$2-private-nopass.pem”
then
${OPENSSL} smime -sign -signer ${CERT_FILE} -inkey ${PRIV_KEY_FILE} -in body2.$$ -out signed.$$
1) Your sign.sh has wrong SIGN_DIR? Is it /var/spool/signing?
2). Maybe private key and certificate should not combine together and with different file permissions:
PRIV_KEY_FILE=”${CERT_DIR}/$2-private-nopass.pem”
then
${OPENSSL} smime -sign -signer ${CERT_FILE} -inkey ${PRIV_KEY_FILE} -in body2.$$ -out signed.$$