Für die Mitspieler an den Schirmen zu Hause:
-------------8<---------------
#!/bin/bash
EX_UNAVAILABLE=69
export RANDFILE=/var/spool/exim4/.rnd
umask 077
MAILTMP=`mktemp /tmp/smime.XXXXXXXX`
trap "rm -f ${MAILTMP} ${MAILTMP}.header ${MAILTMP}.body ${MAILTMP}.signedbody ${MAILTMP}.signedbody-tr" 0 1 2 3 15
# STDIN in Datei schreiben
cat > "${MAILTMP}" || ( echo "Cannot save mail to file"; exit $EX_UNAVAILABLE;)
# Header extrahieren, leere Zeile am Ende entfernen
sed -e '/^$/ q' < "${MAILTMP}" | head -n -1 > "${MAILTMP}.header" || ( echo "Cannot save header to file"; exit $EX_UNAVAILABLE;)
# Body extrahieren
sed -e '1,/^$/ d' < "${MAILTMP}" > "${MAILTMP}.body" || ( echo "Cannot save body to file"; exit $EX_UNAVAILABLE;)
# Signieren
openssl smime -text -passin file:/etc/smime-signer/smimepass -sign -signer /etc/smime-signer/smime-signer.pem -in "${MAILTMP}.body" -out "${MAILTMP}.signedbody" 2>/dev/null || ( echo "Cannot sign mail"; exit $EX_UNAVAILABLE;)
# Überflüssige \r entfernen, die openssl hinzufügt, die später doppelt entfernt werden würden
# -> Signatur passt nicht mehr
tr -d '\r' < "${MAILTMP}.signedbody" > "${MAILTMP}.signedbody-tr"
# Heeader und signierten Body ausgeben
cat "${MAILTMP}.header" "${MAILTMP}.signedbody-tr"
rm -f "${MAILTMP}" "${MAILTMP}.header" "${MAILTMP}.body" "${MAILTMP}.signedbody" "${MAILTMP}.signedbody-tr"
-------------8<---------------
Das Verhalten von openssl, vor dem Signieren noch ein \r zuzufügen, hat
mir echt Kopfschmerzen bereitet.
Exim fügt dann nämlich vor dem Versenden an alle anderen Zeilen der Mail
noch ein \r hinzu, wie von SMTP-RFC gefordert, nur nicht bei den Zeilen,
die schon ein \r haben (das hat openssl ja schon gemacht).
Das Zielsystem entfernt dann alle \r zur Anzeige wieder und schon stimmt
die Signatur nicht mehr, da die \r im signierten Teil ja auch entfernt
wurden.
Das man den Pfad für RANDFILE für openssl hilfsweise angeben muss, ist
da noch die kleinere Sache.
Mit obigem Code bekomme ich auf meinem Test-System jetzt sauber
signierte Mails hin, wenn man das Ding einfach via transport_filter (und
"size_addition = -1" um die SIZE-Extension für den Transport zu
deaktivieren, da der Filter die Mail doch deutlich vergrößert) aufruft.
Sinnigerweise macht man einen speziellen Transport, der von einem
speziellen Router aufgerufen wird, der über entsprechende conditions
etc. prüft, ob die Mail überhaupt signiert werden soll.
Braucht man mehrere Signatur-Keys, so ist das obige Script natürlich
anzupassen, damit dies entweder als Parameter übergeben oder aus der
Mail geparst wird.
Grüße,
Sven.