Skip to content

Comments

Fix SSL_pending() and SSL_has_pending() with DTLS#18868

Closed
mattcaswell wants to merge 3 commits intoopenssl:masterfrom
mattcaswell:fix-dtls-pending
Closed

Fix SSL_pending() and SSL_has_pending() with DTLS#18868
mattcaswell wants to merge 3 commits intoopenssl:masterfrom
mattcaswell:fix-dtls-pending

Conversation

@mattcaswell
Copy link
Member

If app data is received before a Finished message in DTLS then we buffer
it to return later. The function SSL_pending() is supposed to tell you
how much processed app data we have already buffered, and SSL_has_pending()
is supposed to tell you if we have any data buffered (whether processed or
not, and whether app data or not).

Neither SSL_pending() or SSL_has_pending() were taking account of this
DTLS specific app data buffer.

@mattcaswell mattcaswell added branch: master Applies to master branch approval: review pending This pull request needs review by a committer branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL) approval: otc review pending branch: 3.0 Applies to openssl-3.0 branch labels Jul 25, 2022
@mattcaswell
Copy link
Member Author

I wrote the test for this first while working on #18132. It was only after I had the test that I realised there was a bug in SSL_pending/SSL_has_pending

@t8m t8m added the triaged: bug The issue/pr is/fixes a bug label Jul 25, 2022
@t8m
Copy link
Member

t8m commented Jul 25, 2022

Does it matter that the data might be discarded later if the Finished message is completely lost or inconsistent?

@mattcaswell
Copy link
Member Author

Does it matter that the data might be discarded later if the Finished message is completely lost or inconsistent?

In that case the handshake is never completed so you will never be able to read this app data.

@mattcaswell
Copy link
Member Author

Ping for second review?

if (SSL3_RECORD_get_type(&s->rlayer.rrec[i])
!= SSL3_RT_APPLICATION_DATA)
return 0;
return num;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, er, what? Isn't this supposed to signal an error? How does a value != 0 do that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No - this should not be an error. The return value represents the amount of application data that is buffered and available to read.

With DTLS there are 2 places application data might be buffered - either in the buffered_app_data queue - or in the rrec array. The rrec array could contain records that aren't app data. If that's the case then we ignore the data there. In that case we should return the amount of data we found in buffered_app_data.

Previously it was ok to just return 0 if we hit an rrec array entry that wasn't app data. All the rrec entries are guaranteed to be of the same type. So, if that type isn't app data, then we have 0 bytes of app data. Now that we're additionally checking buffered_app_data that is no longer the case.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manpage simply says "returns the number of buffered and processed application data bytes that are pending and are available for immediate read". There is no defined error code.

If I understand this code correctly, it's not that this is an error case anyway, but presumably that SSL3_RT_APPLICATION_DATA records can't appear in rrec after records of other types, thus the loop can be terminated in this case. (?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SSL3_RT_APPLICATION_DATA records can't appear in rrec after records of other types, thus the loop can be terminated in this case.

Yes - exactly. Its not an error case

Copy link
Member

@hlandau hlandau left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one typo, otherwise looks good.

if (SSL3_RECORD_get_type(&s->rlayer.rrec[i])
!= SSL3_RT_APPLICATION_DATA)
return 0;
return num;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manpage simply says "returns the number of buffered and processed application data bytes that are pending and are available for immediate read". There is no defined error code.

If I understand this code correctly, it's not that this is an error case anyway, but presumably that SSL3_RT_APPLICATION_DATA records can't appear in rrec after records of other types, thus the loop can be terminated in this case. (?)

If app data is received before a Finished message in DTLS then we buffer
it to return later. The function SSL_pending() is supposed to tell you
how much processed app data we have already buffered, and SSL_has_pending()
is supposed to tell you if we have any data buffered (whether processed or
not, and whether app data or not).

Neither SSL_pending() or SSL_has_pending() were taking account of this
DTLS specific app data buffer.
If the first app data record arrives before the Finished message we should
be able to buffer it and move on to the Finished message.
@mattcaswell
Copy link
Member Author

Typo fixed and rebased due to the SSL Object refactor

@hlandau hlandau added approval: done This pull request has the required number of approvals and removed approval: review pending This pull request needs review by a committer labels Jul 29, 2022
@openssl-machine openssl-machine added approval: ready to merge The 24 hour grace period has passed, ready to merge and removed approval: done This pull request has the required number of approvals labels Jul 30, 2022
@openssl-machine
Copy link
Collaborator

This pull request is ready to merge

openssl-machine pushed a commit that referenced this pull request Aug 1, 2022
If app data is received before a Finished message in DTLS then we buffer
it to return later. The function SSL_pending() is supposed to tell you
how much processed app data we have already buffered, and SSL_has_pending()
is supposed to tell you if we have any data buffered (whether processed or
not, and whether app data or not).

Neither SSL_pending() or SSL_has_pending() were taking account of this
DTLS specific app data buffer.

Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Hugo Landau <[email protected]>
(Merged from #18868)
openssl-machine pushed a commit that referenced this pull request Aug 1, 2022
If the first app data record arrives before the Finished message we should
be able to buffer it and move on to the Finished message.

Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Hugo Landau <[email protected]>
(Merged from #18868)
@hlandau
Copy link
Member

hlandau commented Aug 1, 2022

Merged to master. Thank you.

This does not cherry-pick cleanly to 3.0 or 1.1.1, will need another PR.

JeffroMF pushed a commit to JeffroMF/openssl.1.55555 that referenced this pull request Aug 5, 2022
If app data is received before a Finished message in DTLS then we buffer
it to return later. The function SSL_pending() is supposed to tell you
how much processed app data we have already buffered, and SSL_has_pending()
is supposed to tell you if we have any data buffered (whether processed or
not, and whether app data or not).

Neither SSL_pending() or SSL_has_pending() were taking account of this
DTLS specific app data buffer.

Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Hugo Landau <[email protected]>
(Merged from openssl/openssl#18868)
JeffroMF pushed a commit to JeffroMF/openssl.1.55555 that referenced this pull request Aug 5, 2022
If the first app data record arrives before the Finished message we should
be able to buffer it and move on to the Finished message.

Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Hugo Landau <[email protected]>
(Merged from openssl/openssl#18868)
@mattcaswell
Copy link
Member Author

Merged to master. Thank you.

This does not cherry-pick cleanly to 3.0 or 1.1.1, will need another PR.

3.0 backport in #18975. 1.1.1 backport in #18976.

Closing this one.

sftcd pushed a commit to sftcd/openssl that referenced this pull request Sep 24, 2022
If app data is received before a Finished message in DTLS then we buffer
it to return later. The function SSL_pending() is supposed to tell you
how much processed app data we have already buffered, and SSL_has_pending()
is supposed to tell you if we have any data buffered (whether processed or
not, and whether app data or not).

Neither SSL_pending() or SSL_has_pending() were taking account of this
DTLS specific app data buffer.

Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Hugo Landau <[email protected]>
(Merged from openssl#18868)
sftcd pushed a commit to sftcd/openssl that referenced this pull request Sep 24, 2022
If the first app data record arrives before the Finished message we should
be able to buffer it and move on to the Finished message.

Reviewed-by: Tomas Mraz <[email protected]>
Reviewed-by: Hugo Landau <[email protected]>
(Merged from openssl#18868)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: ready to merge The 24 hour grace period has passed, ready to merge branch: master Applies to master branch branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL) branch: 3.0 Applies to openssl-3.0 branch triaged: bug The issue/pr is/fixes a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants