Posts tagged: security

Rails: Digitally sign outgoing emails (S/MIME)

In this article, I will introduce one method to digitally sign outgoing emails with S/MIME using Ruby on Rails.

require ‘openssl’ vs. Kernel.system openssl

At first, I tried to sign mails using the Ruby OpenSSL library which is basically a lightweight wrapper for libopenssl. However, I was not successful; I found out how to create PKCS7 signatures in general, but not especially for S/MIME mails.

So I decided to use the openssl command line tool that can be invoked like this:

openssl smime -sign -signer $CERT_FILE -passin pass:$CERT_PASS
  -in $UNSIGNED_MAIL -out $SIGNED_MAIL -certfile $CERT_CA_FILE
  -from 'your ' -to 'recipients <email@address>'
  -subject 'The Subject'

This command takes an unsigned MIME mail (located in a file whose path is stored in $UNSIGNED_MAIL), signs it with $CERT_FILE (protected by $CERT_PASS), attaches the Certification Authority’s certificate ($CERT_CA_FILE) and stores the resulting signed mail (which is in multipart/signed format) into $SIGNED_MAIL, setting the From:, To: and Subject: headers appropriately.

Invoking openssl from your mailer

To sign all emails that go out from your mailer (which is probably derived from ActionMailer::Base), you can use this code:

class Notifications < ActionMailer::Base
  CERT_DIR = ‘…’
  CERT_FILE = ‘cert.pem’
  CERT_PASS = ‘passphrase for cert.pem’
  CERT_CA_FILE = ‘your-ca.pem’

  #… your other mailer code …

  # overload deliver! to sign outgoing emails
  def deliver!
    unsigned = Tempfile.new ‘notification-unsigned’
    unsigned.write mail
    unsigned.close

    signed = Tempfile.new ‘notification-signed’
    signed.close

    Kernel.system ‘openssl’, ‘smime’, ‘-sign’, ‘-signer’, CERT_DIR+CERT_FILE, ‘-passin’, ‘pass:’+CERT_PASS,
      ‘-in’, unsigned.path, ‘-out’, signed.path, ‘-certfile’, CERT_DIR+CERT_CA_FILE,
      ‘-from’, ‘YOUR NAME <EMAIL@ADDRESS>’, ‘-to’, mail.to.join(’,’), ‘-subject’, mail.subject
    unsigned.close!

    mail.instance_variable_set ‘@smime_encoded’, File::read(signed.path)
    signed.unlink

    class << mail
      define_method :encoded do
        self.instance_variable_get ‘@smime_encoded’
      end
    end

    super mail
  end
end

This is a bit dirty because the first parameter for “deliver!” is normally a TMail::Mail object whose “encoded” method is called by the delivery method. In the code above, I have replaced the “mail” object (first parameter for “deliver!”) by a String with an attached “encoded” method that returns the string itself. However, it was the most simple working solution I could think of. Please tell me if you know a cleaner solution (re-parsing the signed email into a TMail::Mail object doesn’t work because it changes the signed mail by a few bytes and makes the signature invalid).

The above code assumes that both public (signature) and private key are stored in the $CERT_FILE. If this is not the case for you, you’d have to modify the command line slightly.

Typo3: still 30 % vulnerable to latest critical security hole

A quick scan of sites made with Typo3 told me that 99 of 330 pages are still vulnerable to the last Typo3 security bug that allows to read all .php files, including localconf.php (where the database password and other things ard stored) at the moment.

That means that about 30 % of all Typo3 pages show their database passwords (and other things) in clear text 5 days after the security bulletin has been sent out.

Image | WordPress Themes