Conversation
There was a problem hiding this comment.
Copilot reviewed 6 out of 9 changed files in this pull request and generated 2 comments.
Files not reviewed (3)
- doc/man1/openssl-cmp.pod.in: Language not supported
- doc/man3/SSL_CTX_set_tlsext_servername_callback.pod: Language not supported
- doc/man3/X509_VERIFY_PARAM_set_flags.pod: Language not supported
Comments suppressed due to low confidence (1)
apps/cmp.c:1520
- According to the PR description, the '-tls_host' option should take precedence over the URL hostname; however, this call uses 'host' instead of checking if '-tls_host' is provided. Consider revisiting this logic to ensure the precedence is properly enforced.
if (!truststore_set_host_etc(trust_store, host))
6b70f7a to
2013643
Compare
|
BTW, since doing the SNI and hostname/address checks is important for correct and secure TLS connections, |
574a9c5 to
a8184c1
Compare
|
This needs a rebase due to conflicts. |
0e1d7c0 to
cdd9fb1
Compare
Done. |
cdd9fb1 to
d25895d
Compare
|
This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago |
vdukhovni
left a comment
There was a problem hiding this comment.
Please fix at least the "is IP address" test.
|
When aligning this PR with a related one in a different project, In retrospect, it would have been better if So I had to push an extension of |
035d24c to
466239e
Compare
esyr
left a comment
There was a problem hiding this comment.
Generally looks good, the only blocker is UB.
466239e to
6bb0219
Compare
…sext_host_name(); update format
Add recommendation to use it for TLS clients, together with X509_VERIFY_PARAM_{set1,add1}_host()
…RIFY_PARAM_set1_host()
…f OSSL_HTTP_REQ_CTX_set_expected()
| return bio; | ||
|
|
||
| err: | ||
| BIO_free(sbio); |
There was a problem hiding this comment.
Is it safe to free the BIO here if the SSL object has it set above?
There was a problem hiding this comment.
I'd say yes, it should be safe because
- the
BIO_set_ssl(sbio, ssl, BIO_CLOSE)call transfers the ownership ofssltosbio, and - in the
errbranch,BIO_free(sbio)freessslalong withsbio.
Both of which (as often, unfortunately) is not documented.
There was a problem hiding this comment.
wait, I had this backwards (I had thought the call to BIO_set_ssl was actuall a call to SSL_set_bio). But, given that, if BIO_set_ssl fails/returns 0, then don't we leak the ssl we just created? I grant thats going to be an unlikely event (it can happen if ssl_new or BIO_up_ref fails).
It looks like thats actually a pretty consistent pattern in uses of BIO_set_ssl.
There was a problem hiding this comment.
sorry, I forgot to submit my last round of reviews. As noted above, I had the problem backwards. You're right in that BIO_free will free the SSL, but if BIO_set_ssl fails, we will leak the allocated SSL. not sure how big a deal that is (it seems to be a fairly common pattern), but it definately looks like a leak problem.
There was a problem hiding this comment.
Now I see what you mean: what happens if the BIO_set_ssl() call fails?
I just had a closer look at BIO_set_ssl() and found that there is one case where ssl_ctrl() in ssl/bio_ssl.c returns 0 after transferring ownership (via bs->ssl = ssl), namely if BIO_up_ref(bio)) fails, which is very unlikely but possible.
Still, so far one cannot fully rely on the ownership transfer to happen if and only if BIO_set_ssl() succeeds,
so calling it, one either risks a mem leak (if ignoring its negative result) or a double free (if deallocating ssl on its failure).
To fully solve this, I now deallocate ssl in case BIO_set_ssl() fails
while adding a little bugfix commit that
- makes sure that
BIO_set_ssl()transfers ownership ofsslonly on success, and - documents this
There was a problem hiding this comment.
I guess you and Neil have just opened a can of worms: if I'm not mistaken, failing
ssl_new()(due to failingOPENSSL_zalloc) afterssl_freewould lead toBIO_SSLdouble-free, asb->ptris not reset toNULLafterOPENSSL_freecall inssl_free, and the latter would be called the second time in [1].
@esyr which b->ptr in which function context do you mean here?
Since I've changed ssl_ctrl() to set bs->ssl only at the end on success,
and as I call SSL_free(ssl) only on failure, I do not see that I introduced potential for double-free.
Which does not preclude that the wonderful code in bio_lib.c bears other potential for double-free,
but that's unrelated to this PR.
There was a problem hiding this comment.
I think what @esyr is getting at is the following set of conditions:
- BIO_set_ssl is called
- In ssl_ctrl, we fall into the BIO_C_SET_SSL case
- ssl_free is called on the passed bio b
- ssl_free(b) is called
- ssl_free calls BIO_get_data to get the data bio (bs)
- SSL_free(bs->ssl) is called
- OPENSSL_free(bs) is called. Critically the BIO data pointer remains pointed to bs (from (5)) which is now no longer valid
- back in ssl_ctrl, ssl_new is called, which we assume fails on a malloc failure, meaning a new bs is not allocated
- ssl_ctrl returns with an error code and the BIOS bs/data pointer still pointing to invalid memory (due to the free in (7)
- your code above detects the error, frees the previously leaked SSL (so you've fixed that and jumps to err:
- at the err label BIO_free is called
- BIO_free calls ssl_free, which calls BIO_get_data to get bs again, which is non-null but invalid.
- we try to call OPENSSL_free again on bs, which results in a double free.
If thats the case it seems like the best solution here is to call BIO_set_data(b, NULL) in ssl_free to set the freed pointer to NULL, and then check it at the top of ssl_free to not use it if it is NULL.
That all said, given the proliferation of the call sites for this, and the fact that no one currently checks the return code of the BIO_set_ssl call anywhere, this might be creeping out of scope for this PR. Maybe just let it be and open an issue to fix this separately along with all the call sites.
There was a problem hiding this comment.
Yes, that what I was trying to tell. In general, I concur that having broken BIO_set_ssl() is out of scope for this PR. Created [1] to track this.
[1] #31388
…X509_VERIFY_PARAM_set1_host()
| @@ -299,7 +299,6 @@ static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) | |||
| } | |||
There was a problem hiding this comment.
I guess you and Neil have just opened a can of worms: if I'm not mistaken, failing ssl_new() (due to failing OPENSSL_zalloc) after ssl_free would lead to BIO_SSL double-free, as b->ptr is not reset to NULL after OPENSSL_free call in ssl_free, and the latter would be called the second time in [1].
| BIO_set_next(b, bio); | ||
| } | ||
| BIO_set_init(b, 1); | ||
| bs->ssl = ssl; |
There was a problem hiding this comment.
The change looks innocuous enough (famous last words), however it's slowly creeping out of scope of the PR.
@mattcaswell might also want to take a look at this.
|
This pull request is ready to merge |
|
Merged - thanks @nhorman, @esyr, and @t8m for your approvals |
Add recommendation that TLS clients should useSSL_set_tlsext_host_name()for SNIand that this should be done jointly with using
{SSL,X509_VERIFY_PARAM}_{set1,add1}_host().On this occasion fix nits and omissions in the respective
.podfiles.Doc changes moved to #29150.Fixmeanwhile superseded by fix OSSL_parse_url userinfo scan to respect authority boundary #30319OSSL_parse_url()going too far when scanning for '@' to detect the end of theuserinfocomponent.,going astray when an
@symbol occurs after thehostcomponent, for instance in thequerycomponent.Fix
OSSL_parse_url()to correctly parse scheme (where only certain chars are allowed)Make sure that
app_http_tls_cb()callsSSL_set_tlsext_host_name()for setting the SNI only if a server name (rather than an IP address) is given.Also fix the server name being set in the SNI: it must always be the server actually connecting to,
while for the CMP CLI app so far this is wrongly tied to the
-tls_hostoption.Add to
OSSL_HTTP_REQ_CTX_nbiosupport for partial content-type string matchingExtend related doc, e.g., of
SSL_set_tlsext_host_name()andOSSL_HTTP_REQ_CTX_set_expected().Checklist