TLS socket fileevent write handler not called on negotiation failure
Brought to you by:
apnadkarni
In wish:
proc pargs {args} {puts [join $args ,]}
set so [twapi::tls_socket -async expired.badssl.com 443; fileevent $so writable [list pargs $so]
The above TLS negotiation fails - expire cert. However the handler pargs is never invoked.
Anonymous
Preface
Thank you for bringing this annoying issue up into a small example.
This is probably due to the weakness of the stacked channel architecture in error cases.
I suppose, the same issues apply to TCLTLS.
It is probalbly a stacked channel issue and not a TWAPI issue.
Nevertheless, Ashok is in a good position to look after this.
If I can be of any help, please advice.
I may retry to trigger Andreas to look into this regarding stacked channels.
Expert time is a rare resource and we are all voluntears.
May I ask you to check, if you get the same results as I do.
I am working on TCL8.6.12 32bit on Windows 64.
I enter the examples into the console.
Example code
There is a bracket missing in the example. So, I re-spelled it like:
I can confirm, that the fileevent never fires, even after waiting for the socket timeout.
This is my typicall use-case of a socket. In consequence, all my programs will not work.
This is an issue for me and many others.
TWAPI 4.7.1
I have tried this with TWAPI 4.7.1, which has enhancements in this field.
Here is the result:
In TWAPI, the "-error" situation may probably be enhanced. At least, the error origins from TWAPI code. Here is the stack trace:
And I have thought, there is a guard against this error in TWAPI 4.7.1.
Get the error by a blocking read command
The only way I found to find the correct error message is a blocking read command:
The stack trace is highly reduced due to big binary blocks included.
IMHO it is easy to reproduce, so try it on your own ;-).
The timing is 300 ms:
Non blocking IO
The only way to avoid deadlocks is non-blocking I/O. Here is an example with non-blocking read:
The correct error message is returned.
Remark, that the "update" is required. Otherwise, we will run in a socket timeout after 52 seconds. I suppose, this also applies on currect connects.
Current work-arounds
Current work-arounds may be a periodic check for:
Here is the test code for the 2nd work around:
Thank you all,
Harald
Last edit: Harald Oehlmann 2022-06-20
Harald,
Let us tackle the problem with fileevent not firing first.
Did you type the commands into the wish shell or in a script? Please try running as a script, not typing into a shell. If you type into a shell, type the line
as a single line (the two commands separated by colon), not as two separate lines.
Do you see the event firing then?
BTW, my previous post does not imply there is no bug. It is more to narrow down the solution
Dear Ashok,
sorry, I was not notified about your post. I forgot to subscribe.
Here is the proposed test:
Yes, in this case, it works. So, the issue is, that the update should not be run jet.
Sorry, that was stupid and logic.
The important role of "update" got only clear to me after some experimentations.
Thanks also for the solution provided by private E-Mail. I will make tests today.
Thank you so much,
Harald
Preface
Thank you for the enhanced version of tls.tcl.
Please allow me to repeat the tests here for this use-case.
iocp was active and it was renamed to socket.
Sorry, I forgot this detail.
In addition, twapi socket is registered to the http package.
autoproxy ran, but probably did not do anything.
fileevent
Test, if the standard scripted fileevent still fires. The event queue did not run between socket and fileevent:
Test ok.
fileevent after update
In contrast to the former version, the fileevent now fires, even if the update ran.
Here is the code:
Remark that some time elapsed between the execution of the lines.
This did not work before and works now. The event fires -> fixed.
fconfigure -error
fconfigre -error reported a script error before, and not the real socket error.
So, lets try it again:
The error message is ok, but the command should not raise the error state.
We will see below, that this is critical for the http case.
Still an issue.
use case of http
Within the http package, the fileevent writable procedure tests fconfigure -error for the empty string.
To my analysis, the http package will fail in this case.
fconfigure -error should return the error without raising an error.
So, lets try with the http package with registered twapi socket TLS:
As supposed, the http package call runs into an error due to that fact.
use case of receiving first from server
I use long standing connection to a device (barcode scanner in my case), where the device may send at any time after the connect.
* a wirtable event is used after socket creation to cancel the connect timeout (not shown in example).
* a readable event is used to detect received data.
In the error case, this is tricky, as the write and read event should be called by the error case.
This is a great result and did probably not work with the old version, as the readable event would not have been executed after the update.
Result
Great improvement in fileevent and in the error text.
The "fconfigure -error" should not raise an error state
Thank you for all,
Harald
Last edit: Harald Oehlmann 2022-06-22
Thanks, Ashok, for sending the corrected version for the fconfigure -error issue.
I repeat all tests and only mention the so far failed tests.
fconfigure -error
fconfigre -error reported a script error before, and not the real socket error.
So, lets try it again:
-> correct, error returned without error level.
use case of http
Within the http package, the fileevent writable procedure tests fconfigure -error for the empty string.
Ok, now returns error without calling bg error.
So, lets try with the http package with registered twapi socket TLS:
So, the command throws now an error what is ok.
Result
All issues fixed, thank you for the great work !
You rock,
Harald
Harald,
I’ve uploaded the new tclkits. Thanks for your testing
/Ashok
From: bugs@twapi.p.re.sourceforge.net bugs@twapi.p.re.sourceforge.net On Behalf Of Harald Oehlmann
Sent: Wednesday, June 22, 2022 11:10 PM
To: apnadkarni@users.sourceforge.net
Subject: [twapi:bugs] #206 TLS socket fileevent write handler not called on negotiation failure
Thanks, Ashok, for sending the corrected version for the fconfigure -error issue.
I repeat all tests and only mention the so far failed tests.
fconfigure -error
fconfigre -error reported a script error before, and not the real socket error.
So, lets try it again:
% set so [twapi::tls_socket -async expired.badssl.com 443]
rc0
% catch {fconfigure $so -error} err derr
0
% set err
Das empfangene Zertifikat ist abgelaufen.
-> correct, error returned without error level.
use case of http
Within the http package, the fileevent writable procedure tests fconfigure -error for the empty string.
% proc writeevent {so args} {
# this is the original from http.tcl proc http::Connect
if {
[eof $so] ||
[set err [fconfigure $so -error]] ne ""
} {
puts "Read error: $err"
}
}
% set so [twapi::tls_socket -async expired.badssl.com 443];fconfigure $so -blocking 0;fileevent $so writable [list writeevent $so]
Read error: Das empfangene Zertifikat ist abgelaufen.
Ok, now returns error without calling bg error.
So, lets try with the http package with registered twapi socket TLS:
% set h [http::geturl https://expired.badssl.com]
^A1 URL https://expired.badssl.com - token ::http::1
{Using rc4 for expired.badssl.com:443 - token ::http::1} {}
{WARNING - if testing, pay special attention to this case (GJ) which is seldom executed - token ::http::1}
{Closing socket rc4 (no connection info)}
connect failed Das empfangene Zertifikat ist abgelaufen.
% catch {http::geturl https://expired.badssl.com} err derr
1
% set err
connect failed Das empfangene Zertifikat ist abgelaufen.
So, the command throws now an error what is ok.
Result
All issues fixed, thank you for the great work !
You rock,
Harald
[bugs:#206] https://sourceforge.net/p/twapi/bugs/206/ TLS socket fileevent write handler not called on negotiation failure
Status: open
Target Release: Unscheduled
Created: Sun Nov 14, 2021 08:31 AM UTC by Ashok P. Nadkarni
Last Updated: Tue Jun 21, 2022 07:07 PM UTC
Owner: nobody
In wish:
proc pargs {args} {puts [join $args ,]}
set so [twapi::tls_socket -async expired.badssl.com 443; fileevent $so writable [list pargs $so]
The above TLS negotiation fails - expire cert. However the handler pargs is never invoked.
Sent from sourceforge.net because apnadkarni@users.sourceforge.net apnadkarni@users.sourceforge.net is subscribed to https://sourceforge.net/p/twapi/bugs/
To unsubscribe from further messages, a project admin can change settings at https://sourceforge.net/p/twapi/admin/bugs/options. Or, if this is a mailing list, you can unsubscribe from the mailing list.
Related
Tickets:
#206Thank you, TWAPI release 4.7.2 fixes this. Thanks for making a real release for this issue.
Bug may be closed.
THanks for all,
Harald
Just as a side not for people, who may repeat this:
if a custom verify command is used, the error decission is on the command.
So, with the following configuration, the issue is not detected: