From 900d8fcd44f9b4c10cea7f8d5af24d47acf9cc2e Mon Sep 17 00:00:00 2001 From: Rolf Schmidt Date: Thu, 13 Aug 2020 13:32:52 +0200 Subject: [PATCH] Fixes #3147 - S/MIME signing fails because of message encoding. --- lib/secure_mailing/smime/outgoing.rb | 20 ++++++++++++++++ spec/lib/secure_mailing/smime_spec.rb | 33 ++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/secure_mailing/smime/outgoing.rb b/lib/secure_mailing/smime/outgoing.rb index fa4bb650a..0535e8154 100644 --- a/lib/secure_mailing/smime/outgoing.rb +++ b/lib/secure_mailing/smime/outgoing.rb @@ -8,6 +8,8 @@ class SecureMailing::SMIME::Outgoing < SecureMailing::Backend::Handler def process return if !process? + @mail = workaround_mail_bit_encoding_issue(@mail) + if @security[:sign][:success] && @security[:encryption][:success] processed = encrypt(signed) log('sign', 'success') @@ -30,6 +32,24 @@ class SecureMailing::SMIME::Outgoing < SecureMailing::Backend::Handler @security[:sign][:success] || @security[:encryption][:success] end + # S/MIME signing fails because of message encoding #3147 + # workaround for https://github.com/mikel/mail/issues/1190 + def workaround_mail_bit_encoding_issue(mail) + + # change 7bit/8bit encoding to binary so that + # base64 will be used to encode the content + if mail.body.encoding.include?('bit') + mail.body.encoding = :binary + end + + # go into recursion for nested parts + mail.parts&.each do |part| + workaround_mail_bit_encoding_issue(part) + end + + mail + end + def overwrite_mail(processed) @mail.body = nil @mail.body = processed.body.encoded diff --git a/spec/lib/secure_mailing/smime_spec.rb b/spec/lib/secure_mailing/smime_spec.rb index 1f4933279..7ade245b4 100644 --- a/spec/lib/secure_mailing/smime_spec.rb +++ b/spec/lib/secure_mailing/smime_spec.rb @@ -17,12 +17,14 @@ RSpec.describe SecureMailing::SMIME do let(:ca_certificate_subject) { '/emailAddress=ca@example.com/C=DE/ST=Berlin/L=Berlin/O=Example Security/OU=IT Department/CN=example.com' } + let(:content_type) { 'text/plain' } + def build_mail Channel::EmailBuild.build( from: sender_email_address, to: recipient_email_address, body: raw_body, - content_type: 'text/plain', + content_type: content_type, security: security_preferences ) end @@ -92,6 +94,35 @@ RSpec.describe SecureMailing::SMIME do it_behaves_like 'HttpLog writer', 'failed' end + + context 'when message is 7bit or 8bit encoded' do + + let(:mail) do + smime_mail = build_mail + + mail = Channel::EmailParser.new.parse(smime_mail.to_s) + SecureMailing.incoming(mail) + + mail + end + + context 'when Content-Type is text/plain' do + let(:raw_body) { "\r\n\r\n@john.doe, now known as John Dóe has accepted your invitation to join the Administrator / htmltest project.\r\n\r\nhttp://169.254.169.254:3000/root/htmltest\r\n\r\n-- \r\nYou're receiving this email because of your account on 169.254.169.254.\r\n\r\n\r\n\r\n" } + + it 'verifies' do + expect(mail['x-zammad-article-preferences']['security']['sign']['success']).to be true + end + end + + context 'when Content-Type is text/html' do + let(:content_type) { 'text/html' } + let(:raw_body) { "
" } + + it 'verifies' do + expect(mail['x-zammad-article-preferences']['security']['sign']['success']).to be true + end + end + end end context 'no private key present' do