From db825d379ad8e10e93065c7253439a8a7e8a6b38 Mon Sep 17 00:00:00 2001 From: Susan Hinrichs Date: Fri, 12 Oct 2018 18:54:08 +0000 Subject: [PATCH] Cleaning up TLS server verify options Split verify.server into policy and propoerties components. --- doc/admin-guide/files/records.config.en.rst | 254 ++++++++++-------- .../files/ssl_server_name.yaml.en.rst | 77 ++++-- doc/admin-guide/security/index.en.rst | 4 +- .../api/functions/TSVConnReenable.en.rst | 8 +- .../plugins/example-plugins/tls_bridge.en.rst | 2 +- iocore/net/I_NetVConnection.h | 13 +- iocore/net/P_SSLConfig.h | 4 +- iocore/net/P_SSLNetVConnection.h | 29 +- iocore/net/P_SSLSNI.h | 7 +- iocore/net/SSLClientUtils.cc | 99 ++++--- iocore/net/SSLConfig.cc | 91 ++++++- iocore/net/SSLNetVConnection.cc | 103 +++---- iocore/net/SSLSNIConfig.cc | 9 +- iocore/net/SSLUtils.cc | 2 +- iocore/net/YamlSNIConfig.cc | 48 +++- iocore/net/YamlSNIConfig.h | 28 +- mgmt/RecordsConfig.cc | 4 + src/traffic_server/InkAPI.cc | 2 +- tests/gold_tests/tls/ssl/signed-bar.key | 28 ++ tests/gold_tests/tls/ssl/signed-bar.pem | 19 ++ tests/gold_tests/tls/ssl/signed-foo.key | 28 ++ tests/gold_tests/tls/ssl/signed-foo.pem | 19 ++ tests/gold_tests/tls/ssl/signer.key | 15 ++ tests/gold_tests/tls/ssl/signer.pem | 32 +++ tests/gold_tests/tls/tls_verify.test.py | 137 ++++++++++ tests/gold_tests/tls/tls_verify2.test.py | 171 ++++++++++++ 26 files changed, 960 insertions(+), 273 deletions(-) create mode 100644 tests/gold_tests/tls/ssl/signed-bar.key create mode 100644 tests/gold_tests/tls/ssl/signed-bar.pem create mode 100644 tests/gold_tests/tls/ssl/signed-foo.key create mode 100644 tests/gold_tests/tls/ssl/signed-foo.pem create mode 100644 tests/gold_tests/tls/ssl/signer.key create mode 100644 tests/gold_tests/tls/ssl/signer.pem create mode 100644 tests/gold_tests/tls/tls_verify.test.py create mode 100644 tests/gold_tests/tls/tls_verify2.test.py diff --git a/doc/admin-guide/files/records.config.en.rst b/doc/admin-guide/files/records.config.en.rst index 60152eb8221..f85464b54f6 100644 --- a/doc/admin-guide/files/records.config.en.rst +++ b/doc/admin-guide/files/records.config.en.rst @@ -30,7 +30,7 @@ modify :file:`records.config`, run the command :option:`traffic_ctl config reloa to apply the changes. Note: The configuration directory, containing the ``SYSCONFDIR`` value specified at build time -relative to the installation prefix, contains Traffic Server configuration files. +relative to the installation prefix, contains |TS| configuration files. The ``$TS_ROOT`` environment variable can be used alter the installation prefix at run time. The directory must allow read/write access for configuration reloads. @@ -117,7 +117,7 @@ Examples In the following example, the variable `proxy.config.proxy_name`_ is a ``STRING`` datatype with the value ``my_server``. This means that the -name of the Traffic Server proxy is ``my_server``. :: +name of the |TS| proxy is ``my_server``. :: CONFIG proxy.config.proxy_name STRING my_server @@ -174,24 +174,24 @@ System Variables .. ts:cv:: CONFIG proxy.config.product_company STRING Apache Software Foundation - The name of the organization developing Traffic Server. + The name of the organization developing |TS|. .. ts:cv:: CONFIG proxy.config.product_vendor STRING Apache - The name of the vendor providing Traffic Server. + The name of the vendor providing |TS|. -.. ts:cv:: CONFIG proxy.config.product_name STRING Traffic Server +.. ts:cv:: CONFIG proxy.config.product_name STRING |TS| The name of the product. .. ts:cv:: CONFIG proxy.config.proxy_name STRING build_machine :reloadable: - The name of the Traffic Server node. + The name of the |TS| node. .. ts:cv:: CONFIG proxy.config.bin_path STRING bin - The location of the Traffic Server ``bin`` directory. + The location of the |TS| ``bin`` directory. .. ts:cv:: CONFIG proxy.config.proxy_binary STRING traffic_server @@ -199,7 +199,7 @@ System Variables .. ts:cv:: CONFIG proxy.config.proxy_binary_opts STRING -M - The command-line options for starting Traffic Server. + The command-line options for starting |TS|. .. ts:cv:: CONFIG proxy.config.manager_binary STRING traffic_manager @@ -219,8 +219,8 @@ System Variables .. ts:cv:: CONFIG proxy.config.output.logfile STRING traffic.out - The name and location of the file that contains warnings, status messages, and error messages produced by the Traffic Server - processes. If no path is specified, then Traffic Server creates the file in its logging directory. + The name and location of the file that contains warnings, status messages, and error messages produced by the |TS| + processes. If no path is specified, then |TS| creates the file in its logging directory. .. ts:cv:: CONFIG proxy.config.output.logfile_perm STRING rw-r--r-- @@ -264,7 +264,7 @@ System Variables :reloadable: :units: seconds - Specifies how often the output log is rolled, in seconds. The timer starts on Traffic Server bootup. + Specifies how often the output log is rolled, in seconds. The timer starts on |TS| bootup. .. ts:cv:: CONFIG proxy.config.output.logfile.rolling_size_mb INT 100 :reloadable: @@ -317,7 +317,7 @@ Thread Variables .. note:: - This option only has an affect when Traffic Server has been compiled with ``--enable-hwloc``. + This option only has an affect when |TS| has been compiled with ``--enable-hwloc``. .. ts:cv:: CONFIG proxy.config.system.file_max_pct FLOAT 0.9 @@ -367,7 +367,7 @@ Thread Variables The shutdown timeout(in seconds) to apply when stopping Traffic Server, in which ATS can initiate graceful shutdowns. It only supports - HTTP/2 graceful shutdown for now. Stopping Traffic Server here means sending + HTTP/2 graceful shutdown for now. Stopping |TS| here means sending `traffic_server` a signal either by `bin/trafficserver stop` or `kill`. .. ts:cv:: CONFIG proxy.config.thread.max_heartbeat_mseconds INT 60 @@ -398,7 +398,7 @@ Network :reloadable: The connection inactivity timeout (in seconds) to apply when - Traffic Server detects that no inactivity timeout has been applied + |TS| detects that no inactivity timeout has been applied by the HTTP state machine. When this timeout is applied, the `proxy.process.net.default_inactivity_timeout_applied` metric is incremented. @@ -571,7 +571,7 @@ Alarm Configuration .. ts:cv:: CONFIG proxy.config.alarm.script_runtime INT 5 :reloadable: - The number of seconds that Traffic Server allows the alarm script + The number of seconds that |TS| allows the alarm script to run before aborting it. HTTP Engine @@ -973,7 +973,7 @@ mptcp Control the re-use of an server session by a user agent (client) session. - If a user agent performs more than one HTTP transaction on its connection to Traffic Server a server session must be + If a user agent performs more than one HTTP transaction on its connection to |TS| a server session must be obtained for the second (and subsequent) transaction as for the first. This settings affects how that server session is selected. @@ -1109,7 +1109,7 @@ mptcp .. ts:cv:: CONFIG proxy.config.http.strict_uri_parsing INT 0 - Enables (``1``) or disables (``0``) Traffic Server to return a 400 Bad Request + Enables (``1``) or disables (``0``) |TS| to return a 400 Bad Request if client's request URI includes character which is not RFC 3986 compliant .. ts:cv:: CONFIG proxy.config.http.errors.log_error_pages INT 1 @@ -1139,14 +1139,14 @@ Parent Proxy Configuration :reloadable: :overridable: - The number of times the connection to the parent cache can fail before Traffic Server considers the parent unavailable. + The number of times the connection to the parent cache can fail before |TS| considers the parent unavailable. .. ts:cv:: CONFIG proxy.config.http.parent_proxy.total_connect_attempts INT 4 :reloadable: :overridable: The total number of connection attempts for a specific transaction allowed to - a parent cache before Traffic Server bypasses the parent or fails the request + a parent cache before |TS| bypasses the parent or fails the request (depending on the ``go_direct`` option in the :file:`parent.config` file). The number of parents tried is ``proxy.config.http.parent_proxy.fail_threshold / proxy.config.http.parent_proxy.total_connect_attempts`` @@ -1179,7 +1179,7 @@ Parent Proxy Configuration :reloadable: :overridable: - Configures Traffic Server to send proxy authentication headers on to the parent cache. + Configures |TS| to send proxy authentication headers on to the parent cache. .. ts:cv:: CONFIG proxy.config.http.no_dns_just_forward_to_parent INT 0 :reloadable: @@ -1210,7 +1210,7 @@ HTTP Connection Timeouts :reloadable: :overridable: - Specifies how long Traffic Server keeps connections to clients open for a + Specifies how long |TS| keeps connections to clients open for a subsequent request after a transaction ends. A value of ``0`` will disable the no activity timeout. @@ -1220,7 +1220,7 @@ HTTP Connection Timeouts :reloadable: :overridable: - Specifies how long Traffic Server keeps connections to origin servers open + Specifies how long |TS| keeps connections to origin servers open for a subsequent transfer of data after a transaction ends. A value of ``0`` will disable the no activity timeout. @@ -1230,7 +1230,7 @@ HTTP Connection Timeouts :reloadable: :overridable: - Specifies how long Traffic Server keeps connections to clients open if a + Specifies how long |TS| keeps connections to clients open if a transaction stalls. See :ref:`admin-performance-timeouts` for more discussion on |TS| timeouts. @@ -1239,7 +1239,7 @@ HTTP Connection Timeouts :reloadable: :overridable: - Specifies how long Traffic Server keeps connections to origin servers open if the transaction stalls. + Specifies how long |TS| keeps connections to origin servers open if the transaction stalls. See :ref:`admin-performance-timeouts` for more discussion on |TS| timeouts. @@ -1247,7 +1247,7 @@ HTTP Connection Timeouts :reloadable: :overridable: - Specifies how long Traffic Server keeps connections open if a websocket stalls. + Specifies how long |TS| keeps connections open if a websocket stalls. See :ref:`admin-performance-timeouts` for more discussion on |TS| timeouts. @@ -1255,7 +1255,7 @@ HTTP Connection Timeouts :reloadable: :overridable: - The maximum amount of time Traffic Server keeps websocket connections open. + The maximum amount of time |TS| keeps websocket connections open. See :ref:`admin-performance-timeouts` for more discussion on |TS| timeouts. @@ -1263,8 +1263,8 @@ HTTP Connection Timeouts :reloadable: :overridable: - The maximum amount of time Traffic Server can remain connected to a client. If the transfer to the client is not complete before this - timeout expires, then Traffic Server closes the connection. + The maximum amount of time |TS| can remain connected to a client. If the transfer to the client is not complete before this + timeout expires, then |TS| closes the connection. The value of ``0`` specifies that there is no timeout. @@ -1274,8 +1274,8 @@ HTTP Connection Timeouts :reloadable: :overridable: - The maximum amount of time Traffic Server waits for fulfillment of a connection request to an origin server. If Traffic Server does not - complete the transfer to the origin server before this timeout expires, then Traffic Server terminates the connection request. + The maximum amount of time |TS| waits for fulfillment of a connection request to an origin server. If |TS| does not + complete the transfer to the origin server before this timeout expires, then |TS| terminates the connection request. The default value of ``0`` specifies that there is no timeout. @@ -1284,7 +1284,7 @@ HTTP Connection Timeouts .. ts:cv:: CONFIG proxy.config.http.accept_no_activity_timeout INT 120 :reloadable: - The timeout interval in seconds before Traffic Server closes a connection that has no activity. + The timeout interval in seconds before |TS| closes a connection that has no activity. See :ref:`admin-performance-timeouts` for more discussion on |TS| timeouts. @@ -1292,7 +1292,7 @@ HTTP Connection Timeouts :reloadable: :overridable: - Specifies how long Traffic Server continues a background fill before giving up and dropping the origin server connection. + Specifies how long |TS| continues a background fill before giving up and dropping the origin server connection. See :ref:`admin-performance-timeouts` for more discussion on |TS| timeouts. @@ -1396,7 +1396,7 @@ Origin Server Connect Attempts :reloadable: :overridable: - The maximum number of connection retries Traffic Server can make when the origin server is not responding. + The maximum number of connection retries |TS| can make when the origin server is not responding. Each retry attempt lasts for `proxy.config.http.connect_attempts_timeout`_ seconds. Once the maximum number of retries is reached, the origin is marked dead. After this, the setting `proxy.config.http.connect_attempts_max_retries_dead_server`_ is used to limit the number of retry attempts to the known dead origin. @@ -1405,7 +1405,7 @@ Origin Server Connect Attempts :reloadable: :overridable: - Maximum number of connection retries Traffic Server can make while an origin is marked dead. Typically this value is smaller than + Maximum number of connection retries |TS| can make while an origin is marked dead. Typically this value is smaller than `proxy.config.http.connect_attempts_max_retries`_ so an error is returned to the client faster and also to reduce the load on the dead origin. The timeout interval `proxy.config.http.connect_attempts_timeout`_ in seconds is used with this setting. @@ -1532,20 +1532,20 @@ Origin Server Connect Attempts :reloadable: :overridable: - Specifies how long (in seconds) Traffic Server remembers that an origin server was unreachable. + Specifies how long (in seconds) |TS| remembers that an origin server was unreachable. .. ts:cv:: CONFIG proxy.config.http.down_server.abort_threshold INT 10 :reloadable: :overridable: - The number of seconds before Traffic Server marks an origin server as unavailable after a client abandons a request + The number of seconds before |TS| marks an origin server as unavailable after a client abandons a request because the origin server was too slow in sending the response header. .. ts:cv:: CONFIG proxy.config.http.uncacheable_requests_bypass_parent INT 1 :reloadable: :overridable: - When enabled (1), Traffic Server bypasses the parent proxy for a request that is not cacheable. + When enabled (1), |TS| bypasses the parent proxy for a request that is not cacheable. Congestion Control ================== @@ -1572,7 +1572,7 @@ Congestion Control .. ts:cv:: CONFIG proxy.config.http.websocket.max_number_of_connections INT -1 :reloadable: - When enabled >= (``0``), Traffic Server will enforce a maximum number of simultaneous websocket connections. + When enabled >= (``0``), |TS| will enforce a maximum number of simultaneous websocket connections. .. _admin-negative-response-caching: @@ -1590,7 +1590,7 @@ Negative Response Caching When disabled (``0``), |TS| will only cache the response if the response has ``Cache-Control`` headers. - The following negative responses are cached by Traffic Server by default: + The following negative responses are cached by |TS| by default: ====================== ===================================================== HTTP Response Code Description @@ -1616,7 +1616,7 @@ Negative Response Caching :reloadable: :overridable: - How long (in seconds) Traffic Server keeps the negative responses valid in cache. This value only affects negative + How long (in seconds) |TS| keeps the negative responses valid in cache. This value only affects negative responses that do NOT have explicit ``Expires:`` or ``Cache-Control:`` lifetimes set by the server. .. ts:cv:: CONFIG proxy.config.http.negative_caching_list STRING 204 305 403 404 405 414 500 501 502 503 504 @@ -1649,36 +1649,36 @@ Proxy User Variables :reloadable: :overridable: - When enabled (``1``), Traffic Server removes the ``From`` header to protect the privacy of your users. + When enabled (``1``), |TS| removes the ``From`` header to protect the privacy of your users. .. ts:cv:: CONFIG proxy.config.http.anonymize_remove_referer INT 0 :reloadable: - When enabled (``1``), Traffic Server removes the ``Referrer`` header to protect the privacy of your site and users. + When enabled (``1``), |TS| removes the ``Referrer`` header to protect the privacy of your site and users. .. ts:cv:: CONFIG proxy.config.http.anonymize_remove_user_agent INT 0 :reloadable: :overridable: - When enabled (``1``), Traffic Server removes the ``User-agent`` header to protect the privacy of your site and users. + When enabled (``1``), |TS| removes the ``User-agent`` header to protect the privacy of your site and users. .. ts:cv:: CONFIG proxy.config.http.anonymize_remove_cookie INT 0 :reloadable: :overridable: - When enabled (``1``), Traffic Server removes the ``Cookie`` header to protect the privacy of your site and users. + When enabled (``1``), |TS| removes the ``Cookie`` header to protect the privacy of your site and users. .. ts:cv:: CONFIG proxy.config.http.anonymize_remove_client_ip INT 0 :reloadable: :overridable: - When enabled (``1``), Traffic Server removes ``Client-IP`` headers for more privacy. + When enabled (``1``), |TS| removes ``Client-IP`` headers for more privacy. .. ts:cv:: CONFIG proxy.config.http.insert_client_ip INT 1 :reloadable: :overridable: - Specifies whether Traffic Server inserts ``Client-IP`` headers to retain the client IP address: + Specifies whether |TS| inserts ``Client-IP`` headers to retain the client IP address: ===== ====================================================================== Value Description @@ -1691,19 +1691,19 @@ Proxy User Variables .. ts:cv:: CONFIG proxy.config.http.anonymize_other_header_list STRING NULL :reloadable: - Comma separated list of headers Traffic Server should remove from outgoing requests. + Comma separated list of headers |TS| should remove from outgoing requests. .. ts:cv:: CONFIG proxy.config.http.insert_squid_x_forwarded_for INT 1 :reloadable: :overridable: - When enabled (``1``), Traffic Server adds the client IP address to the ``X-Forwarded-For`` header. + When enabled (``1``), |TS| adds the client IP address to the ``X-Forwarded-For`` header. .. ts:cv:: CONFIG proxy.config.http.insert_forwarded STRING none :reloadable: :overridable: - The default value (``none``) means that Traffic Server does not insert or append information to any + The default value (``none``) means that |TS| does not insert or append information to any ``Forwarded`` header (described in IETF RFC 7239) in the request message. To put information into a ``Forwarded`` header in the request, the value of this variable must be a list of the ``Forwarded`` parameters to be inserted. @@ -1725,7 +1725,7 @@ Proxy User Variables Each paramater in the list must be separated by ``|`` or ``:``. For example, ``for|by=uuid|proto`` is a valid value for this variable. Note that the ``connection`` parameter is a non-standard extension to - RFC 7239. Also note that, while Traffic Server allows multiple ``by`` parameters for the same proxy, this + RFC 7239. Also note that, while |TS| allows multiple ``by`` parameters for the same proxy, this is prohibited by RFC 7239. Currently, for the ``host`` parameter to provide the original host from the incoming client request, `proxy.config.url_remap.pristine_host_hdr`_ must be enabled. @@ -1844,7 +1844,7 @@ Cache Control reformatting or repartitioning. To be safe in Linux, you could just use the entire drive: ``/dev/sdb`` instead of ``/dev/sdb1`` and - Traffic Server will do the right thing. Misaligned partitions on Linux are auto-detected. + |TS| will do the right thing. Misaligned partitions on Linux are auto-detected. For example: If ``/sys/block/sda/sda1/alignment_offset`` is non-zero, ATS will offset reads/writes to that disk by that alignment. If Linux knows about any existing partition misalignments, ATS will compensate. @@ -1907,19 +1907,19 @@ Cache Control :reloadable: :overridable: - When enabled (``1``), Traffic Server ignores client requests to bypass the cache. + When enabled (``1``), |TS| ignores client requests to bypass the cache. .. ts:cv:: CONFIG proxy.config.http.cache.ims_on_client_no_cache INT 1 :reloadable: :overridable: - When enabled (``1``), Traffic Server issues a conditional request to the origin server if an incoming request has a ``No-Cache`` header. + When enabled (``1``), |TS| issues a conditional request to the origin server if an incoming request has a ``No-Cache`` header. .. ts:cv:: CONFIG proxy.config.http.cache.ignore_server_no_cache INT 0 :reloadable: :overridable: - When enabled (``1``), Traffic Server ignores origin server requests to bypass the cache. + When enabled (``1``), |TS| ignores origin server requests to bypass the cache. .. ts:cv:: CONFIG proxy.config.http.cache.cache_responses_to_cookies INT 1 :reloadable: @@ -1941,7 +1941,7 @@ Cache Control .. ts:cv:: CONFIG proxy.config.http.cache.ignore_authentication INT 0 :overridable: - When enabled (``1``), Traffic Server ignores ``WWW-Authentication`` headers in responses ``WWW-Authentication`` headers are removed and + When enabled (``1``), |TS| ignores ``WWW-Authentication`` headers in responses ``WWW-Authentication`` headers are removed and not cached. .. ts:cv:: CONFIG proxy.config.http.cache.cache_urls_that_look_dynamic INT 1 @@ -2004,12 +2004,12 @@ Cache Control .. ts:cv:: CONFIG proxy.config.http.cache.range.lookup INT 1 :overridable: - When enabled (``1``), Traffic Server looks up range requests in the cache. + When enabled (``1``), |TS| looks up range requests in the cache. .. ts:cv:: CONFIG proxy.config.http.cache.range.write INT 0 :overridable: - When enabled (``1``), Traffic Server will attempt to write (lock) the URL + When enabled (``1``), |TS| will attempt to write (lock) the URL to cache. This is rarely useful (at the moment), since it'll only be able to write to cache if the origin has ignored the ``Range:`` header. For a use case where you know the origin will respond with a full (``200``) response, @@ -2019,7 +2019,7 @@ Cache Control :reloadable: :overridable: - When enabled with a value of ``1``, Traffic Server serves documents from cache with a + When enabled with a value of ``1``, |TS| serves documents from cache with a ``Content-Type:`` header even if it does not match the ``Accept:`` header of the request. If set to ``2`` (default), this logic only happens in the absence of a ``Vary`` header in the cached response (which is the recommended and safe use). @@ -2036,7 +2036,7 @@ Cache Control :reloadable: :overridable: - When enabled with a value of ``1``, Traffic Server serves documents from cache with a + When enabled with a value of ``1``, |TS| serves documents from cache with a ``Content-Language:`` header even if it does not match the ``Accept-Language:`` header of the request. If set to ``2`` (default), this logic only happens in the absence of a ``Vary`` header in the cached response (which is the recommended and safe use). @@ -2053,7 +2053,7 @@ Cache Control :reloadable: :overridable: - When enabled with a value of ``1``, Traffic Server serves documents from cache with a + When enabled with a value of ``1``, |TS| serves documents from cache with a ``Content-Encoding:`` header even if it does not match the ``Accept-Encoding:`` header of the request. If set to ``2`` (default), this logic only happens in the absence of a ``Vary`` header in the cached response (which is the recommended and safe use). @@ -2070,7 +2070,7 @@ Cache Control :reloadable: :overridable: - When enabled with a value of ``1``, Traffic Server serves documents from cache with a + When enabled with a value of ``1``, |TS| serves documents from cache with a ``Content-Type:`` header even if it does not match the ``Accept-Charset:`` header of the request. If set to ``2`` (default), this logic only happens in the absence of a ``Vary`` header in the cached response (which is the recommended and safe use). @@ -2087,7 +2087,7 @@ Cache Control :reloadable: :overridable: - When enabled (``1``), Traffic Server ignores any ``Cache-Control: + When enabled (``1``), |TS| ignores any ``Cache-Control: max-age`` headers from the client. This technically violates the HTTP RFC, but avoids a problem where a client can forcefully invalidate a cached object. @@ -2104,7 +2104,7 @@ Cache Control .. ts:cv:: CONFIG proxy.config.cache.permit.pinning INT 0 :reloadable: - When enabled (``1``), Traffic Server will keep certain HTTP objects in the cache for a certain time as specified in cache.config. + When enabled (``1``), |TS| will keep certain HTTP objects in the cache for a certain time as specified in cache.config. .. ts:cv:: CONFIG proxy.config.cache.hit_evacuate_percent INT 0 @@ -2250,7 +2250,7 @@ Heuristic Expiration .. note:: - Previous versions of Apache Traffic Server defaulted this to 240s. This + Previous versions of Apache |TS| defaulted this to 240s. This feature is deprecated as of ATS v6.2.0. .. ts:cv:: CONFIG proxy.config.http.cache.fuzz.probability FLOAT 0.0 @@ -2263,7 +2263,7 @@ Heuristic Expiration .. note:: - Previous versions of Apache Traffic Server defaulted this to 0.005 (0.5%). + Previous versions of Apache |TS| defaulted this to 0.005 (0.5%). This feature is deprecated as of ATS v6.2.0 .. ts:cv:: CONFIG proxy.config.http.cache.fuzz.min_time INT 0 @@ -2296,22 +2296,22 @@ Dynamic Content & Content Negotiation :reloadable: :overridable: - The header on which Traffic Server varies for text documents. + The header on which |TS| varies for text documents. -For example: if you specify ``User-agent``, then Traffic Server caches +For example: if you specify ``User-agent``, then |TS| caches all the different user-agent versions of documents it encounters. .. ts:cv:: CONFIG proxy.config.http.cache.vary_default_images STRING NULL :reloadable: :overridable: - The header on which Traffic Server varies for images. + The header on which |TS| varies for images. .. ts:cv:: CONFIG proxy.config.http.cache.vary_default_other STRING NULL :reloadable: :overridable: - The header on which Traffic Server varies for anything other than text and images. + The header on which |TS| varies for anything other than text and images. .. ts:cv:: CONFIG proxy.config.http.cache.open_read_retry_time INT 10 :reloadable: @@ -2372,13 +2372,13 @@ Customizable User Response Pages .. ts:cv:: CONFIG proxy.config.body_factory.enable_logging INT 0 - Enables (``1``) or disables (``0``) logging for customizable response pages. When enabled, Traffic Server records a message in + Enables (``1``) or disables (``0``) logging for customizable response pages. When enabled, |TS| records a message in the error log each time a customized response page is used or modified. .. ts:cv:: CONFIG proxy.config.body_factory.template_sets_dir STRING etc/trafficserver/body_factory The customizable response page default directory. If this is a - relative path, Traffic Server resolves it relative to the + relative path, |TS| resolves it relative to the ``PREFIX`` directory. .. ts:cv:: CONFIG proxy.config.body_factory.template_base STRING "" @@ -2396,7 +2396,7 @@ Customizable User Response Pages .. ts:cv:: CONFIG proxy.config.body_factory.response_suppression_mode INT 0 - Specifies when Traffic Server suppresses generated response pages: + Specifies when |TS| suppresses generated response pages: ===== ====================================================================== Value Description @@ -2472,7 +2472,7 @@ DNS .. ts:cv:: CONFIG proxy.config.dns.splitDNS.enabled INT 0 :reloadable: - Enables (``1``) or disables (``0``) DNS server selection. When enabled, Traffic Server refers to the :file:`splitdns.config` file for + Enables (``1``) or disables (``0``) DNS server selection. When enabled, |TS| refers to the :file:`splitdns.config` file for the selection specification. Refer to :ref:`Configuring DNS Server Selection `. .. ts:cv:: CONFIG proxy.config.dns.resolv_conf STRING /etc/resolv.conf @@ -2802,7 +2802,7 @@ Logging Configuration .. ts:cv:: CONFIG proxy.config.log.hostname STRING localhost :reloadable: - The hostname of the machine running Traffic Server. + The hostname of the machine running |TS|. .. ts:cv:: CONFIG proxy.config.log.logfile_dir STRING var/log/trafficserver :reloadable: @@ -2883,7 +2883,7 @@ Logging Configuration :reloadable: :deprecated: - When enabled (``1``), configures Traffic Server to include the hostname of the collation client that generated the log entry in each entry. + When enabled (``1``), configures |TS| to include the hostname of the collation client that generated the log entry in each entry. .. ts:cv:: CONFIG proxy.config.log.collation_retry_sec INT 5 :reloadable: @@ -2937,7 +2937,7 @@ Logging Configuration The log file rolling interval, in seconds. The minimum value is ``60`` (1 minute). The maximum, and default, value is 86400 seconds (one day). -.. note:: If you start Traffic Server within a few minutes of the next rolling time, then rolling might not occur until the next rolling time. +.. note:: If you start |TS| within a few minutes of the next rolling time, then rolling might not occur until the next rolling time. .. ts:cv:: CONFIG proxy.config.log.rolling_offset_hr INT 0 :reloadable: @@ -2974,7 +2974,7 @@ Logging Configuration :reloadable: :units: seconds - How often Traffic Server executes log related periodic tasks, in seconds + How often |TS| executes log related periodic tasks, in seconds .. ts:cv:: CONFIG proxy.config.http.slow.log.threshold INT 0 :reloadable: @@ -3104,7 +3104,7 @@ Diagnostic Logging Configuration :reloadable: :units: seconds - Specifies how often the diagnostics log is rolled, in seconds. The timer starts on Traffic Server bootup. + Specifies how often the diagnostics log is rolled, in seconds. The timer starts on |TS| bootup. .. ts:cv:: CONFIG proxy.config.diags.logfile.rolling_size_mb INT 100 :reloadable: @@ -3136,7 +3136,7 @@ URL Remap Rules .. ts:cv:: CONFIG proxy.config.url_remap.remap_required INT 1 :reloadable: - Set this variable to ``1`` if you want Traffic Server to serve + Set this variable to ``1`` if you want |TS| to serve requests only from origin servers listed in the mapping rules of the :file:`remap.config` file. If a request does not match, then the browser will receive an error. @@ -3268,7 +3268,7 @@ SSL Termination The location of the SSL certificates and chains used for accepting and validation new SSL sessions. If this is a relative path, - it is appended to the Traffic Server installation PREFIX. All + it is appended to the |TS| installation PREFIX. All certificates and certificate chains listed in :file:`ssl_multicert.config` will be loaded relative to this path. @@ -3354,7 +3354,7 @@ SSL Termination This configuration specifies the lifetime of SSL session cache entries in seconds. If it is ``0``, then the SSL library will use a default value, typically 300 seconds. Note: This option has no affect - when using the Traffic Server session cache (option ``2`` in + when using the |TS| session cache (option ``2`` in ``proxy.config.ssl.session_cache``) See :ref:`admin-performance-timeouts` for more discussion on |TS| timeouts. @@ -3372,12 +3372,12 @@ SSL Termination .. ts:cv:: CONFIG proxy.config.ssl.session_cache.num_buckets INT 256 This configuration specifies the number of buckets to use with the - Traffic Server SSL session cache implementation. The TS implementation + |TS| SSL session cache implementation. The TS implementation is a fixed size hash map where each bucket is protected by a mutex. .. ts:cv:: CONFIG proxy.config.ssl.session_cache.skip_cache_on_bucket_contention INT 0 - This configuration specifies the behavior of the Traffic Server SSL session + This configuration specifies the behavior of the |TS| SSL session cache implementation during lock contention on each bucket: ===== ====================================================================== @@ -3417,7 +3417,7 @@ SSL Termination certificate files' access rights can be restricted to help reduce the vulnerability of certificates. - This feature requires Traffic Server to be built with POSIX + This feature requires |TS| to be built with POSIX capabilities enabled. .. ts:cv:: CONFIG proxy.config.ssl.handshake_timeout_in INT 0 @@ -3449,23 +3449,57 @@ SSL Termination Client-Related Configuration ---------------------------- +.. ts:cv:: CONFIG proxy.config.ssl.client.verify.server.policy STRING DISABLED + :reloadable: + + Configures |TS| to verify the origin server certificate + with the Certificate Authority (CA). This configuration takes a value of :code:`DISABLED`, :code:`PERMISSIVE`, or :code:`ENFORCED` + + You can override this global setting on a per domain basis in the ssl_servername.yaml file using the :ref:`verify_server_policy attribute`. + +:code:`DISABLED` + Server Certificate will not be verified +:code:`PERMISSIVE` + Certificate will be verified and the connection will not be established if verification fails. +:code:`ENFORCED` + The provided certificate will be verified and the connection will be established irrespective of the verification result. If verification fails the name of the server will be logged. + +.. ts:cv:: CONFIG proxy.config.ssl.client.verify.server.properties STRING ALL + :reloadable: + + Configures |TS| for what the default verify callback should check during origin server verification. + + You can override this global setting on a per domain basis in the ssl_servername.yaml file using the :ref:`verify_server_properties attribute`. + +:code:`NONE` + Check nothing in the standard callback. Rely entirely on plugins to check the certificate. +:code:`SIGNATURE` + Check only for a valid signature. +:code:`NAME` + Check only that the SNI name is in the certificate. +:code:`ALL` + Check both the signature and the name. + .. ts:cv:: CONFIG proxy.config.ssl.client.verify.server INT 0 :reloadable: + :deprecated: + + This setting has been deprecated and :ts:cv:`proxy.config.ssl.client.verify.server.policy` and + :ts:cv:`proxy.config.ssl.client.verify.server.properties` should be used instead. - Configures Traffic Server to verify the origin server certificate + Configures |TS| to verify the origin server certificate with the Certificate Authority (CA). This configuration takes a value between 0 to 2. You can override this global setting on a per domain basis in the ssl_servername.yaml file using the :ref:`verify_origin_server attribute`. -:0: Server Certificate will not be verified -:1: Certificate will be verified and the connection will not be established if verification fails. -:2: The provided certificate will be verified and the connection will be established irrespective of the verification result. If verification fails the name of the server will be logged. - + :0: Server Certificate will not be verified + :1: Certificate will be verified and the connection will not be established if verification fail + :2: The provided certificate will be verified and the connection will be established .. ts:cv:: CONFIG proxy.config.ssl.client.cert.filename STRING NULL :overridable: - The filename of SSL client certificate installed on Traffic Server. + The filename of SSL client certificate installed on |TS|. .. ts:cv:: CONFIG proxy.config.ssl.client.cert.path STRING /config @@ -3474,13 +3508,13 @@ Client-Related Configuration .. ts:cv:: CONFIG proxy.config.ssl.client.private_key.filename STRING NULL - The filename of the Traffic Server private key. Change this variable - only if the private key is not located in the Traffic Server SSL + The filename of the |TS| private key. Change this variable + only if the private key is not located in the |TS| SSL client certificate file. .. ts:cv:: CONFIG proxy.config.ssl.client.private_key.path STRING NULL - The location of the Traffic Server private key. Change this variable + The location of the |TS| private key. Change this variable only if the private key is not located in the SSL client certificate file. @@ -3608,7 +3642,7 @@ HTTP/2 Configuration This advisory setting informs a peer of the maximum size of header list that the sender is prepared to accept blocks. The default value, which is - the unsigned int maximum value in Traffic Server, implies unlimited size. + the unsigned int maximum value in |TS|, implies unlimited size. .. ts:cv:: CONFIG proxy.config.http2.stream_priority_enabled INT 0 :reloadable: @@ -3627,7 +3661,7 @@ HTTP/2 Configuration :reloadable: :overridable: - Specifies how long Traffic Server keeps connections to clients open if no + Specifies how long |TS| keeps connections to clients open if no activity is received on the connection. Lowering this timeout can ease pressure on the proxy if misconfigured or misbehaving clients are opening a large number of connections without submitting requests. @@ -3636,7 +3670,7 @@ HTTP/2 Configuration :reloadable: :overridable: - Specifies how long Traffic Server keeps connections to clients open if a + Specifies how long |TS| keeps connections to clients open if a transaction stalls. Lowering this timeout can ease pressure on the proxy if misconfigured or misbehaving clients are opening a large number of connections without submitting requests. @@ -3647,7 +3681,7 @@ HTTP/2 Configuration This timeout enables the zombie debugging feature. If it is non-zero, it sets a zombie event to go off that many seconds in the future when the HTTP2 session reaches one but not both of the terminating events, i.e received a close event (via client goaway or timeout) and the number of active streams has gone to zero. If the event is executed, - the Traffic Server process will assert. This mechanism is useful to debug potential leaks in the HTTP2 Stream and Session + the |TS| process will assert. This mechanism is useful to debug potential leaks in the HTTP2 Stream and Session processing. .. ts:cv:: CONFIG proxy.config.http2.push_diary_size INT 256 @@ -3662,7 +3696,7 @@ Plug-in Configuration .. ts:cv:: CONFIG proxy.config.plugin.plugin_dir STRING config/plugins - Specifies the location of Traffic Server plugins. + Specifies the location of |TS| plugins. .. ts:cv:: CONFIG proxy.config.remap.num_remap_threads INT 0 @@ -3710,7 +3744,7 @@ SOCKS Processor .. ts:cv:: CONFIG proxy.config.socks.connection_attempts INT 4 The total number of connection attempts allowed to a SOCKS server - Traffic Server bypasses the server or fails the request + |TS| bypasses the server or fails the request .. ts:cv:: CONFIG proxy.config.socks.server_retry_timeout INT 300 @@ -3730,21 +3764,21 @@ SOCKS Processor .. ts:cv:: CONFIG proxy.config.socks.server_fail_threshold INT 2 The number of times the connection to the SOCKS server can fail - before Traffic Server considers the server unavailable. + before |TS| considers the server unavailable. .. ts:cv:: CONFIG proxy.config.socks.accept_enabled INT 0 Enables (1) or disables (0) the SOCKS proxy option. As a SOCKS - proxy, Traffic Server receives SOCKS traffic (usually on port + proxy, |TS| receives SOCKS traffic (usually on port 1080) and forwards all requests directly to the SOCKS server. .. ts:cv:: CONFIG proxy.config.socks.accept_port INT 1080 - Specifies the port on which Traffic Server accepts SOCKS traffic. + Specifies the port on which |TS| accepts SOCKS traffic. .. ts:cv:: CONFIG proxy.config.socks.http_port INT 80 - Specifies the port on which Traffic Server accepts HTTP proxy requests + Specifies the port on which |TS| accepts HTTP proxy requests over SOCKS connections.. Sockets @@ -3761,7 +3795,7 @@ Sockets :reloadable: This directive sets the maximum number of pending connections. - If it is set to -1, Traffic Server will automatically set this + If it is set to -1, |TS| will automatically set this to a platform-specific maximum. .. ts:cv:: CONFIG proxy.config.net.tcp_congestion_control_in STRING "" @@ -3778,11 +3812,11 @@ Sockets .. ts:cv:: CONFIG proxy.config.net.sock_send_buffer_size_in INT 0 - Sets the send buffer size for connections from the client to Traffic Server. + Sets the send buffer size for connections from the client to |TS|. .. ts:cv:: CONFIG proxy.config.net.sock_recv_buffer_size_in INT 0 - Sets the receive buffer size for connections from the client to Traffic Server. + Sets the receive buffer size for connections from the client to |TS|. .. ts:cv:: CONFIG proxy.config.net.sock_option_flag_in INT 0x5 @@ -3807,12 +3841,12 @@ Sockets .. ts:cv:: CONFIG proxy.config.net.sock_send_buffer_size_out INT 0 :overridable: - Sets the send buffer size for connections from Traffic Server to the origin server. + Sets the send buffer size for connections from |TS| to the origin server. .. ts:cv:: CONFIG proxy.config.net.sock_recv_buffer_size_out INT 0 :overridable: - Sets the receive buffer size for connections from Traffic Server to + Sets the receive buffer size for connections from |TS| to the origin server. .. ts:cv:: CONFIG proxy.config.net.sock_option_flag_out INT 0x1 @@ -3832,7 +3866,7 @@ Sockets keepalive options above. When SO_LINGER is enabled, the linger timeout time is set - to 0. This is useful when Traffic Server and the origin server + to 0. This is useful when |TS| and the origin server are co-located and large numbers of sockets are retained in the TIME_WAIT state. @@ -3941,7 +3975,7 @@ Sockets .. ts:cv:: CONFIG proxy.config.http.enabled INT 1 Turn on or off support for HTTP proxying. This is rarely used, the one - exception being if you run Traffic Server with a protocol plugin, and would + exception being if you run |TS| with a protocol plugin, and would like for it to not support HTTP requests at all. .. ts:cv:: CONFIG proxy.config.http.allow_half_open INT 1 diff --git a/doc/admin-guide/files/ssl_server_name.yaml.en.rst b/doc/admin-guide/files/ssl_server_name.yaml.en.rst index 4da0c0f7f10..2169d8a3e42 100644 --- a/doc/admin-guide/files/ssl_server_name.yaml.en.rst +++ b/doc/admin-guide/files/ssl_server_name.yaml.en.rst @@ -43,34 +43,46 @@ wildcard entries. To apply an SNI based setting on all the servernames with a co the user needs to enter the fqdn in the configuration with a ``*.`` followed by the common domain name. (``*.yahoo.com`` for e.g.,). .. _override-verify-origin-server: +.. _override-verify-server-policy: +.. _override-verify-server-properties: -======================= ============================================================================== -Key Meaning -======================= ============================================================================== -fqdn Fully Qualified Domain Name. This item is used if the SNI value matches this. +========================= ============================================================================== +Key Meaning +========================= ============================================================================== +fqdn Fully Qualified Domain Name. This item is used if the SNI value matches this. -verify_origin_server One of the values :code:`NONE`, :code:`MODERATE`, or :code:`STRICT`. +verify_server_policy One of the values :code:`DISABLED`, :code:`PERMISSIVE`, or :code:`ENFORCED`. - By default this is :ts:cv:`proxy.config.ssl.client.verify.server`. + By default this is :ts:cv:`proxy.config.ssl.client.verify.server.policy`. + This controls how Traffic Server evaluated the origin certificate. -verify_client One of the values :code:`NONE`, :code:`MODERATE`, or :code:`STRICT`. +verify_server_properties One of the values :code:`NONE`, :code:`SIGNATURE`, :code:`NAME`, and :code:`ALL` - By default this is :ts:cv:`proxy.config.ssl.client.certification_level`. + By default this is :ts:cv:`proxy.config.ssl.client.verify.server.properties`. + This controls what Traffic Server checks when evaluating the origin certificate. -client_cert The client certificate to use for the outbound connection. +verify_origin_server Deprecated. Use verify_server_policy and verify_server_properties instead. + One of the values :code:`NONE`, :code:`MODERATE`, or :code:`STRICT`. + By default this is :ts:cv:`proxy.config.ssl.client.verify.server`. - If this is relative it is relative to the path in - :ts:cv:`proxy.config.ssl.server.cert.path`. If not set - :ts:cv:`proxy.config.ssl.client.cert.filename` is used. +verify_client One of the values :code:`NONE`, :code:`MODERATE`, or :code:`STRICT`. -disable_h2 :code:`true` or :code:`false`. + By default this is :ts:cv:`proxy.config.ssl.client.certification_level`. - If :code:`false` then HTTP/2 is removed from - the valid next protocol list. It is not an error to set this to :code:`false` - for proxy ports on which HTTP/2 is not enabled. +client_cert The file containing the client certificate to use for the outbound connection. -tunnel_route Destination as an FQDN and port, separated by a colon ``:``. -======================= ============================================================================== + If this is relative it is relative to the path in + :ts:cv:`proxy.config.ssl.server.cert.path`. If not set + :ts:cv:`proxy.config.ssl.client.cert.filename` is used. + +disable_h2 :code:`true` or :code:`false`. + + If :code:`false` then HTTP/2 is removed from + the valid next protocol list. It is not an error to set this to :code:`false` + for proxy ports on which HTTP/2 is not enabled. + +tunnel_route Destination as an FQDN and port, separated by a colon ``:``. +========================= ============================================================================== Client verification, via ``verify_client``, correponds to setting :ts:cv:`proxy.config.ssl.client.certification_level` for this connection as noted below. @@ -85,21 +97,38 @@ Client verification, via ``verify_client``, correponds to setting If the verification fails the failure is logged to :file:`diags.log` and the connection is denied. -Upstream (server) verification, via ``verify_origin_server``, is similar to client verification +Upstream (server) verification, via ``verify_server_policy`` and ``verify_server_properties``, is similar to client verification except there is always an upstream certificate. This is equivalent to setting -:ts:cv:`proxy.config.ssl.client.verify.server` for this connection. +:ts:cv:`proxy.config.ssl.client.verify.server.policy` and :ts:cv:`proxy.config.ssl.client.verify.server.properties` for this connection. -:code:`NONE` - ``0`` +``verify_server_policy`` specifies how Traffic Server will enforce the server certificate verification. + +:code:`DISABLED` Do not verify the upstream server certificate. -:code:`MODERATE` - ``2`` +:code:`PERMISSIVE` Do verification of the upstream certificate but do not enforce. If the verification fails the failure is logged in :file:`diags.log` but the connection is allowed. -:code:`STRICT` - ``1`` +:code:`ENFORCED` Do verification of the upstream certificate. If verification fails, the failure is logged in :file:`diags.log` and the connection is denied. +In addition ``verify_server_properties`` specifies what Traffic Server will check when performing the verification. + +:code:`NONE` + Do not check anything in the standard Traffic Server verification routine. Rely entirely on the ``TS_SSL_VERIFY_SERVER_HOOK`` for evaluating the origin's certificate. + +:code:`SIGNATURE` + Check the signature of the origin certificate. + +:code:`NAME` + Verify that the SNI is in the origin certificate. + +:code:`ALL` + Verify both the signature and the SNI in the origin certificate. + + If ``tunnel_route`` is specified, none of the certificate verification will be done because the TLS negotiation will be tunneled to the upstream target, making those values irrelevant for that configuration item. This option is explained in more detail in :ref:`sni-routing`. @@ -129,7 +158,7 @@ client certificate. .. code-block:: yaml - fqdn: trusted.example.com - verify_origin_server: NONE + verify_server_policy: DISABLED verify_client: STRICT See Also diff --git a/doc/admin-guide/security/index.en.rst b/doc/admin-guide/security/index.en.rst index 4271c963150..411a924a448 100644 --- a/doc/admin-guide/security/index.en.rst +++ b/doc/admin-guide/security/index.en.rst @@ -220,10 +220,10 @@ and origin server connections, you must do the following: CONFIG proxy.config.ssl.client.private_key.filename STRING "client.pem" #. Enable or disable, per your security policy, server SSL certificate - verification using :ts:cv:`proxy.config.ssl.client.verify.server` in + verification using :ts:cv:`proxy.config.ssl.client.verify.server.policy` in :file:`records.config`. :: - CONFIG proxy.config.ssl.client.verify.server INT 1 + CONFIG proxy.config.ssl.client.verify.server.policy STRING ENFORCED #. Add the collection of authorized Certificate Authorities to the Traffic Server configuration in :file:`records.config` using the settings diff --git a/doc/developer-guide/api/functions/TSVConnReenable.en.rst b/doc/developer-guide/api/functions/TSVConnReenable.en.rst index 847c6901760..b076b6093f6 100644 --- a/doc/developer-guide/api/functions/TSVConnReenable.en.rst +++ b/doc/developer-guide/api/functions/TSVConnReenable.en.rst @@ -35,10 +35,9 @@ Reenable the SSL connection :arg:`svc`. If a plugin hook is called, ATS processing on that connnection will not resume until this is invoked for that connection. -If the server is running OpenSSL 1.0.1 with the appropraite patch installed or -it is running OpenSSL 1.0.2, the plugin writer can pause SSL handshake -processing by not reenabling the connection. Without the OpenSSL patch or -running an OpenSSL versions older than 1.0.2, the handshake processing in +If the server is running OpenSSL 1.0.2, the plugin writer can pause SSL handshake +processing at the certificate callback by not reenabling the connection. +Running an OpenSSL versions older than 1.0.2, the handshake processing in ``SSL_accept`` will not be stopped even if the SNI callback does not reenable the connection. @@ -49,3 +48,4 @@ Traffic Server. This call does appropriate locking and scheduling, so it is safe to call from another thread. + diff --git a/doc/developer-guide/plugins/example-plugins/tls_bridge.en.rst b/doc/developer-guide/plugins/example-plugins/tls_bridge.en.rst index 31cce7d370e..1b979fea4c0 100644 --- a/doc/developer-guide/plugins/example-plugins/tls_bridge.en.rst +++ b/doc/developer-guide/plugins/example-plugins/tls_bridge.en.rst @@ -96,7 +96,7 @@ Configuration #. Configure the Ingress |TS| to verify the Peer server certificate:: - CONFIG proxy.config.ssl.client.verify.server INT 1 + CONFIG proxy.config.ssl.client.verify.server.policy STRING ENFORCED #. Configure Certificate Authority used by the Ingress |TS| to verify the Peer server certificate. If this is a directory all of the certificates in the directory are treated as Certificate Authorites. :: diff --git a/iocore/net/I_NetVConnection.h b/iocore/net/I_NetVConnection.h index de9b44b6249..e9b0427a429 100644 --- a/iocore/net/I_NetVConnection.h +++ b/iocore/net/I_NetVConnection.h @@ -33,6 +33,7 @@ #include "I_Socks.h" #include "ts/apidefs.h" #include +#include "YamlSNIConfig.h" #define CONNECT_SUCCESS 1 #define CONNECT_FAILURE 0 @@ -188,7 +189,17 @@ struct NetVCOptions { ats_scoped_str clientCertificate; /// Reset all values to defaults. - uint8_t clientVerificationFlag = 0; + /** + * Set to DISABLED, PERFMISSIVE, or ENFORCED + * Controls how the server certificate verification is handled + */ + YamlSNIConfig::Policy verifyServerPolicy = YamlSNIConfig::Policy::DISABLED; + + /** + * Bit mask of which features of the server certificate should be checked + * Currently SIGNATURE and NAME + */ + YamlSNIConfig::Property verifyServerProperties = YamlSNIConfig::Property::NONE; void reset(); void set_sock_param(int _recv_bufsize, int _send_bufsize, unsigned long _opt_flags, unsigned long _packet_mark = 0, diff --git a/iocore/net/P_SSLConfig.h b/iocore/net/P_SSLConfig.h index 9bbb7b1911c..152a6bb2617 100644 --- a/iocore/net/P_SSLConfig.h +++ b/iocore/net/P_SSLConfig.h @@ -35,6 +35,7 @@ #include "tscore/ink_inet.h" #include #include "P_SSLCertLookup.h" +#include "YamlSNIConfig.h" struct SSLCertLookup; struct ssl_ticket_key_block; @@ -82,7 +83,8 @@ struct SSLConfigParams : public ConfigInfo { char *clientKeyPath; char *clientCACertFilename; char *clientCACertPath; - int8_t clientVerify; + YamlSNIConfig::Policy verifyServerPolicy; + YamlSNIConfig::Property verifyServerProperties; int client_verify_depth; long ssl_ctx_options; long ssl_client_ctx_options; diff --git a/iocore/net/P_SSLNetVConnection.h b/iocore/net/P_SSLNetVConnection.h index 0d64e3ddddf..72ef4d76d30 100644 --- a/iocore/net/P_SSLNetVConnection.h +++ b/iocore/net/P_SSLNetVConnection.h @@ -77,6 +77,8 @@ typedef enum { SSL_HOOK_OP_LAST = SSL_HOOK_OP_TERMINATE ///< End marker value. } SslVConnOp; +enum SSLHandshakeStatus { SSL_HANDSHAKE_ONGOING, SSL_HANDSHAKE_DONE, SSL_HANDSHAKE_ERROR }; + ////////////////////////////////////////////////////////////////// // // class NetVConnection @@ -113,13 +115,13 @@ class SSLNetVConnection : public UnixNetVConnection bool getSSLHandShakeComplete() const override { - return sslHandShakeComplete; + return sslHandshakeStatus != SSL_HANDSHAKE_ONGOING; } virtual void - setSSLHandShakeComplete(bool state) + setSSLHandShakeComplete(enum SSLHandshakeStatus state) { - sslHandShakeComplete = state; + sslHandshakeStatus = state; } void @@ -192,7 +194,7 @@ class SSLNetVConnection : public UnixNetVConnection using super::reenable; /// Reenable the VC after a pre-accept or SNI hook is called. - virtual void reenable(NetHandler *nh); + virtual void reenable(NetHandler *nh, int event = TS_EVENT_CONTINUE); /// Set the SSL context. /// @note This must be called after the SSL endpoint has been created. @@ -280,6 +282,10 @@ class SSLNetVConnection : public UnixNetVConnection } break; + case HANDSHAKE_HOOKS_VERIFY_SERVER: + retval = (eventId == TS_EVENT_SSL_VERIFY_SERVER); + break; + case HANDSHAKE_HOOKS_DONE: retval = true; break; @@ -340,13 +346,13 @@ class SSLNetVConnection : public UnixNetVConnection std::string_view map_tls_protocol_to_tag(const char *proto_string) const; bool update_rbio(bool move_to_socket); - bool sslHandShakeComplete = false; - bool sslClientRenegotiationAbort = false; - bool sslSessionCacheHit = false; - MIOBuffer *handShakeBuffer = nullptr; - IOBufferReader *handShakeHolder = nullptr; - IOBufferReader *handShakeReader = nullptr; - int handShakeBioStored = 0; + enum SSLHandshakeStatus sslHandshakeStatus = SSL_HANDSHAKE_ONGOING; + bool sslClientRenegotiationAbort = false; + bool sslSessionCacheHit = false; + MIOBuffer *handShakeBuffer = nullptr; + IOBufferReader *handShakeHolder = nullptr; + IOBufferReader *handShakeReader = nullptr; + int handShakeBioStored = 0; bool transparentPassThrough = false; @@ -364,6 +370,7 @@ class SSLNetVConnection : public UnixNetVConnection HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE, HANDSHAKE_HOOKS_OUTBOUND_PRE, HANDSHAKE_HOOKS_OUTBOUND_PRE_INVOKE, + HANDSHAKE_HOOKS_VERIFY_SERVER, HANDSHAKE_HOOKS_DONE } sslHandshakeHookState = HANDSHAKE_HOOKS_PRE; diff --git a/iocore/net/P_SSLSNI.h b/iocore/net/P_SSLSNI.h index fc4ed030b01..33543da8c53 100644 --- a/iocore/net/P_SSLSNI.h +++ b/iocore/net/P_SSLSNI.h @@ -41,9 +41,10 @@ // Properties for the next hop server struct NextHopProperty { - const char *name = nullptr; // name of the server - int8_t verifyLevel = 0; // whether to verify the next hop - SSL_CTX *ctx = nullptr; // ctx generated off the certificate to present to this server + const char *name = nullptr; // name of the server + YamlSNIConfig::Policy verifyServerPolicy = YamlSNIConfig::Policy::DISABLED; // whether to verify the next hop + YamlSNIConfig::Property verifyServerProperties = YamlSNIConfig::Property::NONE; // what to verify on the next hop + SSL_CTX *ctx = nullptr; // ctx generated off the certificate to present to this server NextHopProperty(); }; diff --git a/iocore/net/SSLClientUtils.cc b/iocore/net/SSLClientUtils.cc index 386f2443eb9..79c1525202c 100644 --- a/iocore/net/SSLClientUtils.cc +++ b/iocore/net/SSLClientUtils.cc @@ -37,7 +37,7 @@ typedef SSL_METHOD *ink_ssl_method_t; #endif int -verify_callback(int preverify_ok, X509_STORE_CTX *ctx) +verify_callback(int signature_ok, X509_STORE_CTX *ctx) { X509 *cert; int depth; @@ -45,9 +45,6 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) SSL *ssl; SSLDebug("Entered verify cb"); - depth = X509_STORE_CTX_get_error_depth(ctx); - cert = X509_STORE_CTX_get_current_cert(ctx); - err = X509_STORE_CTX_get_error(ctx); /* * Retrieve the pointer to the SSL of the connection currently treated @@ -55,31 +52,45 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) */ ssl = static_cast(X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx())); SSLNetVConnection *netvc = SSLNetVCAccess(ssl); - bool enforce_mode = (netvc && netvc->options.clientVerificationFlag == static_cast(YamlSNIConfig::Level::STRICT)); - if (!preverify_ok && netvc != nullptr) { - // Don't bother to check the hostname if we failed openssl's verification - SSLDebug("verify error:num=%d:%s:depth=%d", err, X509_verify_cert_error_string(err), depth); - const char *sni_name; - char buff[INET6_ADDRSTRLEN]; - ats_ip_ntop(netvc->get_remote_addr(), buff, INET6_ADDRSTRLEN); - if (netvc->options.sni_servername) { - sni_name = netvc->options.sni_servername.get(); - } else { - sni_name = buff; - } - Warning("Core server certificate verification failed for (%s). Action=%s Error=%s server=%s(%s) depth=%d", sni_name, - enforce_mode ? "Terminate" : "Continue", X509_verify_cert_error_string(err), netvc->options.ssl_servername.get(), buff, - depth); - // If not enforcing ignore the error, just log warning - return enforce_mode ? preverify_ok : 1; + + // No enforcing, go away + if (netvc && netvc->options.verifyServerPolicy == YamlSNIConfig::Policy::DISABLED) { + return true; // Tell them that all is well + } else if (!netvc) { // No netvc, very bad. Go away. Things are not good. + Warning("Netvc gone by in verify_callback"); + return false; } - if (depth != 0) { - // Not server cert.... - return preverify_ok; + + depth = X509_STORE_CTX_get_error_depth(ctx); + cert = X509_STORE_CTX_get_current_cert(ctx); + err = X509_STORE_CTX_get_error(ctx); + + bool enforce_mode = (netvc->options.verifyServerPolicy == YamlSNIConfig::Policy::ENFORCED); + bool check_sig = + static_cast(netvc->options.verifyServerProperties) & static_cast(YamlSNIConfig::Property::SIGNATURE_MASK); + + if (check_sig) { + if (!signature_ok) { + SSLDebug("verify error:num=%d:%s:depth=%d", err, X509_verify_cert_error_string(err), depth); + const char *sni_name; + char buff[INET6_ADDRSTRLEN]; + ats_ip_ntop(netvc->get_remote_addr(), buff, INET6_ADDRSTRLEN); + if (netvc->options.sni_servername) { + sni_name = netvc->options.sni_servername.get(); + } else { + sni_name = buff; + } + Warning("Core server certificate verification failed for (%s). Action=%s Error=%s server=%s(%s) depth=%d", sni_name, + enforce_mode ? "Terminate" : "Continue", X509_verify_cert_error_string(err), netvc->options.ssl_servername.get(), + buff, depth); + // If not enforcing ignore the error, just log warning + return enforce_mode ? signature_ok : 1; + } } - if (netvc != nullptr) { - netvc->callHooks(TS_EVENT_SSL_VERIFY_SERVER); + bool check_name = + static_cast(netvc->options.verifyServerProperties) & static_cast(YamlSNIConfig::Property::NAME_MASK); + if (check_name) { char *matched_name = nullptr; unsigned char *sni_name; char buff[INET6_ADDRSTRLEN]; @@ -92,18 +103,34 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx) if (validate_hostname(cert, sni_name, false, &matched_name)) { SSLDebug("Hostname %s verified OK, matched %s", netvc->options.sni_servername.get(), matched_name); ats_free(matched_name); - return preverify_ok; + } else { // Name validation failed + // Get the server address if we did't already compute it + if (netvc->options.sni_servername) { + ats_ip_ntop(netvc->get_remote_addr(), buff, INET6_ADDRSTRLEN); + } + // If we got here the verification failed + Warning("SNI (%s) not in certificate. Action=%s server=%s(%s)", sni_name, enforce_mode ? "Terminate" : "Continue", + netvc->options.ssl_servername.get(), buff); + return !enforce_mode; } - // Get the server address if we did't already compute it + } + // If the previous configured checks passed, give the hook a try + netvc->callHooks(TS_EVENT_SSL_VERIFY_SERVER); + if (netvc->getSSLHandShakeComplete()) { // hook moved the handshake state to terminal + unsigned char *sni_name; + char buff[INET6_ADDRSTRLEN]; if (netvc->options.sni_servername) { + sni_name = reinterpret_cast(netvc->options.sni_servername.get()); + } else { + sni_name = reinterpret_cast(buff); ats_ip_ntop(netvc->get_remote_addr(), buff, INET6_ADDRSTRLEN); } - // If we got here the verification failed - Warning("SNI (%s) not in certificate. Action=%s server=%s(%s)", sni_name, enforce_mode ? "Terminate" : "Continue", - netvc->options.ssl_servername.get(), buff); - return enforce_mode ? 0 : preverify_ok; + Warning("TS_EVENT_SSL_VERIFY_SERVER plugin failed the origin certificate check for %s. Action=%s SNI=%s", + netvc->options.ssl_servername.get(), enforce_mode ? "Terminate" : "Continue", sni_name); + return !enforce_mode; } - return preverify_ok; + // Made it this far. All is good + return true; } SSL_CTX * @@ -175,10 +202,8 @@ SSLInitClientContext(const SSLConfigParams *params) } } - if (params->clientVerify) { - SSL_CTX_set_verify(client_ctx, SSL_VERIFY_PEER, verify_callback); - SSL_CTX_set_verify_depth(client_ctx, params->client_verify_depth); - } + SSL_CTX_set_verify(client_ctx, SSL_VERIFY_PEER, verify_callback); + SSL_CTX_set_verify_depth(client_ctx, params->client_verify_depth); if (params->clientCACertFilename != nullptr || params->clientCACertPath != nullptr) { if (!SSL_CTX_load_verify_locations(client_ctx, params->clientCACertFilename, params->clientCACertPath)) { diff --git a/iocore/net/SSLConfig.cc b/iocore/net/SSLConfig.cc index ae8fdc05d1f..6291a2af05b 100644 --- a/iocore/net/SSLConfig.cc +++ b/iocore/net/SSLConfig.cc @@ -36,6 +36,7 @@ #include #include "P_Net.h" #include "P_SSLConfig.h" +#include "YamlSNIConfig.h" #include "P_SSLUtils.h" #include "P_SSLCertLookup.h" #include "SSLSessionCache.h" @@ -99,11 +100,13 @@ SSLConfigParams::reset() server_groups_list = nullptr; client_groups_list = nullptr; client_ctx = nullptr; - clientCertLevel = client_verify_depth = verify_depth = clientVerify = 0; - ssl_ctx_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - ssl_client_ctx_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; - ssl_session_cache = SSL_SESSION_CACHE_MODE_SERVER_ATS_IMPL; - ssl_session_cache_size = 1024 * 100; + clientCertLevel = client_verify_depth = verify_depth = 0; + verifyServerPolicy = YamlSNIConfig::Policy::DISABLED; + verifyServerProperties = YamlSNIConfig::Property::NONE; + ssl_ctx_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + ssl_client_ctx_options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; + ssl_session_cache = SSL_SESSION_CACHE_MODE_SERVER_ATS_IMPL; + ssl_session_cache_size = 1024 * 100; ssl_session_cache_num_buckets = 1024; // Sessions per bucket is ceil(ssl_session_cache_size / ssl_session_cache_num_buckets) ssl_session_cache_skip_on_contention = 0; ssl_session_cache_timeout = 0; @@ -320,7 +323,83 @@ SSLConfigParams::initialize() // ++++++++++++++++++++++++ Client part ++++++++++++++++++++ client_verify_depth = 7; - REC_EstablishStaticConfigByte(clientVerify, "proxy.config.ssl.client.verify.server"); + + // remove before 9.0.0 release + // Backwards compatibility if proxy.config.ssl.client.verify.server is explicitly set + RecSourceT source = REC_SOURCE_DEFAULT; + bool set_backwards_compatible = false; + if (RecGetRecordSource("proxy.config.ssl.client.verify.server", &source, false) == REC_ERR_OKAY) { + if (source != REC_SOURCE_DEFAULT && source != REC_SOURCE_NULL) { + int8_t verifyServer = 0; + REC_EstablishStaticConfigByte(verifyServer, "proxy.config.ssl.client.verify.server"); + verifyServerProperties = YamlSNIConfig::Property::ALL_MASK; + switch (verifyServer) { + case 0: + verifyServerPolicy = YamlSNIConfig::Policy::DISABLED; + set_backwards_compatible = true; + break; + case 1: + verifyServerPolicy = YamlSNIConfig::Policy::ENFORCED; + set_backwards_compatible = true; + break; + case 2: + verifyServerPolicy = YamlSNIConfig::Policy::PERMISSIVE; + set_backwards_compatible = true; + break; + } + } + } + + bool policy_default = true; + bool properties_default = true; + if (!set_backwards_compatible) { + policy_default = properties_default = false; + } else { // Only check for non-defaults if we have a backwards compatible situation + if (RecGetRecordSource("proxy.config.ssl.client.verify.server.policy", &source, false) == REC_ERR_OKAY && + source != REC_SOURCE_DEFAULT && source != REC_SOURCE_NULL) { + policy_default = false; + } + if (RecGetRecordSource("proxy.config.ssl.client.verify.server.properties", &source, false) == REC_ERR_OKAY && + source != REC_SOURCE_DEFAULT && source != REC_SOURCE_NULL) { + properties_default = false; + } + } + + if (!set_backwards_compatible || !policy_default) { + char *verify_server = nullptr; + REC_ReadConfigStringAlloc(verify_server, "proxy.config.ssl.client.verify.server.policy"); + if (strcmp(verify_server, "DISABLED") == 0) { + verifyServerPolicy = YamlSNIConfig::Policy::DISABLED; + } else if (strcmp(verify_server, "PERMISSIVE") == 0) { + verifyServerPolicy = YamlSNIConfig::Policy::PERMISSIVE; + } else if (strcmp(verify_server, "ENFORCED") == 0) { + verifyServerPolicy = YamlSNIConfig::Policy::ENFORCED; + } else { + Warning("%s is invalid for proxy.config.ssl.client.verify.server.policy. Should be one of DISABLED, PERMISSIVE, or ENFORCED", + verify_server); + verifyServerPolicy = YamlSNIConfig::Policy::DISABLED; + } + ats_free(verify_server); + } + + if (!set_backwards_compatible || !properties_default) { + char *verify_server = nullptr; + REC_ReadConfigStringAlloc(verify_server, "proxy.config.ssl.client.verify.server.properties"); + if (strcmp(verify_server, "SIGNATURE") == 0) { + verifyServerProperties = YamlSNIConfig::Property::SIGNATURE_MASK; + } else if (strcmp(verify_server, "NAME") == 0) { + verifyServerProperties = YamlSNIConfig::Property::NAME_MASK; + } else if (strcmp(verify_server, "ALL") == 0) { + verifyServerProperties = YamlSNIConfig::Property::ALL_MASK; + } else if (strcmp(verify_server, "NONE") == 0) { + verifyServerProperties = YamlSNIConfig::Property::NONE; + } else { + Warning("%s is invalid for proxy.config.ssl.client.verify.server.properties. Should be one of SIGNATURE, NAME, or ALL", + verify_server); + verifyServerProperties = YamlSNIConfig::Property::NONE; + } + ats_free(verify_server); + } ssl_client_cert_filename = nullptr; ssl_client_cert_path = nullptr; diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc index 35ebb5a1f6d..6b3dde29c75 100644 --- a/iocore/net/SSLNetVConnection.cc +++ b/iocore/net/SSLNetVConnection.cc @@ -514,7 +514,7 @@ SSLNetVConnection::net_read_io(NetHandler *nh, EThread *lthread) // the client hello message back into the standard read.vio // so it will get forwarded onto the origin server if (!this->getSSLHandShakeComplete()) { - this->sslHandShakeComplete = true; + this->sslHandshakeStatus = SSL_HANDSHAKE_DONE; // Copy over all data already read in during the SSL_accept // (the client hello message) @@ -840,7 +840,7 @@ SSLNetVConnection::do_io_close(int lerrno) callHooks(TS_EVENT_VCONN_CLOSE); } - if (sslHandShakeComplete) { + if (getSSLHandShakeComplete()) { int shutdown_mode = SSL_get_shutdown(ssl); Debug("ssl-shutdown", "previous shutdown state 0x%x", shutdown_mode); int new_shutdown_mode = shutdown_mode | SSL_RECEIVED_SHUTDOWN; @@ -883,18 +883,17 @@ SSLNetVConnection::clear() ssl = nullptr; } - sslHandShakeComplete = false; + sslHandshakeStatus = SSL_HANDSHAKE_ONGOING; sslHandshakeBeginTime = 0; sslLastWriteTime = 0; sslTotalBytesSent = 0; sslClientRenegotiationAbort = false; sslSessionCacheHit = false; - curHook = nullptr; - hookOpRequested = SSL_HOOK_OP_DEFAULT; - npnSet = nullptr; - npnEndpoint = nullptr; - sslHandShakeComplete = false; + curHook = nullptr; + hookOpRequested = SSL_HOOK_OP_DEFAULT; + npnSet = nullptr; + npnEndpoint = nullptr; free_handshake_buffers(); sslTrace = false; @@ -965,8 +964,8 @@ SSLNetVConnection::sslStartHandShake(int event, int &err) if (cc && SSLCertContext::OPT_TUNNEL == cc->opt) { if (this->is_transparent) { - this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL; - sslHandShakeComplete = true; + this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL; + sslHandshakeStatus = SSL_HANDSHAKE_DONE; SSL_free(this->ssl); this->ssl = nullptr; return EVENT_DONE; @@ -998,8 +997,7 @@ SSLNetVConnection::sslStartHandShake(int event, int &err) // Making the check here instead of later, so we only // do this setting immediately after we create the SSL object SNIConfig::scoped_config sniParam; - int8_t clientVerify = 0; - cchar *serverKey = this->options.sni_servername; + cchar *serverKey = this->options.sni_servername; if (!serverKey) { ats_ip_ntop(this->get_remote_addr(), buff, INET6_ADDRSTRLEN); serverKey = buff; @@ -1008,12 +1006,14 @@ SSLNetVConnection::sslStartHandShake(int event, int &err) SSL_CTX *clientCTX = nullptr; if (nps) { - clientCTX = nps->ctx; - clientVerify = nps->verifyLevel; + clientCTX = nps->ctx; + options.verifyServerPolicy = nps->verifyServerPolicy; + options.verifyServerProperties = nps->verifyServerProperties; + } else { - clientCTX = params->client_ctx; - // Keeping backwards compatability on the proxy.config.ssl.client.verify.server setting - clientVerify = params->clientVerify ? (params->clientVerify == 1 ? 2 : 1) : 0; + clientCTX = params->client_ctx; + options.verifyServerPolicy = params->verifyServerPolicy; + options.verifyServerProperties = params->verifyServerProperties; } if (!clientCTX) { SSLErrorVC(this, "failed to create SSL client session"); @@ -1025,15 +1025,8 @@ SSLNetVConnection::sslStartHandShake(int event, int &err) SSLErrorVC(this, "failed to create SSL client session"); return EVENT_ERROR; } - int verify_op; - if (clientVerify) { - verify_op = SSL_VERIFY_PEER; - SSL_set_verify(this->ssl, verify_op, verify_callback); - } else { - // Don't bother to set the verify callback if no verification is required - verify_op = SSL_VERIFY_NONE; - SSL_set_verify(this->ssl, verify_op, nullptr); - } + + SSL_set_verify(this->ssl, SSL_VERIFY_PEER, verify_callback); if (this->options.sni_servername) { if (SSL_set_tlsext_host_name(this->ssl, this->options.sni_servername)) { @@ -1095,7 +1088,7 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) // over the buffered handshake packets to the O.S. return EVENT_DONE; } else if (SSL_HOOK_OP_TERMINATE == hookOpRequested) { - sslHandShakeComplete = true; + sslHandshakeStatus = SSL_HANDSHAKE_DONE; return EVENT_DONE; } @@ -1179,8 +1172,8 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) char *buf = handShakeBuffer ? handShakeBuffer->buf() : nullptr; if (getTransparentPassThrough() && buf && *buf != SSL_OP_HANDSHAKE) { SSLVCDebug(this, "Data does not look like SSL handshake, starting blind tunnel"); - this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL; - sslHandShakeComplete = false; + this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL; + sslHandshakeStatus = SSL_HANDSHAKE_ONGOING; return EVENT_CONT; } } @@ -1198,7 +1191,7 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) } } - sslHandShakeComplete = true; + sslHandshakeStatus = SSL_HANDSHAKE_DONE; TraceIn(trace, get_remote_addr(), get_remote_port(), "SSL server handshake completed successfully"); // do we want to include cert info in trace? @@ -1279,8 +1272,8 @@ SSLNetVConnection::sslServerHandShakeEvent(int &err) #endif #if defined(SSL_ERROR_WANT_SNI_RESOLVE) || defined(SSL_ERROR_WANT_X509_LOOKUP) if (this->attributes == HttpProxyPort::TRANSPORT_BLIND_TUNNEL || SSL_HOOK_OP_TUNNEL == hookOpRequested) { - this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL; - sslHandShakeComplete = false; + this->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL; + sslHandshakeStatus = SSL_HANDSHAKE_ONGOING; return EVENT_CONT; } else { // Stopping for some other reason, perhaps loading certificate @@ -1380,7 +1373,7 @@ SSLNetVConnection::sslClientHandShakeEvent(int &err) TraceIn(trace, get_remote_addr(), get_remote_port(), "SSL client handshake completed successfully"); // do we want to include cert info in trace? - sslHandShakeComplete = true; + sslHandshakeStatus = SSL_HANDSHAKE_DONE; return EVENT_DONE; case SSL_ERROR_WANT_WRITE: @@ -1502,7 +1495,7 @@ SSLNetVConnection::select_next_protocol(SSL *ssl, const unsigned char **out, uns } void -SSLNetVConnection::reenable(NetHandler *nh) +SSLNetVConnection::reenable(NetHandler *nh, int event) { Debug("ssl", "Handshake reenable from state=%d", sslHandshakeHookState); @@ -1516,6 +1509,11 @@ SSLNetVConnection::reenable(NetHandler *nh) case HANDSHAKE_HOOKS_CERT_INVOKE: sslHandshakeHookState = HANDSHAKE_HOOKS_CERT; break; + case HANDSHAKE_HOOKS_VERIFY_SERVER: + if (event == TS_EVENT_ERROR) { + sslHandshakeStatus = SSL_HANDSHAKE_ERROR; + } + break; default: break; } @@ -1555,6 +1553,9 @@ SSLNetVConnection::reenable(NetHandler *nh) } else { ContWrapper::wrap(nh->mutex.get(), curHook->m_cont, TS_EVENT_VCONN_CLOSE, this); } + } else if (sslHandshakeHookState == HANDSHAKE_HOOKS_VERIFY_SERVER) { + Debug("ssl", "ServerVerify"); + ContWrapper::wrap(nh->mutex.get(), curHook->m_cont, TS_EVENT_SSL_VERIFY_SERVER, this); } return; } else { @@ -1582,6 +1583,9 @@ SSLNetVConnection::reenable(NetHandler *nh) case HANDSHAKE_HOOKS_CLIENT_CERT_INVOKE: sslHandshakeHookState = HANDSHAKE_HOOKS_DONE; break; + case HANDSHAKE_HOOKS_VERIFY_SERVER: + sslHandshakeHookState = HANDSHAKE_HOOKS_DONE; + break; default: break; } @@ -1617,6 +1621,8 @@ SSLNetVConnection::callHooks(TSEvent eventId) case HANDSHAKE_HOOKS_PRE: if (eventId == TS_EVENT_SSL_SERVERNAME) { this->sslHandshakeHookState = HANDSHAKE_HOOKS_SNI; + } else if (eventId == TS_EVENT_SSL_VERIFY_SERVER) { + this->sslHandshakeHookState = HANDSHAKE_HOOKS_VERIFY_SERVER; } else if (eventId == TS_EVENT_SSL_CERT) { this->sslHandshakeHookState = HANDSHAKE_HOOKS_CERT; } @@ -1632,22 +1638,23 @@ SSLNetVConnection::callHooks(TSEvent eventId) // Look for hooks associated with the event switch (this->sslHandshakeHookState) { - case HANDSHAKE_HOOKS_SNI: + case HANDSHAKE_HOOKS_VERIFY_SERVER: // The server verify event addresses ATS to origin handshake // All the other events are for client to ATS - if (eventId == TS_EVENT_SSL_VERIFY_SERVER) { - if (!curHook) { - curHook = ssl_hooks->get(TS_SSL_VERIFY_SERVER_INTERNAL_HOOK); - } + if (!curHook) { + curHook = ssl_hooks->get(TS_SSL_VERIFY_SERVER_INTERNAL_HOOK); } else { - if (!curHook) { - curHook = ssl_hooks->get(TS_SSL_SERVERNAME_INTERNAL_HOOK); - } else { - curHook = curHook->next(); - } - if (!curHook) { - this->sslHandshakeHookState = HANDSHAKE_HOOKS_CERT; - } + curHook = curHook->next(); + } + break; + case HANDSHAKE_HOOKS_SNI: + if (!curHook) { + curHook = ssl_hooks->get(TS_SSL_SERVERNAME_INTERNAL_HOOK); + } else { + curHook = curHook->next(); + } + if (!curHook) { + this->sslHandshakeHookState = HANDSHAKE_HOOKS_CERT; } break; case HANDSHAKE_HOOKS_CERT: @@ -1786,7 +1793,7 @@ SSLNetVConnection::populate(Connection &con, Continuation *c, void *arg) this->ssl = (SSL *)arg; // Maybe bring over the stats? - this->sslHandShakeComplete = true; + sslHandshakeStatus = SSL_HANDSHAKE_DONE; SSLNetVCAttach(this->ssl, this); return EVENT_DONE; } diff --git a/iocore/net/SSLSNIConfig.cc b/iocore/net/SSLSNIConfig.cc index 7366eff7bde..d3b5c0c5df0 100644 --- a/iocore/net/SSLSNIConfig.cc +++ b/iocore/net/SSLSNIConfig.cc @@ -92,10 +92,11 @@ SNIConfigParams::loadSNIConfig() clientCTX = params->getNewCTX(certFile); params->InsertCTX(certFile, clientCTX); } - NextHopProperty *nps = new NextHopProperty(); - nps->name = ats_strdup(servername); - nps->verifyLevel = item.verify_origin_server; - nps->ctx = clientCTX; + NextHopProperty *nps = new NextHopProperty(); + nps->name = ats_strdup(servername); + nps->verifyServerPolicy = item.verify_server_policy; + nps->verifyServerProperties = item.verify_server_properties; + nps->ctx = clientCTX; if (wildcard) { wild_next_hop_table.put(nps->name, nps); } else { diff --git a/iocore/net/SSLUtils.cc b/iocore/net/SSLUtils.cc index 3b09dc0ef23..10a8c803225 100644 --- a/iocore/net/SSLUtils.cc +++ b/iocore/net/SSLUtils.cc @@ -354,7 +354,7 @@ set_context_cert(SSL *ssl) } if (cc && SSLCertContext::OPT_TUNNEL == cc->opt && netvc->get_is_transparent()) { netvc->attributes = HttpProxyPort::TRANSPORT_BLIND_TUNNEL; - netvc->setSSLHandShakeComplete(true); + netvc->setSSLHandShakeComplete(SSL_HANDSHAKE_DONE); retval = -1; goto done; } diff --git a/iocore/net/YamlSNIConfig.cc b/iocore/net/YamlSNIConfig.cc index 6f31777e4d5..ce462ebb768 100644 --- a/iocore/net/YamlSNIConfig.cc +++ b/iocore/net/YamlSNIConfig.cc @@ -55,10 +55,13 @@ YamlSNIConfig::loader(const char *cfgFilename) return ts::Errata(); } -TsEnumDescriptor LEVEL_DESCRIPTOR = {{{"NONE", 0}, {"MODERATE", 1}, {"STRICT", 2}}}; +TsEnumDescriptor LEVEL_DESCRIPTOR = {{{"NONE", 0}, {"MODERATE", 1}, {"STRICT", 2}}}; +TsEnumDescriptor POLICY_DESCRIPTOR = {{{"DISABLED", 0}, {"PERMISSIVE", 1}, {"ENFORCED", 2}}}; +TsEnumDescriptor PROPERTIES_DESCRIPTOR = {{{"NONE", 0}, {"SIGNATURE", 0x1}, {"NAME", 0x2}, {"ALL", 0x3}}}; std::set valid_sni_config_keys = { - TS_fqdn, TS_disable_H2, TS_verify_client, TS_tunnel_route, TS_verify_origin_server, TS_client_cert, TS_ip_allow}; + TS_fqdn, TS_disable_H2, TS_verify_client, TS_tunnel_route, TS_verify_server_policy, TS_verify_server_properties, + TS_client_cert, TS_ip_allow}; namespace YAML { @@ -87,7 +90,7 @@ template <> struct convert { auto value = node[TS_verify_client].as(); int level = LEVEL_DESCRIPTOR.get(value); if (level < 0) { - throw std::runtime_error("unknown value " + value); + throw std::runtime_error("unknown value \"" + value + "\""); } item.verify_client_level = static_cast(level); } @@ -95,14 +98,41 @@ template <> struct convert { if (node[TS_tunnel_route]) { item.tunnel_destination = node[TS_tunnel_route].as(); } - + // remove before 9.0.0 release + // backwards compatibiity if (node[TS_verify_origin_server]) { - auto value = node[TS_verify_origin_server].as(); - int level = LEVEL_DESCRIPTOR.get(value); - if (level < 0) { - throw std::runtime_error("unknown value " + value); + auto value = node[TS_verify_origin_server].as(); + YamlSNIConfig::Level level = static_cast(LEVEL_DESCRIPTOR.get(value)); + item.verify_server_properties = YamlSNIConfig::Property::ALL_MASK; + switch (level) { + case YamlSNIConfig::Level::NONE: + item.verify_server_policy = YamlSNIConfig::Policy::DISABLED; + break; + case YamlSNIConfig::Level::MODERATE: + item.verify_server_policy = YamlSNIConfig::Policy::PERMISSIVE; + break; + case YamlSNIConfig::Level::STRICT: + item.verify_server_policy = YamlSNIConfig::Policy::ENFORCED; + break; + } + } + + if (node[TS_verify_server_policy]) { + auto value = node[TS_verify_server_policy].as(); + int policy = POLICY_DESCRIPTOR.get(value); + if (policy < 0) { + throw std::runtime_error("unknown value \"" + value + "\""); + } + item.verify_server_policy = static_cast(policy); + } + + if (node[TS_verify_server_properties]) { + auto value = node[TS_verify_server_properties].as(); + int properties = PROPERTIES_DESCRIPTOR.get(value); + if (properties < 0) { + throw std::runtime_error("unknown value \"" + value + "\""); } - item.verify_origin_server = static_cast(level); + item.verify_server_properties = static_cast(properties); } if (node[TS_client_cert]) { diff --git a/iocore/net/YamlSNIConfig.h b/iocore/net/YamlSNIConfig.h index cb57d5b7646..d89fe6f7b1c 100644 --- a/iocore/net/YamlSNIConfig.h +++ b/iocore/net/YamlSNIConfig.h @@ -26,25 +26,32 @@ #include "tsconfig/Errata.h" -constexpr char TS_fqdn[] = "fqdn"; -constexpr char TS_disable_H2[] = "disable_h2"; -constexpr char TS_verify_client[] = "verify_client"; -constexpr char TS_tunnel_route[] = "tunnel_route"; -constexpr char TS_verify_origin_server[] = "verify_origin_server"; -constexpr char TS_client_cert[] = "client_cert"; -constexpr char TS_ip_allow[] = "ip_allow"; +#define TSDECL(id) constexpr char TS_##id[] = #id +TSDECL(fqdn); +TSDECL(disable_H2); +TSDECL(verify_client); +TSDECL(tunnel_route); +TSDECL(verify_server_policy); +TSDECL(verify_server_properties); +TSDECL(verify_origin_server); +TSDECL(client_cert); +TSDECL(ip_allow); +#undef TSDECL const int start = 0; struct YamlSNIConfig { enum class Action { disable_h2 = start, verify_client, - tunnel_route, // blind tunnel action - verify_origin_server, // this applies to server side vc only + tunnel_route, // blind tunnel action + verify_server_policy, // this applies to server side vc only + verify_server_properties, // this applies to server side vc only client_cert }; enum class Level { NONE = 0, MODERATE, STRICT }; + enum class Policy : uint8_t { DISABLED = 0, PERMISSIVE, ENFORCED }; + enum class Property : uint8_t { NONE = 0, SIGNATURE_MASK = 0x1, NAME_MASK = 0x2, ALL_MASK = 0x3 }; YamlSNIConfig() {} @@ -53,7 +60,8 @@ struct YamlSNIConfig { bool disable_h2 = false; uint8_t verify_client_level = 0; std::string tunnel_destination; - uint8_t verify_origin_server = 0; + Policy verify_server_policy = Policy::DISABLED; + Property verify_server_properties = Property::NONE; std::string client_cert; std::string ip_allow; }; diff --git a/mgmt/RecordsConfig.cc b/mgmt/RecordsConfig.cc index 27a8108e6c0..ebb0b51909c 100644 --- a/mgmt/RecordsConfig.cc +++ b/mgmt/RecordsConfig.cc @@ -1130,6 +1130,10 @@ static const RecordElement RecordsConfig[] = , {RECT_CONFIG, "proxy.config.ssl.client.verify.server", RECD_INT, "0", RECU_DYNAMIC, RR_NULL, RECC_INT, "[0-2]", RECA_NULL} , + {RECT_CONFIG, "proxy.config.ssl.client.verify.server.policy", RECD_STRING, "NONE", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + , + {RECT_CONFIG, "proxy.config.ssl.client.verify.server.properties", RECD_STRING, "ALL", RECU_DYNAMIC, RR_NULL, RECC_NULL, nullptr, RECA_NULL} + , {RECT_CONFIG, "proxy.config.ssl.client.cert.filename", RECD_STRING, nullptr, RECU_RESTART_TS, RR_NULL, RECC_STR, "^[^[:space:]]*$", RECA_NULL} , {RECT_CONFIG, "proxy.config.ssl.client.cert.path", RECD_STRING, TS_BUILD_SYSCONFDIR, RECU_RESTART_TS, RR_NULL, RECC_NULL, nullptr, RECA_NULL} diff --git a/src/traffic_server/InkAPI.cc b/src/traffic_server/InkAPI.cc index bf61741519a..7513906eb49 100644 --- a/src/traffic_server/InkAPI.cc +++ b/src/traffic_server/InkAPI.cc @@ -8775,7 +8775,7 @@ class TSSslCallback : public Continuation public: TSSslCallback(SSLNetVConnection *vc) : Continuation(vc->nh->mutex), m_vc(vc) { SET_HANDLER(&TSSslCallback::event_handler); } int - event_handler(int, void *) + event_handler(int event, void *) { m_vc->reenable(m_vc->nh); delete this; diff --git a/tests/gold_tests/tls/ssl/signed-bar.key b/tests/gold_tests/tls/ssl/signed-bar.key new file mode 100644 index 00000000000..a95ccd619be --- /dev/null +++ b/tests/gold_tests/tls/ssl/signed-bar.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDuzA6e4MZp98m/ +XuhRAZMCaq9fM5zRBDsY5fpx3zUkJwJtZa4ALk6Adusovfh3t6qYJJ47TItnNG9Z +nAvYQhOccZNkj8xbPytuj5pQzu3CAR/IsBBWtG8O0SLRHNVOmgu3bdXuJca+3LKR +X3qFJbReqd9OI9vGxrxKg9NPUeGpzAuUTplmfs8O70g8l0ZBJ7l/0VmsA5lUDZxV +NjcacVYHc+ApujuLz5drVRKeLxTrtc6DksP7uruT5ZVrWbL35hoviwUilugz9ZDI +SQl0T6cIus8CyUjs8/iJEln9AnxAZ8Muz5+pQ3G/4BsabKlEHf0+GYinXxiTMT1V +Cr9botZ/AgMBAAECggEANwfhiq2kLAGFhcuaYCirt0/csGTVi7mc4OUG7T0SIw22 +Wn2nNrV1M9ez48S7wOMbtkoiCOpf6d3El3MFq8W2fUQTQoZ9Ar4xBR6k4mB9nErk +BzzD1ydnvJNnoacyZRXNA22VcndUMOHtaOEG/C4vPe2J35kV6d4cwFNW3B2zkoxY +VYyFZq+KdYgFixBQQ7kgMdUyPQiSmXsmfb5afXLUHWC6waeAwq6DYkz+UHt4fNhk +vzknjsvpCfRDzkIAuZABbG2s2QbnjZaPgE2k3Uj5+jMymfB3vKCY/URospWQlOoT +WbDsB5bQkwqjhp1zKyk47hFrzvsWSRxwbloHY/MhUQKBgQD9B8W6oAwQoLPKFK2J +ydt8ax5gx5Ew+Y6pxNDfajDa0KImVhrEWbHoKmso2o6QvIETQ4Ey1noEEZTJtuDA +9vDEC6nYRTly2VMmdEZ+vssNaPVQbGBbp6W6huKl85sU4g1J3auouyGXIGEMPwS5 +iQd+st0jzqlRp4eLBmJ4iDJnyQKBgQDxmYVhGjNUl4PehEthk/iXI2waGBSlGjUu +LhHoyUPcn7XOdzBMdgOdK7gwA9aa7SLFZJ12F/1gTVuY3LuLEnSiHvIE5qh0G7rj +2NRvKoLvPKkFebqU8PSU7o0Zkamo2zcGwQZOazpYKMGLWj7NQrNMvTMKGtoQJHNy +SiQI9TIABwKBgBJ4bsagyECuenFV8RUN1yfN6fnGl6KrlO5vn4+vgMF4WV3TC0Eq +CwKXlhr1WVLXb9SoKNY9Mcr6PZI790weupSVBWD0LK1lj9xOwJaf9tKTxtSIFMCc +DE0Ba6oRjlCH79BkjhNTFbCifHMYZo/koNdu1xW2EEYVpJ9RZ/7EcmmBAoGASKkB +QijdEy3WTQ/AlAIqm1nd4yMm4li1ccQNQtN1A19NEGEsN3Kut5A0fsxIuKNk97TA +3olsfJAHYjvQc40DYtantu2f7/t/A5NsoFpKsqStuKXZhX3KMRhlezEhs1Tqga9/ +tAnvrB/lxYFIrfbHcebc+McGmiA8UD0YBVGozfUCgYBxFvVUtzMgJ/ul/RGDDiEZ +Hijr7QqAqd9xEDBRjb3fuZUy7OLRHKTmLf5XQVmWXy37PCncoaD9Wb6Z+FNLvf+l +HXwRL9ZgY2KFVimbYcY2BHy0ojb4axUJDe78MAxFcnZDZMZ2W5XBzHWM3F54Hezc +I2ivPTm03ZFpA+8koiiqdw== +-----END PRIVATE KEY----- diff --git a/tests/gold_tests/tls/ssl/signed-bar.pem b/tests/gold_tests/tls/ssl/signed-bar.pem new file mode 100644 index 00000000000..e620980ed85 --- /dev/null +++ b/tests/gold_tests/tls/ssl/signed-bar.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDDTCCAnYCCQC81MtBCwmQuDANBgkqhkiG9w0BAQsFADCBnTELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh +aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u +ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j +b20wHhcNMTgxMDE1MTU1NzQxWhcNMjgxMDEyMTU1NzQxWjB0MQswCQYDVQQGEwJV +UzELMAkGA1UECAwCSUwxFDASBgNVBAcMC1NwcmluZ2ZpZWxkMRAwDgYDVQQKDAdF +eGFtcGxlMRAwDgYDVQQDDAdiYXIuY29tMR4wHAYJKoZIhvcNAQkBFg9ib2JAZXhh +bXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDuzA6e4MZp +98m/XuhRAZMCaq9fM5zRBDsY5fpx3zUkJwJtZa4ALk6Adusovfh3t6qYJJ47TItn +NG9ZnAvYQhOccZNkj8xbPytuj5pQzu3CAR/IsBBWtG8O0SLRHNVOmgu3bdXuJca+ +3LKRX3qFJbReqd9OI9vGxrxKg9NPUeGpzAuUTplmfs8O70g8l0ZBJ7l/0VmsA5lU +DZxVNjcacVYHc+ApujuLz5drVRKeLxTrtc6DksP7uruT5ZVrWbL35hoviwUilugz +9ZDISQl0T6cIus8CyUjs8/iJEln9AnxAZ8Muz5+pQ3G/4BsabKlEHf0+GYinXxiT +MT1VCr9botZ/AgMBAAEwDQYJKoZIhvcNAQELBQADgYEAo0i/UvFWEtNFLsNUcEmK +ZMOidghBaQV0c8pKxzlv3HsSqccMqkvBXmShzltI+YYABfqqZTTBLSQwdAwBp1cR +U3X5huPKN/6yk1p1KZaLasBAuxOiLPDvQY8djXXe+KSmIVeHqhTvC76SrkptPgm6 +yCX1PeYMHTv2P+0IZ3t/NW4= +-----END CERTIFICATE----- diff --git a/tests/gold_tests/tls/ssl/signed-foo.key b/tests/gold_tests/tls/ssl/signed-foo.key new file mode 100644 index 00000000000..e2c7066f679 --- /dev/null +++ b/tests/gold_tests/tls/ssl/signed-foo.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDJheOsr0o4C0QV +elo8viYl/IjWvkj4Y6YojnO/E9T5HSfWxkRikRT8X7yqs9ClrjNcYoPNNQP5vgl1 +qAIeixUrbZZklcZ3kHF/MXdzuYV//uT3YfWrsOTdfbcu6adHtBr/Qc0w9GSbBpp4 +2ZALxzjZ2hZZq51XmKvcz55/gm/9YvlGErzvsPzkejdH6U1GKeLqGaZOqkV7N2J4 +zKmJyiPzwrmR/8y7k+9jDHQX+A2wa5gaiAMGdIM8aTV+XsNNAvespvXyX7UhwxDs +w0er0GLv4ssYCru5hF+tUcjeOCHxSnCoEC45b2zDZHATLLjr7AIJ52TcSo1kTaTi +rAOAiHRLAgMBAAECggEAB7fXBnAYOZlE3EW5WwY1U9MeMotLJCg83uTFzhWmXHwf +YHxrdhL0aM4J3cfRP+cyFGG5hox3QINkvVrX6e+NugISdnu+BCpGDocIeigq0sIi +Zs8bp524xjrgXy2XuIlPV2NfxnY1vDI+jE5Y0/qnVMCjhn+qIQa53lUdTujh/SRR +3U7di+QMK4mdGwRnInos++ENy33A+2LqtUK8i0ERkzPFa1yMQEE4DOFPzZcW+jhK +arvzBwPIn37PZmL5oyiQB1YiGPGt4XNfPBwACTMYM8LlYBfEBHG77k3bMtUf0WqE +GctoT5SIe5+YbyrWkpfHgoKPxggH3I3TrFnVvqrKQQKBgQDmcV1YbuNEQLeif521 +iGqMgPQYmnpO6k27RsZrM9ikhIgm9bVJsOqnaYzQFeSfJ3eNLXYUL6IF8g46xddw +fDBtrEjDAA9OUkNRcizbeKF+GJRMtX11d4ZNbnG1wyMZYkArZGfraZBLHPEF1pya +2iFdVfokQCBpLmX7BMQEPePyuwKBgQDf33H9njf9oO0l9GfuWDvSoaV8GwqV9x55 +sFjggQYD/xqwEprrzr524X5Y2ZiTUpBu+kqqM8GYfm3bzBKkZU1rnjwxADUwBw8U +L2U/Z7Id3om8tAdzHOSI9d7mxWA8uTsScMm0IFv2l/XBQo1+AAJSD03pcsabr4Lf +SuJGmoFTsQKBgQDVzPASEC+DL5gwh75Gop5YZXwTJ5+6f+BGlM+avquNV/kKTIU6 +LY5IbMFcfjNzBicBMOCQsfDdG0rgdJYBovc7idCoOvH4dJJIimnb5fvPBfbxhKE1 +zwMn7ARL4xQ5hNKMb8eKvpJFXkCwbgE2GpNCCXbfEy/+5jFvx2gll1ZZ6QKBgG3J +OzJ/w796irHBQLKOzI+HvAq3jCJs9KICjCNUwql1EhZkmVqooZjVDkvuMbeVlsUF +s1XyWa852RAf7Mh38VakW6pACtVJsOhaMdG9PYkOWAeVVc3qzlwoDy6mfoJo6AIs +E45lDBRLAzbKN28h/AFYBgJEygcRNCHirEKphGCRAoGAEhcaxbmMo2fHBYuvOR1Q +ZAIq1EPvysDROUBHhdTJqN1wHsuJsmVJxX42+YHcZdjtgeCdjU3HMoyCnTaRxDee +K3VeB4PobN1WpQwFklFoqcvAhW6eicdZXme7ktK120NPQsXrmjgN6Lfg3PNjosn0 +tqSxQhQ4DrSf60fxx0/M/rw= +-----END PRIVATE KEY----- diff --git a/tests/gold_tests/tls/ssl/signed-foo.pem b/tests/gold_tests/tls/ssl/signed-foo.pem new file mode 100644 index 00000000000..6f6aecf53d7 --- /dev/null +++ b/tests/gold_tests/tls/ssl/signed-foo.pem @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCzCCAnQCCQC81MtBCwmQtzANBgkqhkiG9w0BAQsFADCBnTELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh +aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u +ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j +b20wHhcNMTgxMDE1MTU1NjMzWhcNMjgxMDEyMTU1NjMzWjByMQswCQYDVQQGEwJV +UzELMAkGA1UECAwCSUwxEjAQBgNVBAcMCUNoYW1wYWlnbjEQMA4GA1UECgwHRXhh +bXBsZTEQMA4GA1UEAwwHZm9vLmNvbTEeMBwGCSqGSIb3DQEJARYPYm9iQGV4YW1w +bGUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyYXjrK9KOAtE +FXpaPL4mJfyI1r5I+GOmKI5zvxPU+R0n1sZEYpEU/F+8qrPQpa4zXGKDzTUD+b4J +dagCHosVK22WZJXGd5BxfzF3c7mFf/7k92H1q7Dk3X23LumnR7Qa/0HNMPRkmwaa +eNmQC8c42doWWaudV5ir3M+ef4Jv/WL5RhK877D85Ho3R+lNRini6hmmTqpFezdi +eMypicoj88K5kf/Mu5PvYwx0F/gNsGuYGogDBnSDPGk1fl7DTQL3rKb18l+1IcMQ +7MNHq9Bi7+LLGAq7uYRfrVHI3jgh8UpwqBAuOW9sw2RwEyy46+wCCedk3EqNZE2k +4qwDgIh0SwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBALr2gm+KgveEcTXwURM0wxJC +m0yOR8w6MX8fxHKaekhJH1U84G64Ub0gbn2beOdLBQkG+4czLiOOOgyeukPaJJ81 +od2ooE7DrGUPGnbHYxW/70EtVF5nQEctcqpKNF/d04mVKrqI90919MJSxJ5KedHK +2H11+gUPwDWy/mAwJzEJ +-----END CERTIFICATE----- diff --git a/tests/gold_tests/tls/ssl/signer.key b/tests/gold_tests/tls/ssl/signer.key new file mode 100644 index 00000000000..4c7a661a6bd --- /dev/null +++ b/tests/gold_tests/tls/ssl/signer.key @@ -0,0 +1,15 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDWMHOiUF+ORmZjAxI8MWE9dblb7gQSJ36WCXlPFiFx6ynF+S1E +kXAYpIip5X0pzDUaIbLukxJUAAnOtMEO0PCgxJQUrEtRWh8wiJdbdQJF0Zs/9R+u +SUgb61f+mdTQvhqefBGx+xrpfAcgtcWiZuSA9Q3fvpDj5WOWSPWXBUuxywIDAQAB +AoGBAJPxRX2gjFAGWmQbU/YVmXfNH6navh8X/nx9sLeqrpE0AFeJI/ZPiqDKzMal +B43eSfNxwVi+ZxN0L1ICUbL9KKZvHs/QBxWLA1fGVAXrz7sRplEVvakPpTfHoEnv +sKaMWVKaK/S5WGbDhElb6zb/Lwo19DsIAPjGYqFvzFJBmobJAkEA9iSeTGkR9X26 +GywZoYrIMlRh34htOIRx1UUq88rFzdrCF21kQ4lhBIkX5OZMMy652i2gyak4OZTe +YewIv8jw9QJBAN7EQNHG8jPwXfVp91/fqxVQEfumuP2i6uiWWYQgZCmla2+0xcLZ +pMQ6sQEe10hhTrVnzHgAUVp50Ntn2jwBX78CQF09veGAI9d1Cxzj9cmmAvRd1r2Q +tp8kPOLnUsALXib+6WtqewLCdcf8DtsdClyRJMIraq85tRzK8fryKNZNzkkCQEgA +yS7FDj5JgCU15hZgFk1iPx3HCt44jZM2HaL+UUHAzRQjKxTLAl3G1rWVAWLMyQML +lORoveLvotl4HOruSsMCQQCAx9dV9JUSFoyc1CWILp/FgUH/se4cjQCThGO0DoQQ +vGTYmntY7j9WRJ9esQrjdD6Clw8zM/45GIBNwnXzqo7Z +-----END RSA PRIVATE KEY----- diff --git a/tests/gold_tests/tls/ssl/signer.pem b/tests/gold_tests/tls/ssl/signer.pem new file mode 100644 index 00000000000..58b9b9715b7 --- /dev/null +++ b/tests/gold_tests/tls/ssl/signer.pem @@ -0,0 +1,32 @@ +-----BEGIN RSA PRIVATE KEY----- +MIICXQIBAAKBgQDWMHOiUF+ORmZjAxI8MWE9dblb7gQSJ36WCXlPFiFx6ynF+S1E +kXAYpIip5X0pzDUaIbLukxJUAAnOtMEO0PCgxJQUrEtRWh8wiJdbdQJF0Zs/9R+u +SUgb61f+mdTQvhqefBGx+xrpfAcgtcWiZuSA9Q3fvpDj5WOWSPWXBUuxywIDAQAB +AoGBAJPxRX2gjFAGWmQbU/YVmXfNH6navh8X/nx9sLeqrpE0AFeJI/ZPiqDKzMal +B43eSfNxwVi+ZxN0L1ICUbL9KKZvHs/QBxWLA1fGVAXrz7sRplEVvakPpTfHoEnv +sKaMWVKaK/S5WGbDhElb6zb/Lwo19DsIAPjGYqFvzFJBmobJAkEA9iSeTGkR9X26 +GywZoYrIMlRh34htOIRx1UUq88rFzdrCF21kQ4lhBIkX5OZMMy652i2gyak4OZTe +YewIv8jw9QJBAN7EQNHG8jPwXfVp91/fqxVQEfumuP2i6uiWWYQgZCmla2+0xcLZ +pMQ6sQEe10hhTrVnzHgAUVp50Ntn2jwBX78CQF09veGAI9d1Cxzj9cmmAvRd1r2Q +tp8kPOLnUsALXib+6WtqewLCdcf8DtsdClyRJMIraq85tRzK8fryKNZNzkkCQEgA +yS7FDj5JgCU15hZgFk1iPx3HCt44jZM2HaL+UUHAzRQjKxTLAl3G1rWVAWLMyQML +lORoveLvotl4HOruSsMCQQCAx9dV9JUSFoyc1CWILp/FgUH/se4cjQCThGO0DoQQ +vGTYmntY7j9WRJ9esQrjdD6Clw8zM/45GIBNwnXzqo7Z +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIICszCCAhwCCQD4jSkztmlO1TANBgkqhkiG9w0BAQsFADCBnTELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh +aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u +ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j +b20wHhcNMTcwODI4MDM0NDQ1WhcNMjcwODI2MDM0NDQ1WjCBnTELMAkGA1UEBhMC +VVMxCzAJBgNVBAgTAklMMRIwEAYDVQQHEwlDaGFtcGFpZ24xDjAMBgNVBAoTBVlh +aG9vMQ0wCwYDVQQLEwRFZGdlMSgwJgYDVQQDEx9qdWljZXByb2R1Y2UuY29ycC5u +ZTEueWFob28uY29tMSQwIgYJKoZIhvcNAQkBFhVwZXJzaWEuYXppekB5YWhvby5j +b20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYwc6JQX45GZmMDEjwxYT11 +uVvuBBInfpYJeU8WIXHrKcX5LUSRcBikiKnlfSnMNRohsu6TElQACc60wQ7Q8KDE +lBSsS1FaHzCIl1t1AkXRmz/1H65JSBvrV/6Z1NC+Gp58EbH7Gul8ByC1xaJm5ID1 +Dd++kOPlY5ZI9ZcFS7HLAgMBAAEwDQYJKoZIhvcNAQELBQADgYEATX7975NdhIbJ +glda+sXI9a86GgOpiuKO+vKubRJQZA+UlPf2vHEONjC2+7Y1aZvZYaKYL74vxGky +zkgp6ANSPl45lqD632x0e1Z7vzW5TkqK1JB2/xH2WgDcQZmP0FuQHzVNs4GjghDr +HCp1+sQDhfPB4aLmLFeyN0TkhdH1N3M= +-----END CERTIFICATE----- diff --git a/tests/gold_tests/tls/tls_verify.test.py b/tests/gold_tests/tls/tls_verify.test.py new file mode 100644 index 00000000000..01d983fa624 --- /dev/null +++ b/tests/gold_tests/tls/tls_verify.test.py @@ -0,0 +1,137 @@ +''' +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +Test.Summary = ''' +Test tls server certificate verification options +''' + +# need Curl +Test.SkipUnless( + Condition.HasProgram("curl", "Curl need to be installed on system for this test to work") +) + +# Define default ATS +ts = Test.MakeATSProcess("ts", select_ports=False) +server_foo = Test.MakeOriginServer("server_foo", ssl=True, options = {"--key": "{0}/signed-foo.key".format(Test.RunDirectory), "--cert": "{0}/signed-foo.pem".format(Test.RunDirectory)}) +server_bar = Test.MakeOriginServer("server_bar", ssl=True, options = {"--key": "{0}/signed-bar.key".format(Test.RunDirectory), "--cert": "{0}/signed-bar.pem".format(Test.RunDirectory)}) +server = Test.MakeOriginServer("server", ssl=True) + +request_foo_header = {"headers": "GET / HTTP/1.1\r\nHost: foo.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +request_bad_foo_header = {"headers": "GET / HTTP/1.1\r\nHost: badfoo.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +request_bar_header = {"headers": "GET / HTTP/1.1\r\nHost: bar.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +request_bad_bar_header = {"headers": "GET / HTTP/1.1\r\nHost: badbar.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +server_foo.addResponse("sessionlog.json", request_foo_header, response_header) +server_foo.addResponse("sessionlog.json", request_bad_foo_header, response_header) +server_bar.addResponse("sessionlog.json", request_bar_header, response_header) +server_bar.addResponse("sessionlog.json", request_bad_bar_header, response_header) + +# add ssl materials like key, certificates for the server +ts.addSSLfile("ssl/signed-foo.pem") +ts.addSSLfile("ssl/signed-foo.key") +ts.addSSLfile("ssl/signed-bar.pem") +ts.addSSLfile("ssl/signed-bar.key") +ts.addSSLfile("ssl/server.pem") +ts.addSSLfile("ssl/server.key") +ts.addSSLfile("ssl/signer.pem") +ts.addSSLfile("ssl/signer.key") + +ts.Variables.ssl_port = 4443 +ts.Disk.remap_config.AddLine( + 'map / https://127.0.0.1:{0}'.format(server.Variables.Port)) +ts.Disk.remap_config.AddLine( + 'map https://foo.com/ https://127.0.0.1:{0}'.format(server_foo.Variables.Port)) +ts.Disk.remap_config.AddLine( + 'map https://bad_foo.com/ https://127.0.0.1:{0}'.format(server_foo.Variables.Port)) +ts.Disk.remap_config.AddLine( + 'map https://bar.com/ https://127.0.0.1:{0}'.format(server_bar.Variables.Port)) +ts.Disk.remap_config.AddLine( + 'map https://bad_bar.com/ https://127.0.0.1:{0}'.format(server_bar.Variables.Port)) + +ts.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) + +# Case 1, global config policy=permissive properties=signature +# override for foo.com policy=enforced properties=all +ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'http|ssl', + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), + # enable ssl port + 'proxy.config.http.server_ports': '{0} {1}:proto=http2;http:ssl'.format(ts.Variables.port, ts.Variables.ssl_port), + 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', + # set global policy + 'proxy.config.ssl.client.verify.server.policy': 'PERMISSIVE', + 'proxy.config.ssl.client.verify.server.properties': 'SIGNATURE', + 'proxy.config.ssl.client.CA.cert.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.client.CA.cert.filename': 'signer.pem', + 'proxy.config.url_remap.pristine_host_hdr': 1 +}) + +ts.Disk.ssl_server_name_yaml.AddLine( + '- fqdn: bar.com') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_policy: ENFORCED') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_properties: ALL') +ts.Disk.ssl_server_name_yaml.AddLine( + '- fqdn: bad_bar.com') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_policy: ENFORCED') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_properties: ALL') + +tr = Test.AddTestRun("Permissive-Test") +tr.Setup.Copy("ssl/signed-foo.key") +tr.Setup.Copy("ssl/signed-foo.pem") +tr.Setup.Copy("ssl/signed-bar.key") +tr.Setup.Copy("ssl/signed-bar.pem") +tr.Processes.Default.Command = "curl -k -H \"host: foo.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr.ReturnCode = 0 +# time delay as proxy.config.http.wait_for_cache could be broken +tr.Processes.Default.StartBefore(server_foo) +tr.Processes.Default.StartBefore(server_bar) +tr.Processes.Default.StartBefore(server) +tr.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(ts.Variables.ssl_port)) +tr.StillRunningAfter = server +tr.StillRunningAfter = ts +tr.Processes.Default.TimeOut = 5 +tr.TimeOut = 5 + +tr2 = Test.AddTestRun("Override-enforcing-Test") +tr2.Processes.Default.Command = "curl -k -H \"host: bar.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr2.ReturnCode = 0 +tr2.StillRunningAfter = server +tr2.Processes.Default.TimeOut = 5 +tr2.StillRunningAfter = ts +tr2.TimeOut = 5 + +tr3 = Test.AddTestRun("Override-enforcing-Test-fail-name-check") +tr3.Processes.Default.Command = "curl -k -H \"host: bad_bar.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr3.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Curl attempt should have failed") +tr3.ReturnCode = 0 +tr3.StillRunningAfter = server +tr3.StillRunningAfter = ts +tr3.Processes.Default.TimeOut = 5 + +# Over riding the built in ERROR check since we expect tr3 to fail +ts.Disk.diags_log.Content = Testers.ExcludesExpression("verification failed", "Make sure the signatures didn't fail") +ts.Disk.diags_log.Content += Testers.ContainsExpression("WARNING: SNI \(bad_bar.com\) not in certificate", "Make sure bad_bar name checked failed.") diff --git a/tests/gold_tests/tls/tls_verify2.test.py b/tests/gold_tests/tls/tls_verify2.test.py new file mode 100644 index 00000000000..b7e730af4ac --- /dev/null +++ b/tests/gold_tests/tls/tls_verify2.test.py @@ -0,0 +1,171 @@ +''' +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +Test.Summary = ''' +Test tls server certificate verification options +''' + +# need Curl +Test.SkipUnless( + Condition.HasProgram("curl", "Curl need to be installed on system for this test to work") +) + +# Define default ATS +ts = Test.MakeATSProcess("ts", select_ports=False) +server_foo = Test.MakeOriginServer("server_foo", ssl=True, options = {"--key": "{0}/signed-foo.key".format(Test.RunDirectory), "--cert": "{0}/signed-foo.pem".format(Test.RunDirectory)}) +server_bar = Test.MakeOriginServer("server_bar", ssl=True, options = {"--key": "{0}/signed-bar.key".format(Test.RunDirectory), "--cert": "{0}/signed-bar.pem".format(Test.RunDirectory)}) +server = Test.MakeOriginServer("server", ssl=True) + +request_foo_header = {"headers": "GET / HTTP/1.1\r\nHost: foo.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +request_bad_foo_header = {"headers": "GET / HTTP/1.1\r\nHost: bad_foo.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +request_bar_header = {"headers": "GET / HTTP/1.1\r\nHost: bar.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +request_bad_bar_header = {"headers": "GET / HTTP/1.1\r\nHost: bad_bar.com\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +response_header = {"headers": "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n", "timestamp": "1469733493.993", "body": ""} +server_foo.addResponse("sessionlog.json", request_foo_header, response_header) +server_foo.addResponse("sessionlog.json", request_bad_foo_header, response_header) +server_bar.addResponse("sessionlog.json", request_bar_header, response_header) +server_bar.addResponse("sessionlog.json", request_bad_bar_header, response_header) + +# add ssl materials like key, certificates for the server +ts.addSSLfile("ssl/signed-foo.pem") +ts.addSSLfile("ssl/signed-foo.key") +ts.addSSLfile("ssl/signed-bar.pem") +ts.addSSLfile("ssl/signed-bar.key") +ts.addSSLfile("ssl/server.pem") +ts.addSSLfile("ssl/server.key") +ts.addSSLfile("ssl/signer.pem") +ts.addSSLfile("ssl/signer.key") + +ts.Variables.ssl_port = 4443 +ts.Disk.remap_config.AddLine( + 'map / https://127.0.0.1:{0}'.format(server.Variables.Port)) +ts.Disk.remap_config.AddLine( + 'map https://foo.com/ https://127.0.0.1:{0}'.format(server_foo.Variables.Port)) +ts.Disk.remap_config.AddLine( + 'map https://bad_foo.com/ https://127.0.0.1:{0}'.format(server_foo.Variables.Port)) +ts.Disk.remap_config.AddLine( + 'map https://bar.com/ https://127.0.0.1:{0}'.format(server_bar.Variables.Port)) +ts.Disk.remap_config.AddLine( + 'map https://bad_bar.com/ https://127.0.0.1:{0}'.format(server_bar.Variables.Port)) + +ts.Disk.ssl_multicert_config.AddLine( + 'dest_ip=* ssl_cert_name=server.pem ssl_key_name=server.key' +) + +# Case 1, global config policy=permissive properties=signature +# override for foo.com policy=enforced properties=all +ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'http|ssl', + 'proxy.config.ssl.server.cert.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.server.private_key.path': '{0}'.format(ts.Variables.SSLDir), + # enable ssl port + 'proxy.config.http.server_ports': '{0} {1}:proto=http2;http:ssl'.format(ts.Variables.port, ts.Variables.ssl_port), + 'proxy.config.ssl.server.cipher_suite': 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RC4-SHA:RC4-MD5:AES128-SHA:AES256-SHA:DES-CBC3-SHA!SRP:!DSS:!PSK:!aNULL:!eNULL:!SSLv2', + # set global policy + 'proxy.config.ssl.client.verify.server.policy': 'ENFORCED', + 'proxy.config.ssl.client.verify.server.properties': 'ALL', + 'proxy.config.ssl.client.CA.cert.path': '{0}'.format(ts.Variables.SSLDir), + 'proxy.config.ssl.client.CA.cert.filename': 'signer.pem', + 'proxy.config.url_remap.pristine_host_hdr': 1 +}) + +ts.Disk.ssl_server_name_yaml.AddLine( + '- fqdn: bar.com') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_policy: PERMISSIVE') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_properties: SIGNATURE') +ts.Disk.ssl_server_name_yaml.AddLine( + '- fqdn: bad_bar.com') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_policy: PERMISSIVE') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_properties: SIGNATURE') +ts.Disk.ssl_server_name_yaml.AddLine( + '- fqdn: random.com') +ts.Disk.ssl_server_name_yaml.AddLine( + ' verify_server_policy: DISABLED') + +tr = Test.AddTestRun("default-enforce") +tr.Setup.Copy("ssl/signed-foo.key") +tr.Setup.Copy("ssl/signed-foo.pem") +tr.Setup.Copy("ssl/signed-bar.key") +tr.Setup.Copy("ssl/signed-bar.pem") +tr.Processes.Default.Command = "curl -k -H \"host: foo.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr.ReturnCode = 0 +# time delay as proxy.config.http.wait_for_cache could be broken +tr.Processes.Default.StartBefore(server_foo) +tr.Processes.Default.StartBefore(server_bar) +tr.Processes.Default.StartBefore(server) +tr.Processes.Default.StartBefore(Test.Processes.ts, ready=When.PortOpen(ts.Variables.ssl_port)) +tr.StillRunningAfter = server +tr.StillRunningAfter = ts +tr.Processes.Default.TimeOut = 5 +tr.TimeOut = 5 + +tr2 = Test.AddTestRun("override-disabled") +tr2.Processes.Default.Command = "curl -k -H \"host: random.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr2.ReturnCode = 0 +tr2.StillRunningAfter = server +tr2.Processes.Default.TimeOut = 5 +tr2.StillRunningAfter = ts +tr2.TimeOut = 5 + +tr3 = Test.AddTestRun("override-permissive") +tr3.Processes.Default.Command = "curl -k -H \"host: bar.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr3.ReturnCode = 0 +tr3.StillRunningAfter = server +tr3.StillRunningAfter = ts +tr3.Processes.Default.TimeOut = 5 + +tr4 = Test.AddTestRun("override-permissive-bad-name") +tr4.Processes.Default.Command = "curl -k -H \"host: bad_bar.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr4.ReturnCode = 0 +tr4.StillRunningAfter = server +tr4.StillRunningAfter = ts +tr4.Processes.Default.TimeOut = 5 + +tr5 = Test.AddTestRun("override-permissive-bad-sig") +tr5.Processes.Default.Command = "curl -k -H \"host: random2.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr5.ReturnCode = 0 +tr5.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Curl attempt should have failed") +tr5.StillRunningAfter = server +tr5.StillRunningAfter = ts +tr5.Processes.Default.TimeOut = 5 + +tr6 = Test.AddTestRun("default-enforce-fail") +tr6.Processes.Default.Command = "curl -k -H \"host: bad_foo.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port) +tr6.ReturnCode = 0 +tr6.Processes.Default.Streams.stdout = Testers.ContainsExpression("Could Not Connect", "Curl attempt should have failed") +tr6.StillRunningAfter = server +tr6.StillRunningAfter = ts +tr6.Processes.Default.TimeOut = 5 + + +# Over riding the built in ERROR check since we expect tr4 and tr7 to fail +# No name checking for the sig-only permissive override for bad_bar +ts.Disk.diags_log.Content = Testers.ExcludesExpression("WARNING: SNI \(bad_bar.com\) not in certificate", "bad_bar name checked should be skipped.") +# No checking for the self-signed on random.com. No messages +ts.Disk.diags_log.Content += Testers.ExcludesExpression("WARNING: Core server certificate verification failed for \(random.com\)", "signature check for random.com should be skipped") +ts.Disk.diags_log.Content += Testers.ExcludesExpression("ERROR: SSL connection failed for 'random.com'", "random.com should not fail") +ts.Disk.diags_log.Content += Testers.ContainsExpression("ERROR: SSL connection failed for 'random2.com'", "random2.com should fail") +ts.Disk.diags_log.Content += Testers.ContainsExpression("WARNING: Core server certificate verification failed for \(random2.com\)", "signature check for random.com should fail'") +ts.Disk.diags_log.Content += Testers.ContainsExpression("WARNING: SNI \(bad_foo.com\) not in certificate", "bad_foo name checked should be checked.") +ts.Disk.diags_log.Content += Testers.ContainsExpression("ERROR: SSL connection failed for 'bad_foo.com'", "bad_foo.com should fail")