Skip to content

Commit

Permalink
Fixed issue #1390 - Broken email with huge pdf inline (lead to huge a…
Browse files Browse the repository at this point in the history
…rticle body with bigger then 7MB) is blocking rendering of web app.
  • Loading branch information
martini committed Sep 8, 2017
1 parent a4339bd commit bf36225
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 2 deletions.
20 changes: 18 additions & 2 deletions app/models/ticket/article.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ class Ticket::Article < ApplicationModel
belongs_to :created_by, class_name: 'User'
belongs_to :updated_by, class_name: 'User'
store :preferences
before_create :check_subject, :check_message_id_md5
before_update :check_subject, :check_message_id_md5
before_create :check_subject, :check_body, :check_message_id_md5
before_update :check_subject, :check_body, :check_message_id_md5

sanitized_html :body

Expand Down Expand Up @@ -284,6 +284,22 @@ def check_subject
true
end

# strip body length or raise exception
def check_body
return true if body.blank?
limit = 1_500_000
current_length = body.length
if body.length > limit
if ApplicationHandleInfo.current.present? && ApplicationHandleInfo.current.split('.')[1] == 'postmaster'
logger.warn "WARNING: cut string because of database length #{self.class}.body(#{limit} but is #{current_length})"
self.body = body[0, limit]
else
raise Exceptions::UnprocessableEntity, "body if article is to large, #{current_length} chars - only #{limit} allowed"
end
end
true
end

def history_log_attributes
{
related_o_id: self['ticket_id'],
Expand Down
103 changes: 103 additions & 0 deletions test/unit/ticket_article_dos_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# encoding: utf-8
require 'test_helper'

class TicketArticleDos < ActiveSupport::TestCase

test 'check body size' do

org_community = Organization.create_if_not_exists(
name: 'Zammad Foundation',
)
user_community = User.create_or_update(
login: 'article.dos@example.org',
firstname: 'Article',
lastname: 'Dos',
email: 'article.dos@example.org',
password: '',
active: true,
roles: [ Role.find_by(name: 'Customer') ],
organization_id: org_community.id,
updated_by_id: 1,
created_by_id: 1,
)

UserInfo.current_user_id = user_community.id
ApplicationHandleInfo.current = 'test.postmaster'

ticket1 = Ticket.create!(
group_id: Group.first.id,
customer_id: user_community.id,
title: 'DoS 1!',
updated_by_id: 1,
created_by_id: 1,
)
article1 = Ticket::Article.create!(
ticket_id: ticket1.id,
type_id: Ticket::Article::Type.find_by(name: 'phone').id,
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
from: 'Zammad Feedback <feedback@example.org>',
body: Array.new(2_000_000) { [*'0'..'9', *'a'..'z', ' ', ' ', ' ', '. '].sample }.join,
internal: false,
updated_by_id: 1,
created_by_id: 1,
)
assert_equal(1_500_000, article1.body.length)

ticket2 = Ticket.create!(
group_id: Group.first.id,
customer_id: user_community.id,
title: 'DoS 2!',
updated_by_id: 1,
created_by_id: 1,
)
article2 = Ticket::Article.create!(
ticket_id: ticket2.id,
type_id: Ticket::Article::Type.find_by(name: 'phone').id,
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
from: 'Zammad Feedback <feedback@example.org>',
body: "\u0000#{Array.new(2_000_000) { [*'0'..'9', *'a'..'z', ' ', ' ', ' ', '. '].sample }.join}",
internal: false,
updated_by_id: 1,
created_by_id: 1,
)
assert_equal(1_500_000, article2.body.length)

ApplicationHandleInfo.current = 'web'

ticket3 = Ticket.create!(
group_id: Group.first.id,
customer_id: user_community.id,
title: 'DoS 3!',
updated_by_id: 1,
created_by_id: 1,
)

assert_raises(Exceptions::UnprocessableEntity) {
article3 = Ticket::Article.create!(
ticket_id: ticket3.id,
type_id: Ticket::Article::Type.find_by(name: 'phone').id,
sender_id: Ticket::Article::Sender.find_by(name: 'Customer').id,
from: 'Zammad Feedback <feedback@example.org>',
body: "\u0000#{Array.new(2_000_000) { [*'0'..'9', *'a'..'z', ' ', ' ', ' ', '. '].sample }.join}",
internal: false,
updated_by_id: 1,
created_by_id: 1,
)
}

end

test 'check body size / cut if email' do

email_raw_string = "From: me@example.com
To: customer@example.com
Subject: some new subject
Some Text" + Array.new(2_000_000) { [*'0'..'9', *'a'..'z', ' ', ' ', ' ', '. '].sample }.join

ticket_p, article_p, user_p, mail = Channel::EmailParser.new.process({}, email_raw_string)
assert_equal(1_500_000, article_p.body.length)

end

end

0 comments on commit bf36225

Please sign in to comment.