diff --git a/library/server/wsf/security/support/wsf_protection.e b/library/server/wsf/security/support/wsf_protection.e new file mode 100644 index 00000000..49a2141a --- /dev/null +++ b/library/server/wsf/security/support/wsf_protection.e @@ -0,0 +1,76 @@ +note + description: "Summary description for {WSF_PROTECTION}." + author: "" + date: "$Date$" + revision: "$Revision$" + +deferred class + WSF_PROTECTION + +feature -- Status report + + is_valid: BOOLEAN + deferred + end + +feature -- String Protection + + string_8 (s: READABLE_STRING_8): detachable READABLE_STRING_8 + require + is_valid: is_valid + deferred + end + +feature -- Value Protection + + value (v: WSF_VALUE): detachable WSF_VALUE + require + is_valid: is_valid + do + if attached {WSF_STRING} v as s then + Result := string_value (s) + elseif attached {WSF_MULTIPLE_STRING} v as ms then + Result := multiple_string_value (ms) + else + -- TODO + Result := v + end + end + + string_value (v: WSF_STRING): detachable WSF_STRING + require + is_valid: is_valid + deferred + end + + multiple_string_value (mv: WSF_MULTIPLE_STRING): detachable WSF_MULTIPLE_STRING + require + is_valid: is_valid + local + v: detachable WSF_STRING + do + across + mv as ic + loop + v := string_value (ic.item) + if v = Void then + Result := Void + elseif Result = Void then + create Result.make_with_value (v) + else + Result.add_value (v) + 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)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/security/support/wsf_protection_policy.e b/library/server/wsf/security/support/wsf_protection_policy.e index 9a317260..1e24891e 100644 --- a/library/server/wsf/security/support/wsf_protection_policy.e +++ b/library/server/wsf/security/support/wsf_protection_policy.e @@ -10,7 +10,7 @@ class feature -- Query parameters - custom_query_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable WSF_VALUE + custom_query_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL; a_protections: ITERABLE [WSF_PROTECTION]): detachable WSF_VALUE -- Filtered Query parameter name `a_name' with custom protections. do Result := custom_wsf_value (a_req.query_parameter (a_name), a_protections) @@ -18,7 +18,7 @@ feature -- Query parameters predefined_query_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Filtered Query parameter name `a_name' with all predefined protections. - -- check {WSF_PROTECTION_PATTERNS} class. + -- check {WSF_PROTECTIONS} class. do Result := predefined_value (a_req.query_parameter (a_name)) end @@ -61,7 +61,7 @@ feature -- Query parameters feature -- Form Parameters - custom_form_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable WSF_VALUE + custom_form_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL; a_protections: ITERABLE [WSF_PROTECTION]): detachable WSF_VALUE -- Filtered Form parameter name `a_name' with custom protections. do Result := custom_wsf_value (a_req.form_parameter (a_name), a_protections) @@ -69,7 +69,7 @@ feature -- Form Parameters predefined_form_parameter (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Filtered Form parameter name `a_name' with all predefined protections. - -- check {WSF_PROTECTION_PATTERNS} class. + -- check {WSF_PROTECTIONS} class. do Result := predefined_value (a_req.form_parameter (a_name)) end @@ -112,7 +112,7 @@ feature -- Form Parameters feature -- Meta Variables - custom_meta_variable (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable WSF_VALUE + custom_meta_variable (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL; a_protections: ITERABLE [WSF_PROTECTION]): detachable WSF_VALUE -- Filtered CGI Meta variable name `a_name' with custom protections. require a_name_valid: a_name /= Void and then not a_name.is_empty @@ -124,7 +124,7 @@ feature -- Meta Variables predefined_meta_variable (a_req: WSF_REQUEST; a_name: READABLE_STRING_GENERAL): detachable WSF_VALUE -- Filtered CGI Meta variable name `a_name' with predefined protections. - -- check {WSF_PROTECTION_PATTERNS} class. + -- check {WSF_PROTECTIONS} class. require a_name_valid: a_name /= Void and then not a_name.is_empty do @@ -194,7 +194,7 @@ feature -- Meta Variables end feature -- HTTP_* - custom_http_accept (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_accept (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_accept header with custom protections `a_protections`. -- Contents of the Accept: header from the current wgi_request, if there is one. -- Example: 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' @@ -202,7 +202,7 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_accept, a_protections) end - custom_http_accept_charset (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_accept_charset (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_accept_charset header with custom protections `a_protections`. -- Contents of the Accept-Charset: header from the current wgi_request, if there is one. -- Example: 'iso-8859-1,*,utf-8'. @@ -211,7 +211,7 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_accept_charset, a_protections) end - custom_http_accept_encoding (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_accept_encoding (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_accept_encoding header with custom protections `a_protections`. -- Contents of the Accept-Encoding: header from the current wgi_request, if there is one. -- Example: 'gzip'. @@ -219,7 +219,7 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_accept_encoding, a_protections) end - custom_http_accept_language (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_accept_language (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_accept_language header with custom protections `a_protections`. -- Contents of the Accept-Language: header from the current wgi_request, if there is one. -- Example: 'en'. @@ -227,7 +227,7 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_accept_language, a_protections) end - custom_http_connection (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_connection (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_connection header with custom protections `a_protections`. -- Contents of the Connection: header from the current wgi_request, if there is one. -- Example: 'keep-alive'. @@ -235,7 +235,7 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_connection, a_protections) end - custom_http_expect (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_expect (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_expect header with custom protections `a_protections`. -- The Expect request-header field is used to indicate that particular server behaviors are required by the client. -- Example: '100-continue'. @@ -243,14 +243,14 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_expect, a_protections) end - custom_http_host (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_host (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_host header with custom protections `a_protections`. -- Contents of the Host: header from the current wgi_request, if there is one. do Result := custom_string_value (a_req.http_host, a_protections) end - custom_http_referer (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_referer (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_referer header with custom protections `a_protections`. -- The address of the page (if any) which referred the user agent to the current page. -- This is set by the user agent. @@ -260,7 +260,7 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_referer, a_protections) end - custom_http_user_agent (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_user_agent (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_user_agent header with custom protections `a_protections`. -- Contents of the User-Agent: header from the current wgi_request, if there is one. -- This is a string denoting the user agent being which is accessing the page. @@ -271,14 +271,14 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_user_agent, a_protections) end - custom_http_authorization (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_authorization (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_authorization header with custom protections `a_protections`. -- Contents of the Authorization: header from the current wgi_request, if there is one. do Result := custom_string_value (a_req.http_authorization, a_protections) end - custom_http_transfer_encoding (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_transfer_encoding (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_transfer_encoding header with custom protections `a_protections`. -- Transfer-Encoding -- for instance chunked. @@ -286,7 +286,7 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_transfer_encoding, a_protections) end - custom_http_access_control_request_headers (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_access_control_request_headers (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_access_control_request_headers header with custom protections `a_protections`. -- Indicates which headers will be used in the actual request -- as part of the preflight request @@ -294,63 +294,63 @@ feature -- HTTP_* Result := custom_string_value (a_req.http_access_control_request_headers, a_protections) end - custom_http_if_match (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_if_match (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_if_match header with custom protections `a_protections`. -- Existence check on resource. do Result := custom_string_value (a_req.http_if_match, a_protections) end - custom_http_if_modified_since (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_if_modified_since (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_if_modified_since header with custom protections `a_protections`. -- Modification check on resource. do Result := custom_string_value (a_req.http_if_modified_since, a_protections) end - custom_http_if_none_match (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_if_none_match (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_if_none_match header with custom protections `a_protections`. -- Existence check on resource. do Result := custom_string_value (a_req.http_if_none_match, a_protections) end - custom_http_if_range (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_if_range (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_if_range header with custom protections `a_protections`. -- Existence check on resource. do Result := custom_string_value (a_req.http_if_range, a_protections) end - custom_http_if_unmodified_since (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_if_unmodified_since (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_if_unmodified_since header with custom protections `a_protections`. -- Modification check on resource. do Result := custom_string_value (a_req.http_if_unmodified_since, a_protections) end - custom_http_last_modified (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_last_modified (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_last_modified header with custom protections `a_protections`. -- Modification check on resource. do Result := custom_string_value (a_req.http_last_modified, a_protections) end - custom_http_range (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_range (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_range header with custom protections `a_protections`. -- Requested byte-range of resource. do Result := custom_string_value (a_req.http_range, a_protections) end - custom_http_content_range (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_content_range (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_content_range header with custom protections `a_protections`. -- Partial range of selected representation enclosed in message payload. do Result := custom_string_value (a_req.http_content_range, a_protections) end - custom_http_content_encoding (a_req: WSF_REQUEST; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_http_content_encoding (a_req: WSF_REQUEST; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Filtered http_content_encoding header with custom protections `a_protections`. -- Encoding (usually compression) of message payload. do @@ -359,18 +359,14 @@ feature -- HTTP_* feature {NONE} -- Implementation - custom_wsf_value (a_value: detachable WSF_VALUE; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable WSF_VALUE + custom_wsf_value (a_value: detachable WSF_VALUE; a_protections: ITERABLE [WSF_PROTECTION]): detachable WSF_VALUE -- Return value `a_value` filtered by all protections policy. - local - l_wsf_xss: WSF_PROTECTION_PATTERNS do Result := filter_wsf_value (a_value, a_protections ) end - custom_string_value (a_value: detachable READABLE_STRING_8; a_protections: ARRAY [REGULAR_EXPRESSION]): detachable READABLE_STRING_8 + custom_string_value (a_value: detachable READABLE_STRING_8; a_protections: ITERABLE [WSF_PROTECTION]): detachable READABLE_STRING_8 -- Return value `a_value` filtered by all protections policy. - local - l_wsf_xss: WSF_PROTECTION_PATTERNS do Result := filter_string_value (a_value, a_protections ) end @@ -378,133 +374,109 @@ feature {NONE} -- Implementation predefined_value (a_value: detachable WSF_VALUE): detachable WSF_VALUE -- Return value `a_value` filtered by all predefined protections policy. local - l_wsf_xss: WSF_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTIONS do Result := filter_wsf_value (a_value, - {ARRAY [REGULAR_EXPRESSION]}<< - l_wsf_xss.XSS_regular_expression, - l_wsf_xss.server_side_expression, - l_wsf_xss.sql_injection_regular_expression, - l_wsf_xss.xpath_abbreviated_expression, - l_wsf_xss.xpath_expanded_expression>>) + << + l_wsf_xss.XSS, + l_wsf_xss.server_side, + l_wsf_xss.sql_injection, + l_wsf_xss.xpath_abbreviated, + l_wsf_xss.xpath_expanded + >>) end xss_value (a_value: detachable WSF_VALUE): detachable WSF_VALUE -- Return value `a_value` filtered by xss protection. local - l_wsf_xss: WSF_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTIONS do - Result := filter_wsf_value (a_value, {ARRAY [REGULAR_EXPRESSION]}<>) + Result := filter_wsf_value (a_value, <>) end xss_js_value (a_value: detachable WSF_VALUE): detachable WSF_VALUE -- Return value `a_value` filtered by xss-javascript protection. local - l_wsf_xss: WSF_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTIONS do - Result := filter_wsf_value (a_value, {ARRAY [REGULAR_EXPRESSION]} <>) + Result := filter_wsf_value (a_value, <>) end sql_value (a_value: detachable WSF_VALUE): detachable WSF_VALUE -- Return value `a_value` filtered by sql injection protection. local - l_wsf_xss: WSF_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTIONS do - Result := filter_wsf_value (a_value, {ARRAY [REGULAR_EXPRESSION]} <>) + Result := filter_wsf_value (a_value, <>) end server_side_value (a_value: detachable WSF_VALUE): detachable WSF_VALUE -- Return value `a_value` filtered by server side injection protection. local - l_wsf_xss: WSF_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTIONS do - Result := filter_wsf_value (a_value, {ARRAY [REGULAR_EXPRESSION]} <>) + Result := filter_wsf_value (a_value, <>) end xpath_abbreviated_value (a_value: detachable WSF_VALUE): detachable WSF_VALUE -- Return value `a_value` filtered by xpath_abbreviated injection protection. local - l_wsf_xss: WSF_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTIONS do - Result := filter_wsf_value (a_value, {ARRAY [REGULAR_EXPRESSION]} <>) + Result := filter_wsf_value (a_value, <>) end xpath_expanded_value (a_value: detachable WSF_VALUE): detachable WSF_VALUE -- Return value `a_value` filtered by Xpath expanded injection protection. local - l_wsf_xss: WSF_PROTECTION_PATTERNS + l_wsf_xss: WSF_PROTECTIONS do - Result := filter_wsf_value (a_value, {ARRAY [REGULAR_EXPRESSION]} <>) + Result := filter_wsf_value (a_value, <>) end - filter_wsf_value (a_value: detachable WSF_VALUE; a_regex: ARRAY [REGULAR_EXPRESSION] ): detachable WSF_VALUE - -- Filter value `a_value` with an array of protections policy `a_regex`. + filter_wsf_value (a_value: detachable WSF_VALUE; a_protections: ITERABLE [WSF_PROTECTION]): detachable WSF_VALUE + -- Filter value `a_value` with an array of protections policy `a_protections`. + require + a_protections_valid: across a_protections as ic all ic.item.is_valid end local - not_first: BOOLEAN + prot: WSF_PROTECTION do - Result := a_value - if Result /= Void then - if - attached {WSF_STRING} Result as str and then - a_regex.for_all (agent is_compiled) - then - a_regex.do_all (agent match (?, str.value)) - if a_regex.there_exists (agent has_matched) then - create {WSF_STRING} Result.make (str.name, " ") - end - elseif - attached {WSF_MULTIPLE_STRING} Result as l_multi_str and then - a_regex.for_all (agent is_compiled) - then - across l_multi_str as ic loop - a_regex.do_all (agent match (?, ic.item.value)) - if a_regex.there_exists (agent 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 + if a_value /= Void then + Result := a_value + across + a_protections as ic + until + Result = Void + loop + prot := ic.item + check is_valid: prot.is_valid end + Result := prot.value (Result) end end end - filter_string_value (a_value: detachable READABLE_STRING_8; a_regex: ARRAY [REGULAR_EXPRESSION] ): detachable READABLE_STRING_8 - -- Filter value `a_value` with an array of protections policy `a_regex`. + filter_string_value (a_value: detachable READABLE_STRING_8; a_protections: ITERABLE [WSF_PROTECTION] ): detachable READABLE_STRING_8 + -- Filter value `a_value` with an array of protections policy `a_protections`. + require + all_protections_valid: across a_protections as ic all ic.item.is_valid end + local + v: WSF_STRING + prot: WSF_PROTECTION do - Result := a_value - if Result /= Void then - if - attached a_value as l_value and then - a_regex.for_all (agent is_compiled) - then - a_regex.do_all (agent match (?, l_value)) - if a_regex.there_exists (agent has_matched) then - create {STRING_8} Result.make_empty - end + if a_value /= Void then + Result := a_value + across + a_protections as ic + until + Result = Void + loop + prot := ic.item + check is_valid: prot.is_valid end + Result := prot.string_8 (Result) end end end - is_compiled (a_regex: REGULAR_EXPRESSION): BOOLEAN - -- Is the regular expression 'a_regex' compiled? - do - Result := a_regex.is_compiled - end - - match (a_regex: REGULAR_EXPRESSION; a_value: READABLE_STRING_32) - do - a_regex.match (a_value) - end - - has_matched (a_regex: REGULAR_EXPRESSION): BOOLEAN - do - Result := a_regex.has_matched - 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/security/support/wsf_protection_regexp.e b/library/server/wsf/security/support/wsf_protection_regexp.e new file mode 100644 index 00000000..19abe5f6 --- /dev/null +++ b/library/server/wsf/security/support/wsf_protection_regexp.e @@ -0,0 +1,112 @@ +note + description: "Summary description for {WSF_PROTECTION_REGEXP}." + author: "" + date: "$Date$" + revision: "$Revision$" + +class + WSF_PROTECTION_REGEXP + +inherit + WSF_PROTECTION + +create + make, + make_caseless, + make_with_regexp + +convert + make_with_regexp ({REGULAR_EXPRESSION}) + +feature {NONE} -- Initialization + + make (a_regexp_pattern: READABLE_STRING_8; a_caseless: BOOLEAN) + local + r: REGULAR_EXPRESSION + do + create r + r.set_caseless (a_caseless) + r.compile (a_regexp_pattern) + make_with_regexp (r) + end + + make_caseless (a_regexp_pattern: READABLE_STRING_8) + do + make (a_regexp_pattern, True) + end + + make_with_regexp (a_regexp: REGULAR_EXPRESSION) + do + regexp := a_regexp + end + + +feature -- Access + + regexp: REGULAR_EXPRESSION + +feature -- String Protection + + string_8 (s: READABLE_STRING_8): detachable READABLE_STRING_8 + local + reg: like regexp + do + reg := regexp + reg.match (s) + if reg.has_matched then + Result := Void + else + Result := s + end + end + + string_value (v: WSF_STRING): detachable WSF_STRING + local + vs: READABLE_STRING_8 + do + vs := v.url_encoded_value + if attached string_8 (vs) as s then + if vs = s then + Result := v + else + create Result.make (v.name, s) + end + end + end + +feature -- Status report + + is_valid: BOOLEAN + do + Result := is_compiled + end + + is_compiled: BOOLEAN + do + Result := regexp.is_compiled + end + +feature {NONE} -- Implementation + + compiled_regexp (p: STRING; caseless: BOOLEAN): REGULAR_EXPRESSION + require + p /= Void + do + create Result + Result.set_caseless (caseless) + Result.compile (p) + ensure + is_compiled: Result.is_compiled + 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)" + source: "[ + Eiffel Software + 5949 Hollister Ave., Goleta, CA 93117 USA + Telephone 805-685-1006, Fax 805-685-6869 + Website http://www.eiffel.com + Customer support http://support.eiffel.com + ]" +end diff --git a/library/server/wsf/security/support/wsf_protection_patterns.e b/library/server/wsf/security/support/wsf_protections.e similarity index 65% rename from library/server/wsf/security/support/wsf_protection_patterns.e rename to library/server/wsf/security/support/wsf_protections.e index a41e3e74..a807ec7b 100644 --- a/library/server/wsf/security/support/wsf_protection_patterns.e +++ b/library/server/wsf/security/support/wsf_protections.e @@ -1,6 +1,6 @@ note description: "[ - {WSF_PROTECTION_PATTERNS} + {WSF_PROTECTIONS} Provide application security parterns to assist in Cross Site Scripting ]" date: "$Date$" @@ -9,75 +9,69 @@ note EIS: "name=Regular expression protection", "src=https://docs.apigee.com/api-services/reference/regular-expression-protection", "protocol=uri" expanded class - WSF_PROTECTION_PATTERNS + WSF_PROTECTIONS +feature -- XSS patterns -feature -- xss PATTERNS - - XSS_regular_expression: REGULAR_EXPRESSION + XSS: WSF_PROTECTION_REGEXP note EIS: "name= XSS", "src=https://community.apigee.com/questions/27198/xss-threat-protection-patterns.html#answer-27465", "protocol=uri" - local - p: STRING_32 once - p := "((\%%3C)|<)[^\n]+((\%%3E)|>)" - Result := compiled_regexp (p, True) + create Result.make_caseless ("((\%%3C)|<)[^\n]+((\%%3E)|>)") + ensure + is_compiled: Result.is_compiled end - XSS_javascript_expression: REGULAR_EXPRESSION + XSS_javascript: WSF_PROTECTION_REGEXP note EIS: "name=JavaScript Injection", "src=https://docs.apigee.com/api-services/reference/regular-expression-protection", "protocol=uri" - local - p: STRING_32 once - p := "<\s*script\b[^>]*>[^<]+<\s*/\s*script\s*>" - Result := compiled_regexp (p, True) + Result := compiled_regexp ("<\s*script\b[^>]*>[^<]+<\s*/\s*script\s*>", True) + ensure + is_compiled: Result.is_compiled end feature -- XPath injections Patterns - XPath_abbreviated_expression: REGULAR_EXPRESSION + XPath_abbreviated: WSF_PROTECTION_REGEXP note EIS: "name=XPath Abbreviated Syntax Injection", "src=https://docs.apigee.com/api-services/reference/regular-expression-protection", "protocol=uri" - local - p: STRING_32 once - p := "(/(@?[\w_?\w:\*]+(\[[^]]+\])*)?)+" - Result := compiled_regexp (p, True) + Result := compiled_regexp ("(/(@?[\w_?\w:\*]+(\[[^]]+\])*)?)+", True) + ensure + is_compiled: Result.is_compiled end - XPath_expanded_expression: REGULAR_EXPRESSION + XPath_expanded: WSF_PROTECTION_REGEXP note EIS: "name=XPath Expanded Syntax Injection", "src=https://docs.apigee.com/api-services/reference/regular-expression-protection", "protocol=uri" - local - p: STRING_32 once - p := "/?(ancestor(-or-self)?|descendant(-or-self)?|following(-sibling))" - Result := compiled_regexp (p, True) + Result := compiled_regexp ("/?(ancestor(-or-self)?|descendant(-or-self)?|following(-sibling))", True) + ensure + is_compiled: Result.is_compiled end feature -- Server side injection - Server_side_expression: REGULAR_EXPRESSION + Server_side: WSF_PROTECTION_REGEXP note EIS: "name=Server-Side Include Injection", "src=https://docs.apigee.com/api-services/reference/regular-expression-protection", "protocol=uri" - local - p: STRING_32 once - p := "