Strip trailing dot from FQDNs in Host and TLS#7364
Strip trailing dot from FQDNs in Host and TLS#7364webknjaz merged 17 commits intoaio-libs:masterfrom
Conversation
The TLS verification fails with an exception if the client uses a fully-qualified domain name with a trailing dot, like https://github.com./ : aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host github.com.:443 ssl:True [SSLCertVerificationError: (1, "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'github.com.'. (_ssl.c:1051)")] The reason is that TLS certificates do not contain the trailing dot, as per RFC 6066: "HostName" contains the fully qualified DNS hostname of the server, as understood by the client. The hostname is represented as a byte string using ASCII encoding without a trailing dot. We need to strip the trailing dot for TLS context and Host header, where trailing dots are not present. For DNS resolution, we need to include the trailing dot as it signifies a fully-qualified domain name (FQDN). DNS lookups of FQDNs are faster as the resolver does not need to check DNS search path, like for relative DNS names. Closes aio-libs#3636
|
I tried looking into adding a test for this but it was not clear to me if there is some test I could easily modify to check. Please advise what is the best way to write a test for this. |
The colon was a typo.
I'd assume tests in test_client_request.py and test_connector.py could be added that atleast asserts that something is called with the truncated domain? |
Codecov Report
@@ Coverage Diff @@
## master #7364 +/- ##
==========================================
- Coverage 97.35% 97.35% -0.01%
==========================================
Files 106 106
Lines 31490 31513 +23
Branches 3577 3589 +12
==========================================
+ Hits 30657 30679 +22
Misses 630 630
- Partials 203 204 +1
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 10 files with indirect coverage changes 📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more |
You'll probably want to use these fixtures https://github.com/aio-libs/aiohttp/blob/7911f1e/tests/conftest.py#L50-L61 to test that this patch works well with TLS. |
Co-authored-by: Sviatoslav Sydorenko <[email protected]>
|
Thank you for the review. I've applied the suggestions and added tests. |
|
@martin-sucha hey, it looks like some linting checks are failing. Could you fix those so we could proceed? |
Co-authored-by: Sviatoslav Sydorenko <[email protected]>
Co-authored-by: Sviatoslav Sydorenko <[email protected]>
Co-authored-by: Sviatoslav Sydorenko <[email protected]>
|
@martin-sucha There's a black formatting error (I'd update it myself, but you've disabled maintainer access to your branch). |
Oops. Fixed. |
webknjaz
left a comment
There was a problem hiding this comment.
Love it! Thanks for working on this! I think it's ready now.
|
@martin-sucha looks like there are some legitimate failures in the CI, could you take a look? |
On macOS the real resolver returns NXDOMAIN for something.localhost, so we need to use a mock resolver to ensure that the loopback IP is always used.
Head branch was pushed to by a user without write access
|
@webknjaz Seems that on macOS the resolver won't resolve |
|
@martin-sucha thank you! I've enabled auto-merge and there's a backporting bot label. If it fails to produce a backport PR, please, follow the instructions to do this manually. |
|
RTD build was stuck for some reason. I restarted it so GH could perform merging. |
Backport to 3.9: 💔 cherry-picking failed — conflicts found❌ Failed to cleanly apply d84fcf7 on top of patchback/backports/3.9/d84fcf7c52e7f44b81aae24dc2a7ad2bccc76c9b/pr-7364 Backporting merged PR #7364 into master
🤖 @patchback |
Before this patch, the TLS verification fails with an exception if the client uses a fully-qualified domain name with a trailing dot, like https://github.com./ : ```console aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host github.com.:443 ssl:True [SSLCertVerificationError: (1, "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'github.com.'. (_ssl.c:1051)")] ``` The reason is that TLS certificates do not contain the trailing dot, as per RFC 6066: "HostName" contains the fully qualified DNS hostname of the server, as understood by the client. The hostname is represented as a byte string using ASCII encoding without a trailing dot. This change makes aiohttp strip the trailing dot for TLS context and Host header, where trailing dots are not present. For DNS resolution, we include the trailing dot as it signifies a fully-qualified domain name (FQDN). DNS lookups of FQDNs are faster as the resolver does not need to check DNS search path, like for relative DNS names. This effectively allows clients to connect to server if URL has dot at the end of the hostname, e.g. `https://example.com./. Fixes aio-libs#3636 PR aio-libs#7364 Co-authored-by: Sviatoslav Sydorenko <[email protected]> (cherry picked from commit d84fcf7)
Before this patch, the TLS verification fails with an exception if the client uses a fully-qualified domain name with a trailing dot, like https://github.com./ : ```console aiohttp.client_exceptions.ClientConnectorCertificateError: Cannot connect to host github.com.:443 ssl:True [SSLCertVerificationError: (1, "[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'github.com.'. (_ssl.c:1051)")] ``` The reason is that TLS certificates do not contain the trailing dot, as per RFC 6066: "HostName" contains the fully qualified DNS hostname of the server, as understood by the client. The hostname is represented as a byte string using ASCII encoding without a trailing dot. This change makes aiohttp strip the trailing dot for TLS context and Host header, where trailing dots are not present. For DNS resolution, we include the trailing dot as it signifies a fully-qualified domain name (FQDN). DNS lookups of FQDNs are faster as the resolver does not need to check DNS search path, like for relative DNS names. This effectively allows clients to connect to server if URL has dot at the end of the hostname, e.g. `https://example.com./. Fixes #3636 PR #7364 Co-authored-by: Sviatoslav Sydorenko <[email protected]> (cherry picked from commit d84fcf7) <!-- Thank you for your contribution! --> ## What do these changes do? Backport #7364 into 3.9 <!-- Please give a short brief about these changes. --> ## Are there changes in behavior for the user? <!-- Outline any notable behaviour for the end users. --> ## Related issue number <!-- Are there any issues opened that will be resolved by merging this change? --> ## Checklist - [ ] I think the code is well written - [ ] Unit tests for the changes exist - [ ] Documentation reflects the changes - [ ] If you provide code modification, please add yourself to `CONTRIBUTORS.txt` * The format is <Name> <Surname>. * Please keep alphabetical order, the file is sorted by names. - [ ] Add a new news fragment into the `CHANGES` folder * name it `<issue_id>.<type>` for example (588.bugfix) * if you don't have an `issue_id` change it to the pr id after creating the pr * ensure type is one of the following: * `.feature`: Signifying a new feature. * `.bugfix`: Signifying a bug fix. * `.doc`: Signifying a documentation improvement. * `.removal`: Signifying a deprecation or removal of public API. * `.misc`: A ticket has been closed, but it is not of interest to users. * Make sure to use full sentences with correct case and punctuation, for example: "Fix issue with non-ascii contents in doctest text files."
The TLS verification fails with an exception if the client uses a fully-qualified domain name with a trailing dot, like https://github.com./ :
The reason is that TLS certificates do not contain the trailing dot, as per RFC 6066:
"HostName" contains the fully qualified DNS hostname of the server,
as understood by the client. The hostname is represented as a byte
string using ASCII encoding without a trailing dot.
We need to strip the trailing dot for TLS context and Host header, where trailing dots are not present.
For DNS resolution, we need to include the trailing dot as it signifies a fully-qualified domain name (FQDN).
DNS lookups of FQDNs are faster as the resolver does not need to check DNS search path, like for relative DNS names.
Closes #3636
What do these changes do?
Strip trailing dot from hostname in Host header and TLS context.
Are there changes in behavior for the user?
Allows client to connect to server if URL has dot at the end of the hostname:
https://example.com./Related issue number
#3636
Checklist
CONTRIBUTORS.txtCHANGESfolder<issue_id>.<type>for example (588.bugfix)issue_idchange it to the pr id after creating the pr.feature: Signifying a new feature..bugfix: Signifying a bug fix..doc: Signifying a documentation improvement..removal: Signifying a deprecation or removal of public API..misc: A ticket has been closed, but it is not of interest to users.