diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f72a22f..378a172f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). - `http_client`: Added support for multiple file in form data. Made clear what is the meaning of `upload_filename`, `upload_data` and `form_data`. - `authentication`: HTTP_AUTHORIZATION acceps now READABLE_STRING_GENERAL for username and password argument. - `http_client`: fixed curl implementation by setting `Content-Type` to `x-www-form-urlencoded` (if not set) when POST send data as `x-www-form-urlencoded`. +- `notification_email`: fixed the SMTP support for multiple recipients address. ### Security diff --git a/library/runtime/process/notification_email/smtp/notification_smtp_mailer.e b/library/runtime/process/notification_email/smtp/notification_smtp_mailer.e index 3400dcab..b2597cad 100644 --- a/library/runtime/process/notification_email/smtp/notification_smtp_mailer.e +++ b/library/runtime/process/notification_email/smtp/notification_smtp_mailer.e @@ -95,40 +95,67 @@ feature -- Basic operation l_email: EMAIL h: STRING i: INTEGER + lst: LIST [READABLE_STRING_8] do - create l_email.make_with_entry (a_email.from_address, addresses_to_header_line_value (a_email.to_addresses)) - if attached a_email.reply_to_address as l_reply_to then - l_email.add_header_entry ({EMAIL_CONSTANTS}.h_reply_to, l_reply_to) - end - - if attached a_email.cc_addresses as lst then - l_email.add_header_entry ({EMAIL_CONSTANTS}.h_cc, addresses_to_header_line_value (lst)) - end - if attached a_email.bcc_addresses as lst then - l_email.add_header_entry ({EMAIL_CONSTANTS}.h_bcc, addresses_to_header_line_value (lst)) - end - l_email.set_message (a_email.content) - l_email.add_header_entry ({EMAIL_CONSTANTS}.H_subject, a_email.subject) - - create h.make_empty - ;(create {HTTP_DATE}.make_from_date_time (a_email.date)).append_to_rfc1123_string (h) - l_email.add_header_entry ("Date", h) - - if attached a_email.additional_header_lines as lst then - across - lst as ic - loop - h := ic.item - i := h.index_of (':', 1) - if i > 0 then - l_email.add_header_entry (h.head (i - 1), h.substring (i + 1, h.count)) - else - check is_header_line: False end + lst := a_email.to_addresses + if lst.is_empty then + -- Error ... + else + -- With EMAIL, there should be a unique recipient at creation. + create l_email.make_with_entry (a_email.from_address, lst.first) + if lst.count > 1 then + from + lst.start + lst.forth + until + lst.off + loop + l_email.add_recipient_address (lst.item) + lst.forth end end - end + if attached a_email.reply_to_address as l_reply_to then + l_email.add_header_entry ({EMAIL_CONSTANTS}.h_reply_to, l_reply_to) + end - smtp_send_email (l_email) + if attached a_email.cc_addresses as l_cc_addresses then + across + l_cc_addresses as ic + loop + l_email.add_recipient_address_in_cc (ic.item) + end + end + if attached a_email.bcc_addresses as l_bcc_addresses then + across + l_bcc_addresses as ic + loop + l_email.add_recipient_address_in_bcc (ic.item) + end + end + l_email.set_message (a_email.content) + l_email.add_header_entry ({EMAIL_CONSTANTS}.H_subject, a_email.subject) + + create h.make_empty + ;(create {HTTP_DATE}.make_from_date_time (a_email.date)).append_to_rfc1123_string (h) + l_email.add_header_entry ("Date", h) + + if attached a_email.additional_header_lines as l_lines then + across + l_lines as ic + loop + h := ic.item + i := h.index_of (':', 1) + if i > 0 then + l_email.add_header_entry (h.head (i - 1), h.substring (i + 1, h.count)) + else + check is_header_line: False end + end + end + end + + smtp_send_email (l_email) + + end end feature {NONE} -- Implementation @@ -182,4 +209,3 @@ note Customer support http://support.eiffel.com ]" end - diff --git a/library/server/wsf/router/filter/wsf_xss_filter.e b/library/server/wsf/extension/filter/wsf_xss_filter.e similarity index 100% rename from library/server/wsf/router/filter/wsf_xss_filter.e rename to library/server/wsf/extension/filter/wsf_xss_filter.e diff --git a/library/server/wsf/src/support/wsf_xss_protection_patterns.e b/library/server/wsf/extension/support/wsf_protection_patterns.e similarity index 95% rename from library/server/wsf/src/support/wsf_xss_protection_patterns.e rename to library/server/wsf/extension/support/wsf_protection_patterns.e index 722633a1..43007497 100644 --- a/library/server/wsf/src/support/wsf_xss_protection_patterns.e +++ b/library/server/wsf/extension/support/wsf_protection_patterns.e @@ -1,6 +1,6 @@ note description: "[ - {WSF_XSS_PROTECTION_PATTERNS} + {WSF_PROTECTION_PATTERNS} Provide application security parterns to assist in Cross Site Scripting ]" date: "$Date$" @@ -9,7 +9,7 @@ note EIS: "name=Regular expression protection", "src=https://docs.apigee.com/api-services/reference/regular-expression-protection", "protocol=uri" expanded class - WSF_XSS_PROTECTION_PATTERNS + WSF_PROTECTION_PATTERNS feature -- xss PATTERNS diff --git a/library/server/wsf/src/support/wsf_xss_utilities.e b/library/server/wsf/extension/support/wsf_xss_utilities.e similarity index 56% rename from library/server/wsf/src/support/wsf_xss_utilities.e rename to library/server/wsf/extension/support/wsf_xss_utilities.e index ab51566b..4f3b868f 100644 --- a/library/server/wsf/src/support/wsf_xss_utilities.e +++ b/library/server/wsf/extension/support/wsf_xss_utilities.e @@ -1,20 +1,19 @@ note - description: "Return safe (XSS protection) data for WSF_REQUEST query and form paramters." + description: "Return safe (XSS protection) data for WSF_REQUEST query and form parameters." date: "$Date$" revision: "$Revision$" class WSF_XSS_UTILITIES - -- TODO add header protection. - + feature -- Query parameters safe_query_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Safe Query parameter for name `a_name'. local - l_wsf_xss: WSF_XSS_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTION_PATTERNS r: REGULAR_EXPRESSION do r := l_wsf_xss.XSS_regular_expression @@ -37,8 +36,9 @@ feature -- Form Parameters safe_form_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Safe Form parameter for name `a_name'. local - l_wsf_xss: WSF_XSS_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTION_PATTERNS r: REGULAR_EXPRESSION + not_first: BOOLEAN do r := l_wsf_xss.XSS_regular_expression Result := a_req.form_parameter (a_name) @@ -51,10 +51,50 @@ feature -- Form Parameters if r.has_matched then create {WSF_STRING} Result.make (str.name, " ") end + elseif + attached {WSF_MULTIPLE_STRING} Result as l_multi_str and then + r.is_compiled + then + across l_multi_str as ic loop + r.match (ic.item.value) + if r.has_matched then + if not_first and then attached {WSF_MULTIPLE_STRING} Result as l_result then + l_result.add_value ( (create {WSF_STRING}.make (ic.item.name, " "))) + else + create {WSF_MULTIPLE_STRING} Result.make_with_string (ic.item.name, " ") + not_first := True + end + end + end end + end end +feature -- Meta Variables + + safe_meta_variable (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_STRING + -- CGI Meta variable related to `a_name' + require + a_name_valid: a_name /= Void and then not a_name.is_empty + local + l_wsf_xss: WSF_PROTECTION_PATTERNS + r: REGULAR_EXPRESSION + do + r := l_wsf_xss.XSS_regular_expression + Result := a_req.meta_variable (a_name) + if Result /= Void then + if + attached {WSF_STRING} Result as str and then + r.is_compiled + then + r.match (str.value) + if r.has_matched then + create {WSF_STRING} Result.make (str.name, " ") + end + end + end + end note copyright: "2011-2017, Jocelyn Fiat, Javier Velilla, Olivier Ligot, Colin Adams, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" diff --git a/library/server/wsf/src/wsf_xss_request.e b/library/server/wsf/extension/wsf_xss_request.e similarity index 100% rename from library/server/wsf/src/wsf_xss_request.e rename to library/server/wsf/extension/wsf_xss_request.e diff --git a/library/server/wsf/tests/src/test_xss_patterns.e b/library/server/wsf/tests/src/test_xss_patterns.e index ea5456aa..e2a017c6 100644 --- a/library/server/wsf/tests/src/test_xss_patterns.e +++ b/library/server/wsf/tests/src/test_xss_patterns.e @@ -97,8 +97,8 @@ alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//-- r.match (s) assert ("No quotes and no semicolon", r.has_matched) end - - + + test_case_insensitive_xss_vector local r: REGULAR_EXPRESSION @@ -168,7 +168,7 @@ alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//-- r.match (s) assert ("Malformed A tags", r.has_matched) end - + test_malformed_img local @@ -196,7 +196,7 @@ alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//-- r.match (s) assert ("fromCharCode", r.has_matched) end - + test_default_src_tag local @@ -246,6 +246,6 @@ alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//-- feature {NONE} -- Implementation - xss_pattern: WSF_XSS_PROTECTION_PATTERNS + xss_pattern: WSF_PROTECTION_PATTERNS end diff --git a/library/server/wsf/tests/tests.ecf b/library/server/wsf/tests/tests.ecf index d4f4b4a1..8c752d43 100644 --- a/library/server/wsf/tests/tests.ecf +++ b/library/server/wsf/tests/tests.ecf @@ -1,5 +1,5 @@ - + @@ -28,6 +28,7 @@ + diff --git a/library/server/wsf/wsf.ecf b/library/server/wsf/wsf.ecf index 2576bc7b..c9c4ac34 100644 --- a/library/server/wsf/wsf.ecf +++ b/library/server/wsf/wsf.ecf @@ -1,5 +1,5 @@ - + @@ -18,7 +18,6 @@ - diff --git a/library/server/wsf/wsf_extension.ecf b/library/server/wsf/wsf_extension.ecf index 0cb1459e..7803d38f 100644 --- a/library/server/wsf/wsf_extension.ecf +++ b/library/server/wsf/wsf_extension.ecf @@ -14,6 +14,7 @@ +